題目:輸入一個正數n,輸出所有和為n連續(xù)正數序列览爵。例如輸入15置鼻,由于1+2+3+4+5=4+5+6=7+8=15,所以輸出3個連續(xù)序列1-5蜓竹、4-6和7-8
最簡單沃疮,也是最笨的方法,就是兩次循環(huán)梅肤,代碼如下:
public void getSeri(int n) {
if (n == 1) {
return;
}
//防止溢出
int length = (n+1) >>> 1;
int sum = 0;
for (int i = 1; i < length; i++) {
sum = i;
for (int j = i +1; j <= length; j++) {
sum += j;
if (sum == n) {
System.out.println(i + "-" + j);
break;
} else if (sum > n) {
break;
}
}
}
}
我們先看司蔬,這段代碼,首先如果輸入的是 1直接返回姨蝴,因為不會有連續(xù)的值相加等于自己俊啼。然后看length,這個值是我們for循環(huán)的最大值左医,因為授帕,length的值是輸入值的中間值,一單超過了中間值浮梢,任意兩個值相加都會比n大跛十。比如說,15的中間值是8,8+9=17>15秕硝,之后的所有序列都大于15了芥映,所以循環(huán)到8就可以終止了,節(jié)省下效率远豺。
雖然我們在循環(huán)上稍微注意了下效率奈偏,但實際上,這個代碼的效率還是很低了躯护,因為做了兩次嵌套循環(huán)惊来。如果n=100的話,就要做50*50=2500次循環(huán)棺滞,n越大裁蚁,速度越慢矢渊。
所以我又想了,第二種方法枉证,代碼如下:
public void getSeriProv(int n) {
if (n == 1) {
return;
}
int length = (n+1) >>> 1;
List queue = new LinkedList<>();
int sum = 0;
for (int i =1; i <= length; i++) {
queue.add(i);
sum += i;
while (sum > n) {
int oldvalue = queue.remove(0);
sum -= oldvalue;
}
if (sum == n) {
System.out.println(queue.get(0) + "-" + queue.get(queue.size()-1));
int oldvalue = queue.remove(0);
sum -= oldvalue;
}
}
}
我先創(chuàng)建了一個隊列矮男。每次循環(huán)都向隊列的列尾加入當前的數值,同時計算sum和刽严,如果sum比n大的話就移除列頭的值昂灵,直到sum<=n避凝,如果sum=n則舞萄,直接打印結果,移除列頭管削,進行下一次的循環(huán)倒脓。
因為是連續(xù)數值的和,這樣我就不用每次都從頭sum含思,只需要每次sum隊列里面的值即可崎弃。