剑指offer 41、42

41、和为S的连续正数序列在这里插入图片描述

考虑用滑动窗口,
知识补充:

1、什么是滑动窗口?
顾名思义,首先是一个窗口,既然是一个窗口,就需要用窗口的左边界i和右边界j来唯一表示一个窗口,其次,滑动代表,窗口始终从左往右移动,这也表明左边界i和右边界j始终会往后移动,而不会往左移动。
这里我用左闭右开区间来表示一个窗口。比如在这里插入图片描述
2、滑动窗口的操作

  • 扩大窗口,j += 1
  • 缩小窗口,i += 1
  • 算法步骤:
    – 初始化,i=1,j=1, 表示窗口大小为0
    – 如果窗口中值的和小于目标值sum, 表示需要扩大窗口,j += 1
    – 否则,如果狂口值和大于目标值sum,表示需要缩小窗口,i += 1
    – 否则,等于目标值,存结果,缩小窗口,继续进行步骤2,3,4

3、这里需要注意2个问题:

  • 什么时候窗口终止呢,这里窗口左边界走到sum的一半即可终止,因为题目要求至少包含2个数
  • 什么时候需要扩大窗口和缩小窗口?解释可看上述算法步骤。
# -*- coding:utf-8 -*-
class Solution:
    def FindContinuousSequence(self, tsum):
        # write code here
        l = 1
        r = 2
        sum = 3
        res = []
        while l < r:
            if sum>tsum:
                sum -= l
                l+=1
            else:
                if sum==tsum:
                    res.append([i for i in range(l,r+1)])
                r += 1
                sum +=r 
        return res

42、和为S的两个数字

在这里插入图片描述
刚开始看见题目第一反应就是用双指针,后来看见说要输出两个数的乘积最小的,这个时候就被题干迷惑了,初始化了一个二维数组,将每一对满足要求的数字添加到该二维数组中,可是越写感觉越不对劲,心里默默地想了一串数组,例如:[1,2,3,4,5,6,7,8]要求两数之和为9,按照我的双指针left指向第一个数,right指向最后一个数,会依次输出[1,8],[2,7],[3,6],[4,5]。很明显最小的就是输出的第一对,所以无需考虑题目中输出乘积最小的要求,碰见的第一对满足要求的,就是最小的!

思路:使用双指针,left指向数组第一个数,right指向最后一个数,初始化一个空列表result用来存放满足要求的两个数;
判断array[left]+array[right]与tsum的关系:若大于tsum,则将right指针左移;若小于tsum,则将left指针右移;若相等,则可以添加到result里,返回即可。
注意:相等添加完毕之后要使用break跳出循环,否则会出错,提示内存超过限制!

# -*- coding:utf-8 -*-
class Solution:
    def FindNumbersWithSum(self, array, tsum):
        # write code here
        result = []
        n = len(array)
        if array is None or n<=1:
            return result
        left = 0
        right = n -1
        while left<right:
            if array[left]+array[right] > tsum:
                right -=1
            elif array[left]+array[right] < tsum:
                left += 1
            else:
                result.append(array[left])
                result.append(array[right])
                break
        return result
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页