《剑指offer》——和为S的连续正数序列
2015-12-07 21:56
323 查看
遍历穷举法
滑动窗口法
T:
题目描述
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
`
输出描述:
输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序.
我的code:
将我重新实现一遍的代码再贴出来,code:
滑动窗口法
T:
题目描述
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
`
输出描述:
输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序.
遍历穷举法
我刚开始采用的做法,用遍历穷举的方式,在遍历的过程中,进行条件的约束,但是这种方式的时间复杂度仍然是O(n2)O(n^2)。我的code:
package niuke.sward2offer.findContinuousSequence; import java.util.ArrayList; /** * T: 和为S的连续正数序列 * * 题目描述 * 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。 * 但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。 * 没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。 * 现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck! * * 输出描述: * 输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序 * * date: 2015.12.7 20:53 * @author SSS * */ public class Solution { public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) { ArrayList<ArrayList<Integer>> resultsList = new ArrayList<ArrayList<Integer>>(); // 小于3的没有意义(无解) if (sum < 3) { return resultsList; } // 只要遍历sum一半就可以,因为再往后的连续正数序列其总和肯定大于sum int mid = sum / 2; for (int i = 1; i <= mid; i++) { for (int len = 2; ; len++) { // 长度至少为2 int curSum = this.getSum(i, len); if (curSum == sum) { resultsList.add(this.saveSequence(i, len)); } else if (curSum > sum) { break; } } } return resultsList; } /** * 返回首位为startIndex,长度为length的连续序列的总和 * @param startIndex * @param length * @return */ public int getSum(int startIndex, int length) { int endIndex = startIndex + length - 1; return (startIndex + endIndex) * length / 2; } /** * 返回连续正数列表 * @param startIndex * @param length * @return */ public ArrayList<Integer> saveSequence(int startIndex, int length) { ArrayList<Integer> resList = new ArrayList<Integer>(); int endIndex = startIndex + length; for (int i = startIndex; i < endIndex; i++) { resList.add(i); } return resList; } }
滑动窗口法
这种方式,是看到讨论版上有人贴出来的解题思路,我才恍然大悟的,这种思路将时间复杂度降到了O(n)O(n)。将我重新实现一遍的代码再贴出来,code:
import java.util.ArrayList; /** * T: 和为S的连续正数序列 * * 题目描述 * 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。 * 但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。 * 没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。 * 现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck! * * 输出描述: * 输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序 * * date: 2015.12.7 21:44 * @author SSS * */ public class Solution2 { /** * 类似于滑动窗口的概念,总和小于sum,就执行endIndex ++; 大于的话,就执行 startIndex ++; * @param sum * @return */ public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) { ArrayList<ArrayList<Integer>> resultsList = new ArrayList<ArrayList<Integer>>(); if (sum < 3) { return resultsList; } int startIndex = 1; int endIndex = 2; int curSum = 3; int mid = sum / 2; while (endIndex < mid || startIndex < endIndex) { if (curSum == sum) { resultsList.add(this.saveList(startIndex, endIndex)); } endIndex ++; curSum += endIndex; while (curSum > sum) { curSum -= startIndex; startIndex ++; } } return resultsList; } /** * 存储到list当中,并返回 * @param startIndex * @param endIndex * @return */ public ArrayList<Integer> saveList(int startIndex, int endIndex) { ArrayList<Integer> resList = new ArrayList<Integer>(); for (int i = startIndex; i <= endIndex; i++) { resList.add(i); } return resList; } }
相关文章推荐
- jquery之radio
- 10006---AngularJS 指令
- Manifest如何解析的?
- POJ 3294 Life Forms
- LeetCode-Remove Nth Node From End of List
- 轻松学习JavaScript十二:JavaScript基于面向对象之创建对象(一)
- React-Native入门指导之iOS篇 —— 一、准备工作
- jQuery中attr() 和 prop()【转】
- JavaScript 语法总结
- Effective Java之总是要改写toString
- AngularJs 脏值检查及其相关
- HTML5浏览器嵌入窗口程序解决方案
- CCSpriteBatchNode 是批处理节点
- js插件自动完成
- Web前端开发之定义全局的上下文路径
- zufeoj 2350 贪吃的松鼠
- JavaScript学习之DIV层与图像
- css中float left与float right的使用说明
- BZOJ 1016: [JSOI2008]最小生成树计数( kruskal + dfs )
- Mac环境下安装node.js、npm、express