leetcode (基于python)每日一题+ 15-18题解(双指针总结)

每日一题

2609. 最长平衡子字符串
给你一个仅由 0 和 1 组成的二进制字符串 s 。  
如果子字符串中 所有的 0 都在 1 之前 
且其中 0 的数量等于 1 的数量,
则认为 s 的
这个子字符串是平衡子字符串。请注意,空子字符串也视作平衡子字符串。 
返回  s 中最长的平衡子字符串长度。
子字符串是字符串中的一个连续字符序列。

题解:暴力枚举法,直接数01 0011 000111 00001111 等数量

本质就是数出0和1 的数量,判断是不是连着的,如果不是计数置零,连着的数出来,则平衡串为小的数量的2倍,(多的肯定够配出平衡串,但是少的不行,故需要以少的为基准)

class Solution:
    def findTheLongestBalancedSubstring(self, s) :
        res = 0
        zero, one = 0, 0
        i = 0
        n = len(s)
        if n == 0:
            return 0
        while i <= n - 1:
            while i <= n - 1 and s[i] == '0':
                i += 1
                zero += 1
            while i <= n - 1 and s[i] == '1':
                i += 1
                one += 1
            if one >= zero:
                res = max(res, 2 * zero)
            else:
                res = max(res, 2 * one)
            one = 0
            zero = 0
        return res
