每日一题,由自信走向自闭(493. 翻转对,level:hard)

前言

493. 翻转对

第一次思考

  • 当我看完题目,顿觉好像有点思路了,又看了看难度: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。。。。

题解之一:归并排序

递归里面主要分为:

  1. 临界条件
  2. 递归left和right,保存ret值
  3. 统计下标对数量
  4. 合并两个有序数组,
  5. 更新nums数组为有序数组

官方题解

posted @ 2020-11-28 14:41  acchris  阅读(64)  评论(0)    收藏  举报