• 剑指 Offer 57


    题目描述

    输入一个正整数 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
    

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof

    思路解析

    • 等差数列的前(n)项和为:

    [S=na_1+frac{n(n-1)d}{2} ]

    • 本题中要求连续正整数,则(d=1),我们需要求出(n)(a_1)
      整理上式,得:

    [a_1=frac{S}{n}-frac{n-1}{2}=frac{2S-n(n-1)}{2n} ]

    • (S)为题目中的target,仅当(frac{2S-n(n-1)}{2n})为正整数时,满足条件,因此可以遍历(n),分别检查计算得到的(a_1)是否为正整数,是则将答案存入待输出数组。
    • 此外,还可以确定(n)的范围,来减少查找时间,已知前(n)个自然数的和为(frac{n(n+1)}{2}),则若(frac{n(n+1)}{2}=S)时,(n)取到最大值:

    [n_{max}=sqrt{2S} ]

    • 得到(n)的取值范围为([2,lfloor sqrt{2S} floor]),分别代入上式检查(a_1)是否为正整数即可。

    代码实现

    class Solution {
    public:
        vector<vector<int>> findContinuousSequence(int target) {
            vector<vector<int>> result;
            int max_add = (int)(sqrt(2 * target));
            for(int i = max_add; i > 1; i--) {
                int p = 2 * target - i * (i - 1);
                int q = 2 * i;
                if(p % q == 0) {
                    int a1 = p / q;
                    vector<int> tmp;
                    for(int j = 0; j < i; j++)
                        tmp.push_back(j + a1);
                    result.push_back(tmp);
                }
            }
            return result;
        }
    };
    
  • 相关阅读:
    WPF程序国际化
    MVVM框架搭建
    最全前端开发面试问题及答案整理
    最小化运行批处理
    C#中App.config文件配置获取
    VS2017 打包成exe
    Inno Setup生成桌面快捷方式
    C#文件读写(txt 简单方式)
    Flume 学习笔记之 Flume NG概述及单节点安装
    快学Scala 第二十课 (trait的构造顺序)
  • 原文地址:https://www.cnblogs.com/xqmeng/p/13637853.html
Copyright © 2020-2023  润新知