每日一題,由自信走向自閉(493. 翻轉對,level:hard)
阿新 • • 發佈:2020-11-28
前言
第一次思考
-
當我看完題目,頓覺好像有點思路了,又看了看難度:
hard
,有點震驚,這不是可以用雜湊表做麼? -
當我想用
雜湊表
時,想到鍵值的問題:key
放什麼,value
放什麼。
初步思考覺得key可以為值,value為下標,但是看了第一個示例又打消了念頭。(第一個示例有兩個值相同,但下標不同)只能再修改一下value,結果發現value不行,於是打算改成計數陣列即cnt[]做。
第二次思考
-
cnt陣列
的上限可以去原陣列找最高值,然後eleMx*2
即可。 -
那麼有一個問題,cnt[]放陣列出現的元素?還是放元素的兩倍?為了方便,我覺得可以直接放元素的兩倍,之後用來查詢是否存在當前值
cur(nums[i])>nums[j]*2
-
還有一個問題,題目要求
i > j
&&nums[i] > nums[j]*2
,這裡的cnt是有可能記錄到i前面已有的符合值,所以每遍歷一個元素必須刪除一個。
再度思考完,基本可以用解決第一二個示例了。
class Solution { public int reversePairs(int[] nums) { int ans = 0,n = nums.length; int max = 0; //取陣列上限 for(int i : nums){ max = Math.max(max, i); } int[] cnt = new int[max * 2 + 5]; //先計算元素*2值 for(int i : nums){ cnt[i * 2]++; } //每過一個元素,刪除對應cnt for(int i = 0;i < n - 1; ++i){ int cur = nums[i]; for(int j = cur - 1;j > 0;--j){ if(cnt[j] > 0){ ans++; } } cnt[i]--; } return ans; } }
第三次思考
-
上一個思考可以實現題目的兩個示例,但在提交時報錯了,出現了
[-5,-5]
這樣的負數示例,我直接否認了之前的想法,因為題目注意下面說了最大值不超過32位
,所以又回到了第一次思考。 -
這一次我自然地把
value
值當成了key值頻率
,然後對原先的進行替換修改。以為可以解決負數這一難題,結果還是太天真,GG。
最後我發現下限出現了問題,我前面的思考沒考慮到負數這一情況,所以我打算直接從下限
入手,進行修改。
class Solution { public int reversePairs(int[] nums) { int ans = 0,n = nums.length; //陣列無法解決負數,key:當前下標值*2 value:出現次數 Map<Integer,Integer> map = new HashMap(); //先計算元素*2值 for(int i = 0;i < n;++i){ map.put(nums[i] * 2,map.getOrDefault(nums[i] * 2, 0) + 1); } //每過一個元素,刪除對應map for(int i = 0;i < n - 1; ++i){ int cur = nums[i]; int flag = cur > 0 ? 0 : Integer.MIN_VALUE; for(int j = cur - 1;j > flag;--j){ if(map.containsKey(j) && map.get(j) > 0){ ans++; } } map.put(nums[i] * 2, map.get(nums[i] * 2) - 1); } return ans; } }
- 重點來了!此時我以為萬事俱備,必能過的時候,測試案例給我來了一棒
[2147483647,2147483647,2147483647,2147483647,2147483647,2147483647]
什麼東西,邊緣值???
自此,思考結束,我發現hard不愧是hard。。。。
題解之一:歸併排序
遞迴裡面主要分為:
- 臨界條件
- 遞迴left和right,儲存ret值
- 統計下標對數量
- 合併兩個有序陣列,
- 更新nums陣列為有序陣列