659. 分割數組為連續子序列
輸入一個按升序排序的整數數組(可能包含重復數字),你需要將它們分割成幾個子序列,其中每個子序列至少包含三個連續整數。返回你是否能做出這樣的分割?
示例 1:
輸入: [1,2,3,3,4,5]
輸出: True
解釋:
你可以分割出這樣兩個連續子序列 :
1, 2, 3
3, 4, 5
示例 2:
輸入: [1,2,3,3,4,4,5,5]
輸出: True
解釋:
你可以分割出這樣兩個連續子序列 :
1, 2, 3, 4, 5
3, 4, 5
示例 3:
輸入: [1,2,3,4,4,5]
輸出: False
提示:
- 輸入的數組長度范圍為 [1, 10000]
************************************************************
問題分析:
- 采用鏈表freq保存數組元素對應個數
- 采用need用來判斷當前元素是否能夠插入到一個已經構建好的序列末端
1 public boolean isPossible(int[] nums) { 2 //數組中每個元素與出現次數的對應關系 3 Map<Integer, Integer> freq = new HashMap<>(); 4 Map<Integer, Integer> need = new HashMap<>(); 5 6 for (int n : nums) freq.put(n, freq.getOrDefault(n, 0) + 1); 7 8 for (int n: nums) { 9 if (freq.getOrDefault(n, 0) == 0) continue; 10 11 if (need.getOrDefault(n, 0) > 0){ 12 need.put(n, need.get(n) - 1); 13 need.put(n + 1, need.getOrDefault(n + 1, 0) + 1); 14 } else if (freq.getOrDefault(n + 1, 0) > 0 && freq.getOrDefault(n + 2, 0) > 0){ 15 freq.put(n +1, freq.get(n + 1) - 1); 16 freq.put(n + 2, freq.get(n + 2) - 1); 17 need.put(n + 3, need.getOrDefault(n + 3, 0) + 1); 18 } else return false; 19 freq.put(n, freq.get(n) - 1); 20 } 21 22 return true; 23 }
參考鏈接:https://blog.csdn.net/LaputaFallen/article/details/80034863
在測試時,發現有些條件題目沒有給出提示,比如所有nums數組中的元素值大小都在±10000以內,所以也可以基於數組的形式完成,並且效率更高!
1 //測試中發現nums元素值都在正負10000以內 2 public boolean isPossible(int[] nums) { 3 int[] counts = new int[20000]; 4 int[] need = new int[20000]; 5 6 for (int i = 0; i < nums.length; i ++) { 7 //將所有負數轉為正數 8 nums[i] += 10000; 9 counts[nums[i]] ++; 10 } 11 12 for (int n : nums) { 13 if (counts[n] == 0) continue; 14 15 if (need[n] > 0){ 16 need[n] --; 17 need[n + 1] ++; 18 } else if (counts[n + 1] > 0 && counts[n + 2] > 0){ 19 counts[n + 1] --; 20 counts[n + 2] --; 21 need[n + 3] ++; 22 } else return false; 23 counts[n] --; 24 } 25 return true; 26 }