*leetcode刷题_(剑指offer_滑动窗口)_57_和为s的连续数列/和为s的两个数字

面试题57. 和为s的两个数字

输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[2,7] 或者 [7,2]
示例 2:

输入:nums = [10,26,30,31,47,60], target = 40
输出:[10,30] 或者 [30,10]

解答:
最开始的思路 从头开始做两层遍历,一旦发现即return。
时间复杂度为O(n^2) TLE

优化:
观察数组,如果当数字小于最小值就不存在了;当数字大于最大时依然有可能存在。
1 设置左右边界点,相加和看是否大于target。
2 大于时 r-=1, 小于时l+=1,等于时返回数组即可。
时间复杂度:O(n)

可能存在的优化:针对中间数字,可以设置二分查找确定右边界。
时间复杂度O(n)+O(log n) 还是O(n),但是针对特殊情况会有更好的效果。

代码:

import bisect
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        if nums[0]>=target:
            return []
        r = bisect.bisect_left(nums,target)-1
        l = 0
        while l<r:
            if nums[l]+nums[r] == target:
                return [nums[l],nums[r]]
            elif nums[l]+nums[r]>target:
                r-=1
            else:
                l+=1
        return []

关注点:
滑动窗口的滑动条件变化。根据现在值的大小变化确定滑动的节奏。

面试题57 - II. 和为s的连续正数序列

输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。

序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。

示例 1:

输入:target = 9
输出:[[2,3,4],[4,5]]
示例 2:

输入:target = 15
输出:[[1,2,3,4,5],[4,5,6],[7,8]]

限制:

1 <= target <= 10^5

解答:
1 观察发现数组出现的方式 一般是中间值左右分布。
2 右分布只有一种情况 因为再往右肯定更大。
3 左分布存在多种情况,可以在左边做滑动窗口,起点均为中值,如果小于target,则l-=1,如果大于target,则r-=1。满足条件l<=r, l>=1。
4 最后结果没问题,但是题中需要返回从小到大的分布。可以在sorted一次或者生成时即进行排列。

优化1
滑动窗口均从1开始,小于时则 r+=1 , 大于时则 l+=1.
边界l <=mid 即可, 满足从小到大排列。

优化2:
以上每一步需要从新生成数组进行计算,使用了额外的空间(事实上都需要添加数组到res,对比也算不上额外空间)以及算力(每次sum数组)。
可以改为cur_sum,r+=1时,加上新的值; l+=1时,提前减去旧的值。减少了sum的时间。

代码:

class Solution:###improved!!!!!!!!
    def findContinuousSequence(self, target: int):
        mid = target // 2
        res = []
        l = 1
        r = 1
        cur_sum = 1
        while l <= r and l <= mid:
            #print(l,r,cur_sum)
            if cur_sum == target:
                res.append([i for i in range(l,r+1)])
                cur_sum -= l
                l += 1

            elif cur_sum < target:

                r += 1
                cur_sum += r
            else:
                cur_sum -= l
                l += 1
        return res

总结:
滑动窗口的使用:
1 明确需求: 一般对 排序或者存在规律的数组使用(因为在滑动时 存在规律)
2 明确滑动时的变化:针对滑动的变化,作出不同的判定。
3 终止点:一般是窗口左右相遇 或者达到题意条件

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值