牛客网在线编程专题《剑指offer-面试题41》和为S的连续正数序列

我的个人微信公众号:Microstrong

微信公众号ID:MicrostrongAI

微信公众号介绍:Microstrong(小强)同学主要研究机器学习、深度学习、计算机视觉、智能对话系统相关内容,分享在学习过程中的读书笔记!期待您的关注,欢迎一起学习交流进步!

知乎主页:https://www.zhihu.com/people/MicrostrongAI/activities

Github:https://github.com/Microstrong0305

个人博客:https://blog.csdn.net/program_developer

 题目链接:

https://www.nowcoder.com/practice/c451a3fd84b64cb19485dad758a55ebe?tpId=13&tqId=11194&tPage=3&rp=3&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

题目描述:

解题思路:

(1)时间复杂度为O(n^{2})

已经AC的代码:

# -*- coding:utf-8 -*-

import math


class Solution:
    def FindContinuousSequence(self, tsum):
        if tsum == 0 or tsum == 1:
            return []
        mid_ceil = int(math.ceil(float(tsum) / 2))
        result_list = []
        for i in range(1, mid_ceil + 1, 1):
            temp_sum = 0
            for j in range(i, 0, -1):
                temp_sum += j
                if temp_sum == tsum:
                    temp_list = [k for k in range(j, i + 1, 1)]
                    result_list.append(temp_list)
        return result_list


if __name__ == "__main__":
    sol = Solution()
    print(sol.FindContinuousSequence(3))

(2)时间复杂度为O(n)

         我们可以考虑用两个数small和big分别表示序列的最小值和最大值。首先把small初始化为1,big初始化为2。如果从small到 big的序列的和大于s,则可以从序列中去掉较小的值,也就是增大small的值。如果从small到big的序列的和小于s,则可以增大big,让这个序列包含更多的数字。因为这个序列至少要有两个数字,我们一直增加small到(1+s)/2 为止。
         以求和为9的所有连续序列为例,我们先把small初始化为1,big初始化为2。此时介于small和big之间的序列是{1,2},序列的和为3,小于9,所以我们下一步要让序列包含更多的数字。我们把big增加1变成3,此时序列为{1,2,3}。由于序列的和是6,仍然小于9,我们接下来再增加big变成4,介于 small 和big之间的序列也随之变成{1,2,34}。由于序列的和10大于9,我们要删去序列中的一些数字,于是我们增加small变成2,此时得到的序列是{2,3,4},序列的和正好是9。我们找到了第一个和为9的连续序列,把它打印出来。接下来我们再增加big,重复前面的过程,可以找到第二个和为9的连续序列{4, 5} 。可以用下表总结整个过程。

表:求取和为9的连续序列的过程
步骤 small big 序列 序列和 与s相比较 下一步操作
1 1 2 1,2 3 小于 增加big
2 1 3 1,2,3 6 小于 增加big
3 1 4 1,2,3,4 10 大于 增加small
4 2 4 2,3,4 9 等于 保存序列, 增加big
5 2 5 2,3,4,5 14 大于 增加small
6 3 5 3,4,5 12 大于 增加small
7 4 5 4,5 9 等于 保存序列

    形成了清晰的解题思路之后,我们就可以开始写代码了。 下面是已经AC的参考代码:

# -*- coding:utf-8 -*-
class Solution:
    def FindContinuousSequence(self, tsum):
        # write code here
        if tsum == 0 or tsum == 1 or tsum == 2:
            return []
 
        result_list = []
 
        mid = int((tsum + 1) // 2)
        array = [i for i in range(0, mid + 1)]
        small = 1
        big = 2
        temp_sum = array[small] + array[big]
        temp = [array[small], array[big]]
        while True:
            if temp_sum == tsum:
                temp_list = [t for t in temp]
                result_list.append(temp_list)
                if big < len(array) - 1:
                    big += 1
                    temp_sum = temp_sum + array[big]
                    temp.append(array[big])
                else:
                    return result_list
            if temp_sum > tsum:
                temp_sum = temp_sum - array[small]
                temp.remove(array[small])
                small += 1
            if temp_sum < tsum:
                if big < len(array) - 1:
                    big += 1
                    temp_sum = temp_sum + array[big]
                    temp.append(array[big])
                else:
                    return result_list
 
        return result_list

        在上述代码中,求连续序列的和应用了一个小技巧。通常我们可以用循环求一个连续序列的和,但考虑到每次操作之后的序列和操作之前的序列相比大部分数字都是一样的,只是增加或者减少了一个数字,因此我们可以在前一个序列的和的基础上求操作之后的序列的和。这样可以减少很多不必要的运算,从而提高代码的效率。

Reference:

【1】《剑指offer》,何海涛著。

发布了289 篇原创文章 · 获赞 1000 · 访问量 120万+

猜你喜欢

转载自blog.csdn.net/program_developer/article/details/104745775