【自刷 剑指offer57】和为S的连续正数序列

 好歹是按自己的思路写出来了。。。。耗时2h

题目描述

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

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

 我的思路

 首先这题没给我数组,我就自己搞了个0-100的数列,根据题目的输出示例,观察到输出的数组总会在target的(一半+1)以下,这样就可以减少一些查找量。这里需要注意的是,JavaScript的除法是直接除可以有小数的,不同于c/c++。因此我就向下取整了(向上取整会更好点),然后新建一个不知道长度的数组就直接const res=[]即可,后面会往里面放东西,因此不需要fill(0)。

其次开始循环找几个重要数值,n(返回数组里有几组数组),flag&outFlag(加了几轮,也就意味着一个小数组里有几个数),num(一个小数组里最大的数)。需要注意的是,因为设置的参数有点多,所以最好写好注释以免搞混了。我一开始的时候犯了一个很愚蠢的错误,直接把j拿到while循环里加给sum,同时j也会自加,导致外层for循环只循环了一次就出来了,我还一直在找为什么。

因此最好不要在for循环里改变j这类数的值。

接着就是对每个参数的规则添加,flag因为需要清0,所以要给一个outFlag出来。

关于这个outFlag又有一个小问题,因为是在for循环里while,所以有些outFlag存在为0的情况,这个outFlag直接关系到一个小数组里有几个数,就是如果有数下来的话,下面的while循环也会创建一个空的新数组,所以要规避掉这些没用的0,就搞一个if,如果不为0,才执行下面的步骤。

最后就是如何把小数组放进返回数组里,这里我是看了一下别人的题解的,因为本人只懂push,但是push进去以后输出空值。别人的办法是使用splice(0)方法拷贝数组,再把数组push进返回数组里。

 我的代码

/**
 * @param {number} target
 * @return {number[][]}
 */
var findContinuousSequence = function(target) {
       const nums=new Array(100);
       let sum=0,num=0,n=0,t=0,flag=0,outFlag=0;
       for(let i=0;i<nums.length;i++)
       {
           nums[i]=i;
       }
       //向下取整
       let a=Math.floor(target/2);
       const res=[];
       for(let j=1;j<=a+1;j++)
       {
           sum=0,t=j;
           flag=0;
           while(t<=a+1)
           {
               sum+=t;
               //加了几轮
               flag++;

               if(sum==target)
               {
                   //n代表了数组里有几组数组
                   n++;
                   //num代表数组里最大的那个数
                   num=t; 
                   //outflag代表了数组里有几个数,也就是加了几次
                 outFlag=flag;
                   flag=0;
                   break;
               }
                t++;
                if(sum>target)
                {
                    break;
                }
           }  

           console.log(outFlag);
           //输出数组
           if(outFlag!=0)
           {
            const tarr=new Array(outFlag);
            while(num>0&&outFlag>0)
           {
                tarr[outFlag-1]=num;
                num--,outFlag--;
       }
       res.push(tarr.slice(0));
           }       
       }
    return res;
};

官方题解 

 官方使用了滑动窗口的方法,这里我看的是(作者:爱吃糖的猫
链接:https://leetcode.cn/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof/solutions/1956261/yi-chong-hao-li-jie-de-hua-dong-chuang-k-lm4o/)的方法。非常简洁。

这里的Math.ceil()方法就是向上取整。

如果sum比target大了,就移除前面的数,如果相等,就push进返回数组。

然后shift是删除头部的数,unshift是在头部添加数。

具体的可以看掘金的这篇:js数组常用方法(19种)|你会的到底有多少呢? - 掘金 (juejin.cn)

var findContinuousSequence = function(target) {
    let sum = 1   //窗口数组的和
    let list =[1] //窗口
    let returnList =[]
    for(let i = 2 ; i<= Math.ceil(target/2) ; i++) {
        sum+=i
        list.push(i)  //每次循环,都将当前的数加入滑动窗口中
        while(sum>target){
            sum-=list.shift()  //移除前面较小的数
        }
        if(sum==target){
            returnList.push(list.slice(0))   //slice深拷贝
        }
    }
    return returnList
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值