15.三数之和
18. 四数之和
给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。
请你找出并返回满足下述全部条件且不重复的四元组 
[nums[a], nums[b], nums[c], nums[d]]
 (若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < n
a、b、c 和 d 互不相同
nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。
示例 1:
输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
示例 2:
输入:nums = [2,2,2,2,2], target = 8
输出:[[2,2,2,2]]

15 与 18可以说是一模一样,这里以18为例(15 题解代码也赋上)

题解:由于是遍历类型,如果暴力枚举,需要遍历四次,并且会有很多的重复操作,故可以采用哈希表双指针优化,可以大大减少不必要的计算

就不写具体题解了,我把代码每行注释都给表明了,基本完全小白也能看懂了,现对遍历类型百试不爽的双指针简单总结一下

双指针总结:

1.对待操作序列排序(可以是数组元素,也可为字典索引(key,value均可反正能查到就行))

2.指针赋值 (左右指针,分别置于待处理序列俩端) 注意:是待处理序列,需要辨析,如果对初始序列切片了,辨清看是在哪里使用双指针,18题中就有例子

3.大条件  while left<right:  (我一般都打  l ,r 大家注意辨析,就是个人习惯问题)

4.移动条件,这里就与事先排序有关了,知道大小顺序,可以根据自己要求,看是怎么移动指针

# 15
class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        nums.sort()  # 首先对数组进行排序
        result = []  # 初始化结果列表
        for i in range(len(nums) - 2):  # 遍历数组,注意我们只需要遍历到倒数第三个元素,要求为三元组,后面俩个没有必要了,构不成三元组了
            if i > 0 and nums[i] == nums[i - 1]:  # 如果当前元素和前一个元素相同,我们就跳过,因为我们不想有重复的解
                continue
            l, r = i + 1, len(nums) - 1  # 初始化左右指针,它们分别指向当前元素的下一个元素和数组的最后一个元素
            while l < r:  # 当左指针小于右指针时,我们继续寻找解
                s = nums[i] + nums[l] + nums[r]  # 计算当前三个元素的和
                if s < 0:  # 如果和小于0,我们就将左指针向右移动,以增大和
                    l += 1
                elif s > 0:  # 如果和大于0,我们就将右指针向左移动,以减小和
                    r -= 1
                else:  # 如果和等于0,我们就找到了一个解
                    result.append([nums[i], nums[l], nums[r]])  # 将解添加到结果列表中
                    while l < r and nums[l] == nums[l + 1]:  # 如果左指针的下一个元素和当前元素相同,我们就将左指针向右移动,以避免重复的解
                        l += 1
                    while l < r and nums[r] == nums[r - 1]:  # 如果右指针的前一个元素和当前元素相同,我们就将右指针向左移动,以避免重复的解
                        r -= 1
                    l += 1  # 找到一个解后,我们将左右指针都移动,以寻找下一个解
                    r -= 1
        return result
# 18
# 优化
class Solution(object):
    def fourSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[List[int]]
        """
        result = set()
        nums.sort()  # 凡是考虑用双指针,先将其索引或者值排序更好,后续更方便判断指针以东方走向

        for i in range(len(nums) - 3):  # 四元组 到达长度-3时就可,后面就剩三个不够构成
            for j in range(i+1,len(nums) - 2):  # 确定第二个元素,相当于,四元组已知了第一个元素,只要找三那个元素就可,长度-2原因同上
                new = nums[i] + nums[j]  # 此时确定下的俩数和,也方便后续代码可读性
                # 定义双指针,在定了俩个元素情况下
                l = j + 1  # 此时相当于将原数组划分,从j+1到完
                r = len(nums) - 1
                while r > l:
                    if new + nums[l] + nums[r] == target:
                        if (nums[i], nums[j], nums[l], nums[r]) not in result:  # 注意链表不可哈希,即不可集合操作,需要改为元组
                            result.add((nums[i], nums[j], nums[l], nums[r]))
                    if new + nums[l] + nums[r] < target:
                        l += 1
                    # elif new + nums[l] + nums[r] > target:
                    #     r -= 1
                    # else :
                    #     break
                    else :
                        r-=1
            return list(result)
16. 最接近的三数之和
给你一个长度为 n 的整数数组 nums 和 一个目标值 target。
请你从 nums 中选出三个整数,使它们的和与 target 最接近。
返回这三个数的和。
假定每组输入只存在恰好一个解。
示例 1:
输入:nums = [-1,2,1,-4], target = 1
输出:2
解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。
示例 2:
输入:nums = [0,0,0], target = 1
输出:0

题解:与三数四数求和没啥区别,只是将一个确定的 target 变为一个范围加一个判断条件就可

双指针,在0和倒数第三个元素(后面俩个元素不够三元组了,注意,数组下标从0开始)

记录每次的三元组值计算与target的差值(接近程度),与一个无穷大与target差值(此时肯定为最大的,好初始更新)进行比较,然后将小的保存,不断更新最小值,即答案最接近的数

class Solution(object):
    def threeSumClosest(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        nums.sort()
        closest_sum = float('inf')  # 初始化最接近的和为无穷大
        for i in range(len(nums) - 2):
            l, r = i + 1, len(nums) - 1
            while l < r:
                s = nums[i] + nums[l] + nums[r]
                if abs(s - target) < abs(closest_sum - target):  # 如果当前和更接近目标值,就更新最接近的和
                    closest_sum = s
                if s < target:
                    l += 1
                elif s > target:
                    r -= 1
                else:  # 如果和等于目标值,就直接返回
                    return target
        return closest_sum  # 返回最接近的和
17. 电话号码的字母组合
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

题解:建立数字与字母的字典,然后一层一层遍历,这里完全可直接返会temp 只是为了满足题目要求返回【】,故用temp 转化一下,先遍历数组,取出单个数子,将其对应的字母遍历保存,然后第二个数子,取出字母,在遍历第一个数字字母的循环下,全都组合一遍,存入链表(这里第一个数子与第二个数字谁先遍历无所谓,只要最后添加的时候调好位置就行)

class Solution(object):
    def letterCombinations(self, digits):
        """
        :type digits: str
        :rtype: List[str]
        """
        digits_dict={
            1:'1',2:'abc',3:'def',
            4:"ghi",5:'jkl',6:'mno',
            7:'pqrs',8:'tuv',9:'wxyz',
                     0:'0'
        }
        if not digits:
            return []
        result=[""]
        for x in digits:
            temp=[]
            for ch in digits_dict[int(x)]:
                for str in result:
                    temp.append(str + ch)
            result=temp
        return result

  • 10
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

01_

感谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值