双指针问题

题目详细说明请自行到题库 - 力扣 (LeetCode)搜寻题号

1. 两数和

利用数组的有序,使用两个指针,一个为l,指向数组开头,一个为r,指向数组结尾;

和大于target时右边指针左移一个,获得比当前小的下一个和;

和小于target时左边指针右移一个,获得比当前大的下一个和;

循环条件为 l < r ,循环结束时就把所有的和都遍历了一遍, 时间复杂度为O(n);

167. Two Sum II - Input array is sorted

给定一个已按照升序排列的有序数组,找到两个数使得它们相加之和等于目标数。

函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2

class Solution:

    def twoSum(self, numbers, target):

        """

        :type numbers: List[int]

        :type target: int

        :rtype: List[int]

        """

        if len(numbers) < 2:

            return None

        l = 0

        r = len(numbers) - 1

        while l < r:

            s = numbers[l] + numbers[r]

            if s == target:

                #这道题下标从1开始的

                return [l + 1, r + 1]

            elif s < target:

                l += 1

            else:

                r -= 1

        return None

2. 扩展, 三数和

怎么把三数和转化为两数和呢?

我们可以遍历一次数组取每一个 nums[i] ,使三数和等于target相当于

在 nums[ i + 1 : ] 中找两个下标 l , r 使 nums[l] + nums[r] == target - nums[i]

这样就转化为两数和问题, 时间复杂度为 O(n²) , 注意去除重复答案

15. 3Sum

给定一个包含 n 个整数的数组nums,判断nums中是否存在三个元素 a,b,c ,使得a + b + c = 0 ?找出所有满足条件且不重复的三元组。

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

class Solution:

    def threeSum(self, nums):

        """

        :type nums: List[int]

        :rtype: List[List[int]]

        """

        #先排序

        nums.sort()

        res = []

        #current标记用于去重

        current = '-1'

        for i, value in enumerate(nums):

            if current == value:

                continue

            current = value

            l = i + 1

            r = len(nums) - 1

            while l < r:

                s = nums[i] + nums[l] + nums[r]

                if s == 0:

                    res.append([nums[i],nums[l],nums[r]])

                    l += 1

                    r -= 1

                    #去掉重复l

                    while l < r and nums[l] == nums[l - 1]:

                        l += 1

                    #去掉重复r

                    while r > l and nums[r] == nums[r + 1]:

                        r -= 1

                elif s < 0:

                    l += 1

                else:

                    r -= 1

        return res

还有一道4数和的题目, 思路是一样的, 再加一层循环, 时间复杂度为 O(n³)

3. 盛水最多容器

用双指针做,取2个指针,最左 l 和最右 r , 计算两块板装的面积

当 l 的板比 r 的高时 , r -= 1

当 r 的板比 l 的高时,  l += 1

双指针遍历相当于求每个宽度下的最大面积, 从中取一个最大值, 时间复杂度为O(n)

11. Container With Most Water

给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i,ai) 。在坐标内画 n 条垂直线,垂直线 i的两个端点分别为 (i,ai) 和 (i, 0)。找出其中的两条线,使得它们与x轴共同构成的容器可以容纳最多的水。

说明:你不能倾斜容器,且n的值至少为 2。

class Solution:

    def maxArea(self, height):

        """

        :type height: List[int]

        :rtype: int

        """

        res = 0

        l, r = 0, len(height) - 1

        while l < r:

            #求面积, 等于宽度乘以 l , r 中高度比较小的那个值

            res = max(res, (r - l) * min(height[l],height[r]))

            if height[l] > height[r]:

                r -= 1

            else:

                l += 1

        return res

4. 搜寻二维矩阵

使用两层循环搜索时间复杂度为O(n²) , 而且没用到题目给的有序的条件

我们可以假设右上角的值 matrix[x][y] 为初始值, 其中 x = 0 , y = n

当matrix[x][y]  < target时,  说明 matrix[x] 这一行上的值都比 target 小, x += 1

当matrix[x][y] > target时, 说明matrix在y这一列上的值都比target 大, y -= 1

找到target时返回True, 超出矩阵后返回False  时间复杂度为 O(m + n)

240. Search a 2D Matrix II

编写一个高效的算法来搜索n矩阵 matrix 中的一个目标值 target。该矩阵具有以下特性:

每行的元素从左到右升序排列。

每列的元素从上到下升序排列。

class Solution:

    def searchMatrix(self, matrix, target):

        """

        :type matrix: List[List[int]]

        :type target: int

        :rtype: bool

        """

        #判断矩阵有没有值

        x = len(matrix)

        if x == 0:

            return False

        y = len(matrix[0])

        if y == 0:

            return False

        #y取最后一列的下标

        y -= 1

        i = 0

        while i < x and y >= 0:

            if matrix[i][y] < target:

                i += 1

            elif matrix[i][y] > target:

                y -= 1

            else:

                return True

        return False

你可能感兴趣的:(双指针问题)