两数之和,三数之和,若干数之和

一、两数之和(LeetCode1)
二分思路求解i,j

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        # nums.sort()
        an=[]
        length=len(nums)
        for n in range(length):
            an.append([nums[n],n])
        an.sort()
        
        i,j=0,length-1
        while(i<j):
            if(an[i][0]+an[j][0]<target):
                i+=1
            elif(an[i][0]+an[j][0]>target):
                j-=1
            else:
                return [an[i][1],an[j][1]]
        return []

二、三数之和(LeetCode 15)
记得将nums排序再进行a,b,c判断。固定a,使用二分定位b,c。

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        n=len(nums)
        res=[]
        nums.sort()
        for i in range(n):
            if(nums[i]>0):
                return res
            if(i>0 and nums[i]==nums[i-1]):
                continue
            L,R=i+1,n-1
            while(L<R):
                if(nums[L]+nums[R]+nums[i]==0):
                    res.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
                elif(nums[L]+nums[R]+nums[i]>0):
                    R-=1
                else:
                    L+=1
        return res

三、和为K的子数组(LeetCode 560)
依图二面编程题
保存前缀和->差分法

class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
      cnt, n =  0, len(nums)
      pre = [0] * (n + 1)
      for i in range(1, n + 1):
          pre[i] = pre[i - 1] + nums[i - 1]
      for i in range(1, n + 1):
          for j in range(i, n + 1):
              if (pre[j] - pre[i - 1] == k): cnt += 1
      return cnt

使用hashmap简化时间复杂度.
使用collections记录已经存在的和的数量。当前总和-k=字典里某个值。那么以当前节点为结尾结点,记录以当前结点作为尾结点的结点数量。
以下代码抄袭leetcode熊猫大神

class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        # num_times 存储某“前缀和”出现的次数,这里用collections.defaultdict来定义它
        # 如果某前缀不在此字典中,那么它对应的次数为0
        num_times = collections.defaultdict(int)
        num_times[0] = 1  # 先给定一个初始值,代表前缀和为0的出现了一次
        cur_sum = 0  # 记录到当前位置的前缀和
        res = 0
        for i in range(len(nums)):
            cur_sum += nums[i]  # 计算当前前缀和
            if cur_sum - k in num_times:  # 如果前缀和减去目标值k所得到的值在字典中出现,即当前位置前缀和减去之前某一位的前缀和等于目标值
                res += num_times[cur_sum - k]
            # 下面一句实际上对应两种情况,一种是某cur_sum之前出现过(直接在原来出现的次数上+1即可),
            # 另一种是某cur_sum没出现过(理论上应该设为1,但是因为此处用defaultdict存储,如果cur_sum这个key不存在将返回默认的int,也就是0)
            # 返回0加上1和直接将其置为1是一样的效果。所以这里统一用一句话包含上述两种情况
            num_times[cur_sum] += 1
        return res

根据熊猫描述,1248题和本题有异曲同工之妙。
统计优美子数组(LeetCode 1248)

class Solution:
    def numberOfSubarrays(self, nums, k):
        from collections import defaultdict
        odd_nums = defaultdict(int)  # 前缀和类问题重要是设定一个可供查找的表,想清楚存什么后面就好理解了
        odd_nums[0] = 1  # 给定一个初始状态,代表0个奇数的情况出现了1次
        cur_odd_num = 0  # 到当前位置有几个奇数
        res = 0
        for i in range(len(nums)):
            if nums[i] % 2 == 1:
                cur_odd_num += 1
            odd_nums[cur_odd_num] += 1
            if cur_odd_num - k in odd_nums:
                res += odd_nums[cur_odd_num - k]
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值