剑指 Offer 57. 和为s的两个数字、剑指 Offer 57 - II. 和为s的连续正数序列

45 篇文章 1 订阅
5 篇文章 0 订阅

 1.题:输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。

  • #注意是递增数列 双指针法 往中间走,i指向第一个元素,j指向最后一个元素。

                如果这两个元素的和等于target,则输出这两个元素
                如果比target大,让j往前移动一个
                如果比target小,让i往后移动一个

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        i,j=0,len(nums)-1
        while i<j:
            if nums[i]+nums[j]<target:
                i+=1
            elif nums[i]+nums[j]>target:
                j-=1
            else:
                return [nums[i],nums[j]]
        return []
  • #哈希表 妙用 直接根据键访问值

        遍历数组元素,在哈希表中查找sum-array[i],若是没找到,将此信息计入哈希表 ,找到便返回

class Solution:
    def FindNumbersWithSum(self , array: List[int], sum: int) -> List[int]:
        n=len(array)
        dic={}
        for i in range(n):
            tmp=sum-array[i]
            if tmp not in dic:
                dic[array[i]]=i#键值对应下标(无实际意义什么都行)
            else:
                return [tmp,array[i]]#找到就返回这个
        return []#一直没找到

2.题:输入一个正整数 target ,输出所有和为 target 的连续正整数序列

  •  #双指针 滑动窗口左右边界 每轮判断滑动窗口内元素和s=i+...+j与目标值target的大小关系

                若大于target,则移动左边界i;
                若小于target,则移动右边界j 以增大窗口内包括的元素。

class Solution:
    def findContinuousSequence(self, target: int) -> List[List[int]]:
        i,j,s,res=1,2,3,[]
        while i<j:
            if s>target:
                s-=i
                i+=1
            elif s<target:
                j+=1
                s+=j
            else:
                res.append(list(range(i,int(j)+1)))#滑动窗口向左滑动 继续寻找
                s -= i
                i += 1
        return res
  •  #巧妙 解方程

        左边界i和右边界j target= ((i+j)/2)×(j−i+1) 遍历确定左边界i时 通过target和i解出j 看j是不是整数 且j要大于i

class Solution:
    def findContinuousSequence(self, target: int) -> List[List[int]]:
        i,j,res=1,2,[]
        while i <j:
            j = (-1 + (1 + 4 * (2 * target + i * i - i)) ** 0.5) / 2
            if i < j and j == int(j):#判断解j是否满足条件
                res.append(list(range(i,int(j)+1)))
            i+=1
        return res

3.题:给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 

#非单调数列 不能保证左右指针移动带来有效改变(一定变大或变小)!子数组就是连续的

  •  #前缀和加哈希表(‘子数组的和’相关问题考虑前缀和)

        在遍历的过程中构建前缀和sum
        找sum- k在前面的数组中是否存在 即判断 当前位置前缀和减去之前某一位的前缀和等于目标值k 

class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        dic,res,sum={},0,0
        dic[0]=1#或者直接 dic={0:1}
        for i in range(len(nums)):
            sum+= nums[i]#前缀和
            tmp=sum-k#比目标值k多出多少
            if tmp in dic:#判断多出的值tmp能不能很好的去掉
                res+=dic[tmp]#有多少种方式的和等于tmp
            dic[sum]=dic.get(sum,0)+1#记录 前缀和 出现次数
        return res
  •  #暴力枚举 枚举考虑以i结尾的子数组 是否和为k
class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        n,res=len(nums),0
        for i in range(n):
            sum=0
            for j in range(i,-1,-1):#考虑0-i位置作为子数组的开头
                sum+=nums[j]
                if sum==k:
                    res+=1
        return res

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值