Leetcode Hot100之双指针

1. 移动零

  • 题目描述
    给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
    请注意 ,必须在不复制数组的情况下原地对数组进行操作。

  • 解题思路
    双指针遍历一遍即可解决:

    1. 我们定义了两个指针 i 和 j,它们都初始化为 0。然后,我们开始遍历列表。j 指针用于遍历整个列表,而 i 指针用于跟踪下一个非零元素应该放置的位置。
    2. 在第一遍循环结束后,所有非零元素都已经按原始顺序排列在列表的前面。在第二遍循环中,我们将列表中剩余的所有位置都赋值为 0。
    3. 时间复杂度: O(n) 空间复杂度: O(1)
  • 代码

    python 复制代码
    class Solution:
        def moveZeroes(self, nums: List[int]) -> None:
            """
            Do not return anything, modify nums in-place instead.
            """
            n = len(nums)
            if n == 0:
                return
            i = j = 0
            while j < n:
                if nums[j] != 0:
                    nums[i] = nums[j]
                    i += 1
                j += 1
            while i < n:
                nums[i] = 0
                i += 1

2. 盛最多水的容器

  • 题目描述

    给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, heighti) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。返回容器可以储存的最大水量。

    说明:你不能倾斜容器。

  • 解题思路

    1. 我们初始化两个指针 l 和 r,分别指向数组的开始和结束位置,当前水容量是(r - l) * min(heightsl, heightsr);
    2. 我们每次移动高度较小的指针,因为移动高度较大的指针不会增加水容量,只会减少水容量;比如如果heightsl 较小,那么无论 r 指针如何移动,都不可能得到更大的水容量,因此我们选择移动 l 指针。
    3. 时间复杂度:O(n) 空间复杂度:O(1)
  • 代码

    python 复制代码
    class Solution:
        def maxArea(self, height: List[int]) -> int:
            n = len(height)
            if n == 0:
                return 0
            l, r = 0, n - 1
            res = 0
            while l < r:
                res = max(res, (r - l) * min(height[l], height[r]))
                if height[l] < height[r]:
                    l += 1
                else:
                    r -= 1
            return res

3. 三数之和

  • 题目描述

    给你一个整数数组 nums ,判断是否存在三元组 nums\[i, numsj, numsk] 满足 i != j、i != k 且 j != k ,同时还满足 numsi + numsj + numsk == 0 。请

    你返回所有和为 0 且不重复的三元组。

    注意:答案中不可以包含重复的三元组。

  • 解题思路

    1. 求解两数之和可以使用双指针,但此时需要先对数组进行排序,然后使用双指针分别指向数组的头部和尾部,然后根据两个指针指向的元素之和与目标值的大小关系来移动指针。
    2. 那么3数之和就可以在外面加上一层循环,循环内部使用双指针求两数之和等于traget - numsi
    3. 在此过程中注意去重,包括外循环的去重和内循环的去重,如果当前元素和前一个元素相同,那么直接跳过。
    4. 时间复杂度:O(n^2) 空间复杂度:O(1)
  • 代码

    python 复制代码
    class Solution:
        def threeSum(self, nums: List[int]) -> List[List[int]]:
            n = len(nums)
            if n < 3:
                return []
            nums.sort()
            res = []
            for i in range(n-2):
                if i > 0 and nums[i] == nums[i - 1]:
                    continue
                l, r = i + 1, n - 1
                while l < r:
                    if nums[l] + nums[r] == 0 - nums[i]:
                        res.append([nums[i], nums[l], nums[r]])
                        l += 1
                        r -= 1
                        while l < r and nums[l] == nums[l - 1]:
                                l += 1
                        while l < r and nums[r] == nums[r + 1]:
                                r -= 1
                    elif nums[l] + nums[r] > 0 - nums[i]:
                        r -= 1
                    else:
                        l += 1
            return res

4. 接雨水

  • 题目描述

    给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

  • 解题思路

    1. 总的接雨水量等于每个柱子上的接雨水量之和,每个柱子上的接雨水量等于左边最高柱子和右边最高柱子中较小的那个减去当前柱子的高度。
    2. 因此通过动态规划可以求解左边最高柱子和右边最高柱子,然后求解每个柱子上的接雨水量。
    3. 时间复杂度:O(n) 空间复杂度:O(n)
  • 代码

    python 复制代码
    class Solution:
        def trap(self, height: List[int]) -> int:
            n = len(height)
            if n < 3:
                return 0
            left_max = [0] * n
            right_max = [0] * n
            for i in range(1, n):
                left_max[i] = max(left_max[i - 1], height[i - 1])
            for i in range(n - 2, -1, -1):
                right_max[i] = max(right_max[i + 1], height[i + 1])
            res = 0
            for i in range(n):
                if min(left_max[i], right_max[i]) > height[i]:
                    res += min(left_max[i], right_max[i]) - height[i]
            return res

5. 总结

双指针在以下场景可以发挥作用:1. 原地对数组进行一些数据交换的操作,比如移动零、翻转数组、旋转数组等操作;2. 排序数组中求两数的目标和,比如三数之和题目;3.序列搜索中,从left = 0和right = n-1分别出发,可通过一定的规律先后移动left和right,最后再O(n)时间内完成搜索。

相关推荐
1000世界小札9 小时前
《大话数据结构》第9章精读:归并排序与快速排序完整 C++ 实现
数据结构·c++·算法
2601_9561219712 小时前
背包基础篇(01、完全、分组、多重、混合)
c++·算法·动态规划
kobe_OKOK_12 小时前
DRF接口幂等操作
python·django
廿士13 小时前
python脚本使用相关
python
兴通物联科技13 小时前
SMT PCB 微小 DataMatrix 码扫不动问题分析 兴通 XT8601B 600 万像素工业读码器落地实践
大数据·人工智能·单片机·嵌入式硬件·算法·计算机视觉
青 春 记 忆13 小时前
零基础入门python19:Flask账本第一步——应用工厂、蓝图和健康检查
python·flask·后端开发
朦胧之13 小时前
Python 后端核心知识
python
denggun1234514 小时前
yield
前端·数据库·python
zx_7414848115 小时前
【Python 入门】面向对象基础:类、对象、成员变量与构造方法
开发语言·python