最接近零的子陣列和
阿新 • • 發佈:2018-11-06
前言
本解法轉載自九章演算法
九章演算法官網 http://www.jiuzhang.com/?source=code
原題地址 http://www.lintcode.com/problem/subarray-sum-closest/
原答案地址 http://www.jiuzhang.com/solution/subarray-sum-closest
題目資訊
給定一個整數陣列,找到一個和最接近於零的子陣列。返回第一個和最有一個指數。你的程式碼應該返回滿足要求的子陣列的起始位置和結束位置
樣例
給出[-3, 1, 1, -3, 5],返回[0, 2],[1, 3], [1, 1], [2, 2] 或者 [0, 4]。
挑戰
O(nlogn)的時間複雜度
程式碼
import java.math.BigInteger; import java.util.Arrays; import java.util.Comparator; // 相當於一個map class Pair { int sum; // value int index; // key public Pair(int s, int i) { sum = s; index = i; } } public class Solution { /** * @param nums: * A list of integers * @return: A list of integers includes the index of the first number and * the index of the last number */ public int[] subarraySumClosest(int[] nums) { int[] res = new int[2]; if (nums == null || nums.length == 0) { return res; } int len = nums.length; if (len == 1) { res[0] = res[1] = 0; return res; } Pair[] sums = new Pair[len + 1]; int prev = 0; sums[0] = new Pair(0, 0); for (int i = 1; i <= len; i++) { sums[i] = new Pair(prev + nums[i - 1], i); prev = sums[i].sum; } Arrays.sort(sums, new Comparator<Pair>() { public int compare(Pair a, Pair b) { return a.sum - b.sum; } }); int ans = Integer.MAX_VALUE; for (int i = 1; i <= len; i++) { if (ans > sums[i].sum - sums[i - 1].sum) { ans = sums[i].sum - sums[i - 1].sum; int[] temp = new int[] { sums[i].index - 1, sums[i - 1].index - 1 }; Arrays.sort(temp); res[0] = temp[0] + 1; res[1] = temp[1]; } } return res; } } /* * 問:為什麼需要一個 (0,0) 的初始 Pair? * * 答: 我們首先需要回顧一下,在 subarray 這節課裡,我們講過一個重要的知識點,叫做 Prefix Sum * * 比如對於陣列 [1,2,3,4],他的 Prefix Sum 是 [1,3,6,10] * * 分別表示 前1個數之和,前2個數之和,前3個數之和,前4個數之和 * * 這個時候如果你想要知道 子陣列 從下標 1 到下標 2 的這一段的和(2+3),就用前 3個數之和 減去 前1個數之和 = PrefixSum[2] - * PrefixSum[0] = 6 - 1 = 5 * * 你可以看到這裡的 前 x 個數,和具體對應的下標之間,存在 +-1 的問題 * * 第 x 個數的下標是 x - 1,反之 下標 x 是第 x + 1 個數 * * 那麼問題來了,如果要計算 下標從 0~2 這一段呢?也就是第1個數到第3個數,因為那樣會訪問到 PrefixSum[-1] * * 所以我們把 PrefixSum 整體往後面移動一位,把第0位空出來表示前0個數之和,也就是0. => [0,1,3,6,10] * * 那麼此時就用 PrefixSum[3] - PrefixSum[0] ,這樣計算就更方便了。 * * 此時,PrefixSum[i] 代表 前i個數之和,也就是 下標區間在 0 ~ i-1 這一段的和 * * 那麼回過頭來看看,為什麼我們需要一個 (0,0) 的 pair 呢? * * 因為 這個 0,0 代表的就是前0個數之和為0 * * 一個 n 個數的陣列, 變成了 prefix Sum 陣列之後,會多一個數出來 * */
n 個數的陣列, 變成了 prefix Sum 陣列之後,會多一個數出來*/