js + leetcode刷题:No.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

解法:

// Solution One -- 排序后,把后面小于等于前面的数变成比前一个数大一;156ms 40.8mb
// 时间、空间复杂度: O(n)
var minIncrementForUnique0 = function(A) {
    let len = A.length
    if(len <= 1) return 0
    A.sort((a,b) => {return a-b})
    let count = 0
    for(let i = 1; i < len; i++){
        if(A[i] <= A[i-1]){
            count += A[i-1] - A[i] + 1
            A[i] = A[i-1] + 1
        }
    }
    return count
};

// Solution Two -- 官方1 计数  152ms 78.2mb
/*
复杂度分析
    时间复杂度:O(L)O(L),其中 LL 的数量级是数组 A 的长度加上其数据范围内的最大值,因为在最坏情况下,数组 A 中的所有数都是数据范围内的最大值。
    空间复杂度:O(L)O(L),需要长度 LL 的数组统计每个数出现的次数。
*/
var minIncrementForUnique1 = function(A) {
    let countArr = new Array(80000)
    for(let num of A){
        if(!countArr[num]){
            countArr[num] = 1
        }else{
            countArr[num] += 1
        }
    }
    let count = 0, taken = 0
    for(let i = 0; i < 80000; i++){
        if(countArr[i] && countArr[i] >= 2){
            taken += countArr[i] - 1
            count -= i * (countArr[i] - 1)
        }else if(taken > 0 && (countArr[i] === 0 || !countArr[i])){
            taken--
            count += i
        }
    }
    return count
};

// Solution Three -- 官方2 排序  156ms  40.7mb
/*
复杂度分析
    时间复杂度:O(N\log N)O(NlogN),其中 NN 是数组 AA 的长度,即排序的时间复杂度。
    空间复杂度:O(\log N)O(logN),排序需要额外 O(\log N)O(logN) 的栈空间。
*/
var minIncrementForUnique2 = function(A) {
    let len = A.length
    if(len <= 1) return 0
    A.sort((a,b) => {return a-b})
    let count = 0, taken = 0, give = 0
    for(let i = 1; i < len; i++){
        if(A[i-1] === A[i]){
            taken++
            count -= A[i]
        }else{
            give = Math.min(taken, A[i] - A[i-1] - 1)
            count += give * (give + 1)/2 + give * A[i-1]
            taken -= give
        }
    }
    count += taken * (taken + 1)/2 + taken * A[A.length - 1]
    return count
};
发布了67 篇原创文章 · 获赞 8 · 访问量 6333

猜你喜欢

转载自blog.csdn.net/qq_34425377/article/details/105029789