No.1 最富有客戶的資產總量數組
解題思路this
求子數組和的最大值. 可使用 Java 8 以後的 stream 一句話搞定.code
代碼展現排序
classSolution{ publicintmaximumWealth(int[][] accounts){ return Arrays.stream(accounts). map(i -> Arrays.stream(i).sum()). max(Integer::compareTo).get(); } }
No.2 找出最具競爭力都子序列隊列
解題思路ci
即找到長度爲 k 的字典序最小的子序列. 貪心地每次取最小的數便可.rem
可是咱們不能取全局範圍的最小數, 好比說第一次取, 咱們只能在 [0, n - k] 的下標範圍內取最小的, 假設取到的最小值的下標爲 x, 那麼第二次取就應該在 [x, n - k + 1] 的下標範圍內取最小的.get
可使用優先隊列完成.it
代碼展現io
class Number { int num; int idx; public Number(int num, int idx) { this.num = num; this.idx = idx; } } public int[] mostCompetitive(int[] nums, int k) { // 優先按照數值大小排序, 大小相同則按照下標排序 PriorityQueue<Number> heap = new PriorityQueue<>((a, b) -> a.num == b.num ? a.idx - b.idx : a.num - b.num); // idx 表示區間的右端點 int idx; for (idx = 0; idx <= nums.length - k; idx++) { heap.add(new Number(nums[idx], idx)); } int[] res = new int[k]; int latestIdx = -1; for (int i = 0; i < k; i++) { Number num = heap.poll(); // 利用 latestIdx 移動區間左端點 while (num.idx < latestIdx) { num = heap.poll(); } // 取到了當前區間 [x, n - k + i] 中的最小值 res[i] = num.num; latestIdx = num.idx; // 右端點更新, 繼續向優先隊列里加數 for (; idx <= nums.length - k + i + 1 && idx < nums.length; idx++) { heap.add(new Number(nums[idx], idx)); } } return res; }
}
No.3 使數組互補的最少操做數
解題思路
核心仍然是枚舉: 枚舉最終的和是多少. 經過預處理的數據快速計算要使每組數達到這個和, 須要改動多少個數字.
代碼展現
class Solution { public int minMoves(int[] nums, int limit) { int halfLen = nums.length / 2; // 提取每組數, 便於後續處理 int[] smallPart = new int[halfLen]; int[] bigPart = new int[halfLen]; for (int i = 0, j = nums.length - 1; i < j; i++, j--) { smallPart[i] = Math.min(nums[i], nums[j]); bigPart[i] = Math.max(nums[i], nums[j]); } // 數值數量的前綴和 int[] smallCntPreSum = new int[limit + 1]; int[] bigCntPreSum = new int[limit + 1]; for (int i = 0; i < halfLen; i++) { smallCntPreSum[smallPart[i]]++; bigCntPreSum[bigPart[i]]++; } for (int i = 1; i <= limit; i++) { smallCntPreSum[i] += smallCntPreSum[i - 1]; bigCntPreSum[i] += bigCntPreSum[i - 1]; } // 原有的加和數值計數 int[] sumCnt = new int[limit * 2 + 1]; for (int i = 0; i < halfLen; i++) { sumCnt[smallPart[i] + bigPart[i]]++; } int res = nums.length; for (int sum = 2; sum <= limit + limit; ++sum) { // 最終的和爲 sum 時, 須要改動 tot 個數 int tot = halfLen - sumCnt[sum]; if (sum <= limit) tot += halfLen - smallCntPreSum[sum - 1]; else tot += bigCntPreSum[sum - limit - 1]; res = Math.min(res, tot); } return res; } }
No.4 數組的最小偏移量
解題思路
每一個數都有必定的變化範圍, 好比 5 只能變成 5 或 10, 而 8 能夠變成 1, 2, 4, 8
雙向變化很差處理, 咱們能夠先將每一個數都變成它的最大值的形式: 偶數不變, 奇數能夠乘以 2.
而後咱們須要作的就是把一些數縮小, 以使得最大值和最小值的差最小.
咱們須要縮小的就是最大值——由於只有縮小最大值才能影響結果. 因此, 不斷縮小最大值便可.
代碼展現
class Solution { public int minimumDeviation(int[] nums) { TreeSet<Integer> set = new TreeSet<>(); for (int num : nums) { set.add(num % 2 == 0 ? num : num * 2); } int res = set.last() - set.first(); while (res > 0 && set.last() % 2 == 0) { int max = set.last(); set.remove(max); set.add(max / 2); res = Math.min(res, set.last() - set.first()); } return res; } }