陣列三連問題
1、陣列一連 無序陣列只有正數,求子陣列和等於k的最長子陣列長度
解題思想:滑動視窗
兩個指標 left 和 right,sum 為 [left....right] 的和。如果 sum < k ,right 右移;如果 sum > k ,left 右移;如果sum == k,left右移或者right右移
程式碼如下:
1public static int solution(int [] arr, int k){ 2if (arr == null || arr.length == 0 || k <= 0) { 3return 0; 4} 5int left = 0; 6int right = 0; 7int sum = arr[0]; 8int len = 0; 9while (right < arr.length) { 10if (sum == k) { 11len = Math.max(len, right - left + 1); 12sum -= arr[left++]; 13} else if (sum < k) { 14right++; 15if (right == arr.length) { 16break; 17} 18sum += arr[right]; 19} else { 20sum -= arr[left++]; 21} 22} 23return len; 24}
2、陣列二連 無序陣列有正 負 0,求子陣列和等於k的最長子陣列長度
解題思想:字首和( 即如果[i...j...k]中和為sum,如果[i...j]和為s1,那麼(j...k]和必為 sum - s1)
程式碼如下:
1 public static int solution(int [] arr, int k){ 2if (arr == null || arr.length == 0 || k <= 0) { 3return 0; 4} 5HashMap<Integer,Integer> map = new HashMap<>(); 6map.put(0,-1); 7int sum = 0; 8int len = 0; 9for(int i = 0; i < arr.length; i++){ 10sum += arr[i]; 11if(map.containsKey(sum - k)){ 12len = Math.max(len,i - map.get(sum - k)); 13} 14if(!map.containsKey(sum)){ 15map.put(sum,i); 16} 17} 18return len; 19}3、陣列三連 無序陣列有正 負 0,求子陣列和小於等於k的最長子陣列長度
解題思路:預處理陣列+滑動視窗
程式碼如下:
1public staticint solution(int[] arr, int k){ 2if(arr == null || arr.length == 0){ 3return 0; 4} 5int[] minSums = new int[arr.length]; 6int[] minSumsEnds = new int[arr.length]; 7//minSums[i] 代表 i 到arr.length 中最小子陣列和 8minSums[arr.length - 1] = arr[arr.length - 1]; 9//minSumsEnds[i] 代表 i 到arr.length 中最小子陣列和的子陣列右邊界 10minSumsEnds[arr.length - 1] = arr.length - 1; 11//生成預處理陣列 12for(int i = arr.length - 2; i >= 0; i--){ 13if(minSums[i+1] < 0){ 14minSums[i] = arr[i] + minSums[i+1]; 15minSumsEnds[i] = minSumsEnds[i+1]; 16}else{ 17minSums[i] = arr[i]; 18minSumsEnds[i] = i; 19} 20} 21int end = 0; 22int sum = 0; 23int res = 0; 24//i是視窗的最左的位置,end是視窗最右位置的下一個位置 25for(int i = 0; i < arr.length; i++){ 26//while迴圈結束後 27// 1 如果以i為開頭的情況下,累加和<=k 的最長子陣列是arr[i...end-1],看看這個長度能不能更新res 28// 2 如果以i為開頭的情況下,累加和<=k 的最長子陣列比arr[i...end-1]短,更新還是不更新res都不會影響最終結果; 29while(end < arr.length && sum + minSums[end] <= k){ 30sum += minSums[end]; 31end = minSumsEnds[end]+1; 32} 33res = Math.max(res,end - i);//更新res值 34if(end > i){//視窗還有數 35sum -= arr[i]; 36}else{//視窗內已經沒數了,表示從i開頭的所有子陣列累加和都不可能<=k 37end = i + 1; 38} 39} 40return res; 41}