leetcode刷题之路(四)

leetcode15三数之和

算法思路:这道题我开始想到就是要固定一个数,然后要用双指针来做,但是两个指针的移动覆盖所有的数据,这样如何更新我没有想明白。

这是道好题

正确的解法应该是先将数组排序,遍历数组,固定一个数,再用双指针从这个数的右边开始遍历。如果将双指针从数组的起点和端点开始遍历,会得到很多重复的满足条件的组,因为考虑了重复的组别**。所以这里要能想到将双指针从这个数的右边开始遍历就会避免考虑重复的情况而且能够覆盖到所有的情况**,我画了一个简图解释一下。

在这里插入图片描述

从最底下的5开始看,我们先遍历5右边的,然后从加入4后,重新遍历4以后的情况。重复这样一直到1,我们发现所有的情况都覆盖到了,并且不会考虑重复的组

除此之外 算法还值得注意的地方在于:

  • 如果三个指针如果指向的当前元素与前一个元素相当,跳出本轮循环,检索下一个。
  • 固定的指针指向的数如果大于了0,停止,因为三个数之和肯定大于了0
class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        list = []
        if len(nums) < 3:
            return []
        nums.sort()
        for i in range(len(nums)):
            if nums[i] >0:
                break
            low = i+1
            high = len(nums)-1
            if i > 0 and nums[i] == nums[i-1]: #避免重复的组
                continue
            while(low < high):
                value = nums[i] + nums[low] + nums[high]
                if value == 0:
                    list.append([nums[i], nums[low], nums[high]])
                    low += 1
                    high -= 1
                    while(low < high and nums[low] == nums[low-1]): # 避免重复的组
                        low += 1
                    while(high > low and nums[high] == nums[high+1]): # 避免重复的组
                        high -= 1
                if value > 0:
                    high -= 1
                if value < 0:
                    low += 1
        return list

leectcode16最接近三数之和

算法思路:这道题和三数之和思路与很像,唯一的不同点就是要在遍历的过程中要记录和target最接近的三数之和,如何衡量接近,用绝对值就可以。

class Solution:
    def threeSumClosest(self, nums: List[int], target: int) -> int:
        length = len(nums)
        if length < 3:
            return nums
        count = 9223372036854775807
        nums.sort()
        for i in range(length-2):
            low = i+1
            high = length-1
            if i > 0 and nums[i] == nums[i-1]:
                i += 1
                continue
            while low < high:
                value = nums[i] + nums[low] + nums[high]
                if (abs(value - target) < abs(count - target)):
                    count = value
                if value == target:
                    return target
                else:
                    if value > target:
                        high -= 1
                    if value < target:
                        low += 1
        return count

leetcode18四数之和

算法思路:和三数之和基本是一样的,

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        length = len(nums)
        list = []
        if length < 4:
            return list
        nums.sort()
        for i in range(length-3):
            left = i+1
            if i > 0 and nums[i] == nums[i-1]: #这里要注意i > 0的条件
                i += 1
                continue
            for j in range(left, length-2):
                if j > left and nums[j] == nums[j-1]: # 同样这里要注意j > left的条件
                    j += 1
                    continue
                middle = j+1
                right = length - 1
                while(middle < right):
                    value = nums[i] + nums[j] +nums[middle] + nums[right]
                    if target == value:
                        list.append([nums[i], nums[j], nums[middle], nums[right]])
                        middle += 1
                        right -= 1
                        while(middle < right and nums[middle] == nums[middle-1]):
                            middle += 1
                        while(middle < right and nums[right] == nums[right +1]):
                            right -= 1
                    elif target < value:
                        right -= 1
                    else:
                        middle += 1
        return list

leetcode11乘最多水的容器

算法思路,如果能想到用双指针法从数组的两边开始检索,当两指针指向的矩形两边,移动较短的两边可能增加矩形的面积,而移动较长的边注定会减少矩形的面积。这道题就解决了

class Solution:
    def maxArea(self, height: List[int]) -> int:
        low = 0
        high = len(height) -1
        max_Area = 0
        while(low < high):
            # reauslt = height[low] if height[low] < height[high] else height[high]
            max_Area = max(max_Area, min(height[low],height[high])*(high-low))
            if height[low] < height[high]:
                low += 1
            else:
                high -= 1
        return max_Area

leetcode31下一个排列

这道题我真的要爆粗了,用评论中的一句话来说”就是这道题的每个字我都认识,连起来我就不懂了“。

我说下我理解的题意,所谓全排列就是要从从数组的右边往左边开始遍历找第一组 n u m s [ i ] &gt; n u m s [ i − 1 ] nums[i] &gt; nums[i-1] nums[i]>nums[i1]。找到之后就开始在这个位置往右边遍历,然后直到找到最小的大于 n u m s [ i − 1 ] nums[i-1] nums[i1]的数 n u m s [ j ] nums[j] nums[j](在我的code里面这个数是 n u m s [ i n d e x _ l o w ] nums\lbrack index\_low\rbrack nums[index_low]),交换 n u m s [ i − 1 ] nums[i-1] nums[i1] n u m s [ j ] nums[j] nums[j]。此时我们还要保证包括 n u m s [ i ] nums[i] nums[i] n u m s [ l e n g h t h − 1 ] nums[lenghth-1] nums[lenghth1]的元素按升序排列。

最后如果没有找到这一对数字说明整个序列已经按降序排列好了,直接反转就行。

class Solution:
    def nextPermutation(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        length = len(nums)
        flag = 0
        for i in range(length-1, 0, -1):
            if nums[i] > nums[i-1]:
                flag = 1
                index_low = i
                # 注意下面这个判断条件 中不要写成nums[index_low] >= nums[i-1]!!
                while(index_low < length and nums[index_low] > nums[i-1]):
                    index_low += 1
                tmp = nums[index_low-1]
                nums[index_low-1] = nums[i-1]
                nums[i-1] = tmp
                i_right = nums[i::]
                i_right.sort()
                for j in range(len(i_right)):
                    nums[i] = i_right[j]
                    i += 1
                break
        if flag == 0:
            nums.reverse()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值