题解 | #剑指offer JZ74 和为S的连续正数序列#

和为S的连续正数序列

http://www.nowcoder.com/practice/c451a3fd84b64cb19485dad758a55ebe

* 思路1:穷举。

  • 题目中的连续正数序列即为公差为1的等差递增数列,在此对应的求和公式为:Sn=(a1+an)(an-a1+1)/2
  • 由于序列要求至少包括两个数,序列内按照从小至大的顺序;
  • 我采取的策略是每次遍历的时候固定a1(首项),寻找符合条件的an(尾项)
  • 注意观察到符合条件的最后一组序列存在一种规律,a1在范围**[ 1, sum/2 ]**内取值,作为外层循环,首项不会超过sum的一半,尾项不超过sum的一半加1,利用好这个规律 遍历的时候可缩小范围。(建议结合下面的代码和推理理解)
  • 时间复杂度O(n^2)

alt

alt

代码(JAVA实现)

public class Solution {
	 public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
	       ArrayList<ArrayList<Integer>> res=new ArrayList<>();
	       if(sum<2) return res;
	       for(int left=1;left<=sum/2;left++) {//等差数列首项a1=left
	    	   for(int right=sum/2+1;right>left;right--) {//等差数列尾项an=right
	    		   if(sum*2==(left+right)*(right-left+1)) {
	    			   ArrayList<Integer> list=new ArrayList<>();
	    			   for(int k=left;k<=right;k++) list.add(k);
	    			   res.add(list);
	    		   }
	    		   //left固定时,right最大的时候等差数列的和都比sum小,right--后更不可能相等
	    		   else if(sum*2>(left+right)*(right-left+1)) break;
	    	   }
	       }
	       return res;
	    }
}

/*

* 思路2:滑动窗口。

  • 扩大窗口,right += 1
  • 缩小窗口,left += 1

算法步骤:

  1.  初始化,left=1,right=1, 表示窗口大小为0
    
  2.  如果窗口内值的和小于目标值sum, 表示需要扩大窗口,right += 1
    
  3.  否则,如果窗口内的值的和大于目标值sum,表示需要缩小窗口,left += 1
    
  4.  否则,等于目标值,存结果,缩小窗口,继续进行步骤2,3,4
    

代码(JAVA实现)

public class Solution {
 public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum){
		 ArrayList<ArrayList<Integer>> res=new ArrayList<>();
	       if(sum<2) return res;
	       int left=1,right=1;//left窗口左边界,right窗口右边界,初始窗口大小为0,[left,right)
	       int content=0;//滑动窗口内的元素和
	       while(left<=sum/2){//要求至少包括两个数,左边界到sum的一半即可
	    	   if(content<sum) {//扩大窗口
	    		   content+=right;//加入窗口右侧的元素后,再扩大窗口
	    		   right++;
	    	   }
	    	   else if(content>sum){//缩小窗口
	    		   content-=left;
	    		   left++;
	    	   }
	    	   else {//和为sum
	    		   ArrayList<Integer> list=new ArrayList<>();
	    		   for(int k=left;k<right;k++) {//注意left在窗口内,而right不在窗口内,k是小于而不是小于等于right
	    			   list.add(k);//逐个添加到list
	    		   }
	    		   res.add(list);//加入到结果数组
                 content-=left;//减去窗口最左侧的元素,继续寻找
	    		   left++;
	    	   }
	       }
	       return res;
	 }
}
全部评论

相关推荐

02-22 20:28
重庆大学 Java
程序员牛肉:首先不要焦虑,你肯定是有希望的。 首先我觉得你得好好想一想自己想要什么。找不到开发岗就一定是失败的吗?那开发岗的35岁危机怎么说?因此无论是找工作还是考公我觉得你都需要慎重的想一想。但你一定要避开这样一个误区:“我是因为找不到工作所以不得不选择考公”。 千万不要这么想。你这个学历挺好的了,因此你投后端岗肯定是有面试机会的。有多少人简历写的再牛逼,直接连机筛简历都过不去有啥用?因此你先保持自信一点。 以你现在的水平的话,其实如果想要找到暑期实习就两个月:一个月做项目+深挖,并且不断的背八股。只要自己辛苦一点,五月份之前肯定是可以找到暑期实习的,你有点太过于高看大家之间的技术差距了。不要焦虑不要焦虑。 除此之外说回你这个简历内容的话,基本可以全丢了。如果想做后端,先踏踏实实做两个项目再说+背八股再说。如果想考公,那就直接备战考公。 但是但是就像我前面说的:你考公的理由可以是因为想追求稳定,想追求轻松。但唯独不能是因为觉得自己找不到工作。不能这么小瞧自己和自己的学历。
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务