• 面试题57


    题目地址:https://leetcode-cn.com/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof/

    题目描述

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

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

    题目示例

    示例 1:

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

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

    解题思路

    暴力法:分析题目可得,若要求序列长度至少大于 2 ,则枚举上界为(target-1)/2(等价于target/2向下取整)。然后,从1开始枚举每个正整数,判断以它为起点的序列和 sum 是否等于target,若sum>target,则枚举的起点不符合要求,初始化sum=0,并跳出此次循环,并将枚举的起点i自增1,进行下一轮枚举。若sum==target,则将此轮枚举结果插入到res中,最后保存到集合v中,并初始化sum=0,结束此轮枚举。

    等差数列之和+双指针:利用等差数列求和公式可得,数列之和=(首项+尾项)*项数 / 2,即target=(start+end)*(end-start+1)/2。
    在本题中,我们使用双指针left和right表示当前枚举到的以left为起点到right的区间,用sum表示区间[left,right]的区间之和,然后使用求和公式sum = (left+right)*(right-left+1)/2与target相比较,,根据题目要求序列长度至少为2,初始可令left=1,right=2。

    • 若sum>target,则说明以left为起点,不存在right使得sum==target,此时,枚举下一个起点,指针left右移;
    • 若sum<targe,则说明以left为起点,right为尾点的区间之和sum还不够大,也就是right还可以更大,此时,指针right右移;
    • 若sum==target,则说明找到了满足条件的解[left,right],将解的序列放入数组v中,然后枚举下一个起点,即指针left右移;

      通过对暴力法和双指针方法对比发现,双指针考虑到了如果已知 [left,right]的区间和sum等于target ,那么枚举下一个起点的时候,区间 [left+1,right]的和必然小于target ,此时,不再需要从left+1开始重复枚举,而是从right+1开始枚举

    程序源码

    方法1——暴力法

    class Solution {
    public:
        vector<vector<int>> findContinuousSequence(int target) {
            vector<vector<int>> v;
            vector<int> res;
            int sum = 0, upLimit = (target - 1) / 2;
            for(int i = 1; i <= upLimit; i++)
            {
                for(int j = i; ; j++)
                {
                    sum += j;
                    if(sum > target)
                    {
                        sum = 0;
                        break;
                    }
                    else if(sum == target)
                    {
                        res.clear();
                        for(int k = i; k <= j; k++)
                        {
                            res.emplace_back(k);
                        }
                        v.emplace_back(res);
                        sum = 0;
                        break;
                    }
                    else
                    {
                        continue;
                    }
    
                }
            }
            return v;
        }
    };

    方法2——双指针

    class Solution {
    public:
        vector<vector<int>> findContinuousSequence(int target) {
            vector<vector<int>> v;
            vector<int> res;
            int left = 1 , right = 2;
            while(left < right)
            {       
                int sum = (left + right) * (right - left + 1) / 2;
                if(sum > target)
                {
                    left++;
                }
                else if(sum == target)
                {
                    res.clear();
                    for(int i = left; i <= right; i++)
                    {
                        res.emplace_back(i);
                    }
                    v.emplace_back(res);
                    left++;
                }
                else
                {
                    right++;
                }
            }
            return v;
        }
    };
    ----------------------------------- 心之所向,素履所往;生如逆旅,一苇以航。 ------------------------------------------
  • 相关阅读:
    不使用SpringBoot如何将原生Feign集成到Spring中来简化http调用
    干货!从Tomcat执行流程了解jsp是如何被解析的,错误提示是哪里生成的。
    对TCP三次握手四次分手还不清楚的速度进,超简单解析,明白了就很好记!
    SpringCache与redis集成,优雅的缓存解决方案
    高可用的Spring FTP上传下载工具类(已解决上传过程常见问题)
    Hibernate级联之一对多和inverse解析
    Spring的面向切面
    归并排序:步骤讲解与代码实现
    关于操作系统中多个fork()会创建几个进程的理解
    win-sudo插件解决Git bash 执行脚本报错问题 bash: sudo: command not found
  • 原文地址:https://www.cnblogs.com/wzw0625/p/12505962.html
Copyright © 2020-2023  润新知