力扣2020春季每日一题 -945题 使数组唯一的最小增量

原题:点击此处

考点:排序、线性探测法

本题题解参考:线性探测法的路径压缩

解题:

  1. 本题的数字数量不会超过40000,最差情况必须考虑到80000。
  2. 第一时间想到了哈希表,可以用哈希表遍历一遍数组,得到数字与对应的频率,然后通过线性探测的方法,保证所有的数字频率都是“1”。(超时)
  3. 第二种思路是时间复杂度最为简单的“排序”,利用java内置soft函数。时间复杂度为O(nlogn);
  4. 第三种思路即线性探测法的路径压缩法。
    用数组来记录路径,如果当前位置没有被占据,则放入,并把之前路过的地方全部置为此数字,以便于后面的数字进行遍历的时候,可以跳过已经检查过的地方,时间复杂度为O(n),空间复杂度O(n);
    (强烈推荐观看题解参考,非常值得学习的思路)

下面为第三种思路的代码:
(需要注意的是递归的入口和出口!)

class Solution {
    public int minIncrementForUnique(int[] A) {
        // 特殊条件
        if(A.length == 0 || A.length == 1){
            return 0;
        }
        int[] dp = new int[80000];
        Arrays.fill(dp,-1);
        int ans = 0;
        for(int i : A){
            int res = LinearFind(dp,i);
            ans += (res - i);
        }
        return ans;
    }

    public int LinearFind(int[] dp,int i){
        // 递归跳出条件,代表此处没有值
        if(dp[i] == -1){
            dp[i] = i;
            return i;
        }
        // 路径压缩,探索过的路径记录最终的结果
        int road = LinearFind(dp,dp[i]+1);
        dp[i] = road;
        return road;
    }
}

因为排序非常简单,就不打出代码了。
下面是我第一次思考用哈希表的方法,时间复杂度真的太高了,超时了。
先总结到数组题,大致有:哈希表,排序,双指针都是非常常用的方法。

class Solution {
    public int minIncrementForUnique(int[] A) {
        // 特殊条件
        if(A.length == 0 || A.length == 1){
            return 0;
        }
        Map<Integer,Integer> map = new HashMap<>();
        // 遍历一次数组
        for(int i : A){
            map.put(i,map.getOrDefault(i,0)+1);
        }
        int ans = 0;
        // 第二次遍历数组
        for(int i : A){
            int count = map.get(i);
            // 如果本身数组只有一个,就不用管他了
            if(count == 1){
                continue;
            }
            while(count != 1){
                int newnum = i;
                // 进行move操作,加到表里面完全不存在这个数字
                while( map.containsKey(newnum) ){
                    newnum++;
                    ans++;
                }
                // 原位置-1
                map.put(i,map.get(i)-1);
                // 新数字置1;
                map.put(newnum,1);
                count--;
            }
        }
        return ans;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值