您的位置:首页 > Web前端

《剑指offer》——和为S的连续正数序列

2015-12-07 21:56 323 查看
遍历穷举法

滑动窗口法

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;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: