日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

左神算法:未排序正数数组中累加和为给定值的最长子数组长度(Java版)

發布時間:2024/2/28 java 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 左神算法:未排序正数数组中累加和为给定值的最长子数组长度(Java版) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本題來自左神《程序員代碼面試指南》“未排序正數數組中累加和為給定值的最長子數組長度”題目。

題目

牛客OJ:未排序數組中累加和為給定值的最長子數組長度

題解

本文提供的方法可以做到時間復雜度為O(N)、額外空間復雜度為O(N)。

為了說明解法,先定義s 的概念,s(i)代表子數組arr[0…i]所有元素的累加和。那么子數組arr[j…i(] 0≤j≤i<arr.length)的累加和為s(i)-s(j-1),因為根據定義,s(i)=arr[0…i]的累加和等于arr[0…j-1]的累加和與arr[j…i]的累加和相加,又有arr[0…j-1]的累加和為s(j-1)。所以,arr[j…i]的累加和為s(i)-s(j-1),這個結論是求解這道題的核心。

整個過程只遍歷一次arr,具體過程為:

  • 設置變量sum=0,表示從0 位置開始一直加到i 位置所有元素的和。設置變量len=0,表示累加和為k 的最長子數組長度。設置哈希表map,其中,key 表示從arr 最左邊開始累加的過程中出現過的sum 值,對應的value 值則表示sum 值最早出現的位置。
  • 從左到右開始遍歷,遍歷的當前元素為arr[i]。
  • 令sum=sum+arr[i],即之前所有元素的累加和s(i),在map 中查看是否存在sum-k。
    • 如果 sum-k 存在,從map 中取出sum-k 對應的value 值,記為j,j 代表從左到右不斷累加的過程中第一次加出sum-k 這個累加和的位置。根據之前得出的結論,arr[j+1…i]的累加和為s(i)-s(j),此時s(i)=sum,又有s(j)=sum-k,所以arr[j+1…i]的累加和為k。同時因為map 中只記錄每一個累加和最早出現的位置,所以此時的arr[j+1…i]是在必須以arr[i]結尾的所有子數組中,最長的累加和為k 的子數組,如果該子數組的長度大于len,就更新len。
    • 如果 sum-k 不存在,說明在必須以arr[i]結尾的情況下沒有累加和為k 的子數組。
  • 檢查當前的sum(即s(i))是否在map 中。如果不存在,說明此時的sum 值是第一次出現的,就把記錄(sum,i)加入到map 中。如果sum 存在,說明之前已經出現過sum,map 只記錄一個累加和最早出現的位置,所以此時什么記錄也不加。
  • 繼續遍歷下一個元素,直到所有的元素遍歷完。
  • 大體過程如上,但還有一個很重要的問題需要處理。根據arr[j+1…i]的累加和為s(i)-(j),所以,如果從0 位置開始累加,會導致j+1≥1。也就是說,所有從0 位置開始的子數組都沒有考慮過。所以,應該從-1 位置開始累加,也就是在遍歷之前先把(0,-1)這個記錄放進map,這個記錄的意義是如果任何一個數都不加時,累加和為0。這樣,從0 位置開始的子數組就被我們考慮到了。

    具體過程請參看如下代碼中的 maxLength 方法。

    package chapter_8_arrayandmatrix;import java.util.HashMap;public class Problem_11_LongestSumSubArrayLength {public static int maxLength(int[] arr, int k) {if (arr == null || arr.length == 0) {return 0;}HashMap<Integer, Integer> map = new HashMap<Integer, Integer>(); // 含義:<從0位置元素的累加和, 滿足此累加和的最小下標>map.put(0, -1); // 注意不要寫成 (0, 0)int len = 0;int sum = 0;for (int i = 0; i < arr.length; i++) {sum += arr[i];if (map.containsKey(sum - k)) {len = Math.max(i - map.get(sum - k), len);}if (!map.containsKey(sum)) {map.put(sum, i);}}return len;}public static int[] generateArray(int size) {int[] result = new int[size];for (int i = 0; i != size; i++) {result[i] = (int) (Math.random() * 11) - 5;}return result;}public static void printArray(int[] arr) {for (int i = 0; i != arr.length; i++) {System.out.print(arr[i] + " ");}System.out.println();}public static void main(String[] args) {int[] arr = generateArray(20);printArray(arr);System.out.println(maxLength(arr, 10));} }

    附:ACM賽制牛客題解(需手動輸入輸出),即我的解法,已通過全部測試用例

    package test;import java.util.*;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();int k = scanner.nextInt();int[] arr = new int[n];for (int i = 0; i < n; i++) {arr[i] = scanner.nextInt();}// solutionMap<Integer, Integer> map = new HashMap<>(); // <從0位置元素的累加和, 滿足此累加和的最小下標>map.put(0, -1); // 注意不要寫成 (0, 0)int maxLen = 0, curSum = 0;for (int i = 0; i < n; i++) {curSum += arr[i];if (!map.containsKey(curSum)) {map.put(curSum, i);}int gap = curSum - k;if (map.containsKey(gap)) {maxLen = Math.max(i - map.get(gap), maxLen);}}System.out.println(maxLen);} } /* 【示例1】 11 0 1 -2 1 1 1 -1 1 -1 1 -1 2 答案:9 解析:1 [-2 1 1 1 -1 1 -1 1 -1] 2【示例2】 20 0 -1 1 0 4 5 -2 2 -2 2 -2 2 -4 4 5 -2 -2 -1 1 1 1 答案:12 解析:-1 1 0 4 5 [-2 2 -2 2 -2 2 -4 4 5 -2 -2 -1] 1 1 1*/

    總結

    以上是生活随笔為你收集整理的左神算法:未排序正数数组中累加和为给定值的最长子数组长度(Java版)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。