Leetcode.945.使数组唯一的最小增量

题目

给定整数数组 A,每次 move 操作将会选择任意 A[i],并将其递增 1。

返回使 A 中的每个值都是唯一的最少操作次数。

示例 1:

输入:[1,2,2]
输出:1
解释:经过一次 move 操作,数组将变为 [1, 2, 3]。
示例 2:

输入:[3,2,1,2,1,7]
输出:6
解释:经过 6 次 move 操作,数组将变为 [3, 4, 1, 2, 5, 7]。
可以看出 5 次或 5 次以下的 move 操作是不能让数组的每个值唯一的。
提示:

0 <= A.length <= 40000
0 <= A[i] < 40000

思路

采用贪心策略(重复元素后的最佳 move 位置,例如 [ 1, 1, 3 ] 中,对重复元素 1 的最佳 move 位置为 2 而不是 4)对数组元素所占范围的空隙进行“占领”。首先,对数组进行排序;其次,将重复元素入栈(其实也可以不用栈);最后,将栈中元素放入到数组元素范围内的空隙中,并记录所需move操作数。实现如下:

class Solution {
public:
    int minIncrementForUnique(vector<int>& A) {
        if(A.empty())
            return 0;

        fastsort(A, 0, A.size()-1);

        stack<int> s;
        int ans=0;
        for(int i=0; i<A.size()-1; i++){
            if(A[i] == A[i+1])
                s.push(A[i+1]);
            else if(A[i+1]-A[i] > 1){
                for(int j=A[i]+1; j<A[i+1]; j++){
                    if(!s.empty()){
                        int v=s.top();
                        s.pop();
                        ans+=j-v;
                    }else
                        break;
                }
            }
        }
        int p=A[A.size()-1]+1;
        while(!s.empty()){//“空隙”放不下,放到最后。
            int v=s.top();
            s.pop();
            ans+=p-v;
            p++;
        }
        return ans;
    }
    void fastsort(vector<int>& A, int lo, int hi){
        if(lo>=hi)
            return;
        int p=partition(A, lo, hi);
        fastsort(A, lo, p-1);
        fastsort(A, p+1, hi);
    }

    int partition(vector<int>& A, int lo, int hi){
        int v=A[lo];
        int i=lo, j=hi+1;
        while(true){
            while(A[++i]<v) if(i==hi) break;
            while(v<A[--j]) if(j==lo) break;
            if(i>=j)    break;
            swap(A[i], A[j]);
        }
        swap(A[lo], A[j]);
        return j;
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值