記錄在猿輔導筆試時遇到的一道題目。
問題
給定一個正整型數組,要求找出最長的連續元素個數,且這些元素之和小於或等於給定的某個數s。
- 例如:數組 5 1 1 1 2 7,給定最大5
那麼應返回4,即1 1 1 2。
問題分析
第一眼,就覺得是動態規劃,可以設置一個數組nums,存儲以每個元素作爲結尾時最長的連續元素個數,且和不超過給定的數。設置一個value數組存儲對應的元素和。這個思路沒有問題,但是有一個易錯點。即如果前一個元素的最長連續子數組之和加上當前元素大於了給定數,且此時當前元素值不大於給定數,那麼這時不能夠將nums設爲1,應該要從此元素位置向前遍歷,直到找到剛好大於給定數的位置之前,這個纔是此元素作爲結尾的最長連續子數組。對於如果當前元素大於了給定數,那麼設置value數組在這個下標處爲0,nums數組在這個下標處爲0。
解法二
解法二和第一個解法思路一致,都是計算以當前元素作爲結尾最長的連續子數組長度,但是使用另外一種不消耗內存的方法,即雙指針法。簡單地說就是固定左指針,動右指針,當兩指針之間的元素和大於了給定數,則移動右指針,直到兩指針內部元素之和小於或等於了給定數爲止。代碼如下:
作者:我是一個莫得感情的筆試機器
鏈接:https://www.nowcoder.com/discuss/261376?type=all&order=time&pos=&page=0
來源:牛客網
對原作者的代碼進行了一定修改,更加準確。
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int s = scanner.nextInt();
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = scanner.nextInt();
}
int num = 0;
int sum = arr[0];
int i = 0;
int j = 1;
for(int _i=0;_i<n;_i++)
{
i = _i;
j = _i+1;
if(arr[_i]<=s)
{
sum = arr[_i];
num = 1;
break;
}
}
while (j < n) {
if (sum + arr[j] <= s) {
sum += arr[j++];
num = Math.max(num, j - i);
} else {
sum += arr[j++];
while (i <= j && sum > s) {
sum -= arr[i];
i++;
}
}
}
System.out.println(num);
}
}
總結
對於一些題目並沒有那麼複雜是我們想得太複雜了。通過此題目複習了雙指針方法解決實際面試題目。