《剑指Offer》专题: 第五期 41-50

《剑指Offer》专题: 第五期 41-50

这里是《剑指Offer》专题系列第五期,一共十题,每题对应多种解法,一起来看看吧。
###正文

题目41:和为S的连续正数序列

小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
输出描述:
输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序

"""
方法1:利用数学方法 时间复杂度O(sqrt(n))
方法2:滑动窗口法,时间复杂度O(sqrt(n))
"""
class Solution:
    def FindContinuousSequence(self, tsum):
        #方法1:数学规律
        """
        # 鲁棒性代码
        if tsum <=0: return []
        res = []
        temp = []
        x = int((2*tsum)**0.5)# 等差数列求和公式得出 n<sqrt(2*sum)
        for n in range(x,1,-1): #n为序列的长度,范围为了减少n扫描的次数
            #n为偶数和n为奇数时,满足以下条件才能组成连续和S
            if tsum%n==0.5*n or ((n%2) and (tsum%n==0)): 
                for i in range(tsum/n-(n-1)/2,tsum/n+n/2+1):
                    temp.append(i)
                res.append(temp)
                temp = []
        return res
        """
        
        #方法2: 滑动窗口法(不定长,可伸缩)
        l, r, sum, res = 1, 2, 3, []
        while l<r and l<2*tsum**0.5:# l<2*tsum**0.5是从方法1偷师来的,加上会减少时间复杂度
            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的两个数字
输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
输出描述:
对应每个测试案例,输出两个数,小的先输出

# -*- coding:utf-8 -*-
"""
方法1: 时间复杂度o(n),空间复杂度o(1)
    利用数学知识:我们知道两个数的和固定时,两个数越接近,则乘积越大,反之,乘积越小
    于是,我们定义两个指针small,large,一个从第0位开始递增,一个从最后一位开始递减
    当满足两个位置的数字之和等于tsum,则跳出循环,并返回这两个位置的值,此时乘积一定是最小的。
    如果当small>=large时,退出循环,此时未找到两个数之和等于tsum,返回空数组。
"""
class Solution:
    def FindNumbersWithSum(self, array, tsum):
        # write code here
        if not array:return []
        small, large = 0, len(array)-1
        result =[]
        while small<large: #
            if array[small]+array[large]== tsum:
                result = [array[small],array[large]]
                break
            elif array[small]+array[large]<tsum:
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值