跳转至

2856. 删除数对后的最小数组长度

题目描述

给你一个下标从 0 开始的 非递减 整数数组 nums 。

你可以执行以下操作任意次:

  • 选择 两个 下标 i 和 j ,满足 nums[i] < nums[j] 。
  • nums 中下标在 i 和 j 处的元素删除。剩余元素按照原来的顺序组成新的数组,下标也重新从 0 开始编号。

请你返回一个整数,表示执行以上操作任意次后(可以执行 0 次),nums 数组的 最小 数组长度。

 

示例 1:

输入:nums = [1,2,3,4]

输出:0

解释:

示例 2:

输入:nums = [1,1,2,2,3,3]

输出:0

解释:

示例 3:

输入:nums = [1000000000,1000000000]

输出:2

解释:

由于两个数字相等,不能删除它们。

示例 4:

输入:nums = [2,3,4,4,4]

输出:1

解释:

 

提示:

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 109
  • nums 是 非递减 数组。

解法

方法一:贪心 + 优先队列(大根堆)

我们用一个哈希表 \(cnt\) 统计数组 \(nums\) 中每个元素的出现次数,然后将 \(cnt\) 中的每个值加入一个优先队列(大根堆) \(pq\) 中。每次从 \(pq\) 中取出两个元素 \(x\)\(y\),将它们的值减一,如果减一后的值仍大于 \(0\),则将减一后的值重新加入 \(pq\)。每次从 \(pq\) 中取出两个元素,表示将数组中的两个数对删除,因此数组的长度减少 \(2\)。当 \(pq\) 的大小小于 \(2\) 时,停止删除操作。

时间复杂度 \(O(n \times \log n)\),空间复杂度 \(O(n)\)。其中 \(n\) 是数组 \(nums\) 的长度。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
class Solution:
    def minLengthAfterRemovals(self, nums: List[int]) -> int:
        cnt = Counter(nums)
        pq = [-x for x in cnt.values()]
        heapify(pq)
        ans = len(nums)
        while len(pq) > 1:
            x, y = -heappop(pq), -heappop(pq)
            x -= 1
            y -= 1
            if x > 0:
                heappush(pq, -x)
            if y > 0:
                heappush(pq, -y)
            ans -= 2
        return ans
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
    public int minLengthAfterRemovals(List<Integer> nums) {
        Map<Integer, Integer> cnt = new HashMap<>();
        for (int x : nums) {
            cnt.merge(x, 1, Integer::sum);
        }
        PriorityQueue<Integer> pq = new PriorityQueue<>(Comparator.reverseOrder());
        for (int x : cnt.values()) {
            pq.offer(x);
        }
        int ans = nums.size();
        while (pq.size() > 1) {
            int x = pq.poll();
            int y = pq.poll();
            x--;
            y--;
            if (x > 0) {
                pq.offer(x);
            }
            if (y > 0) {
                pq.offer(y);
            }
            ans -= 2;
        }
        return ans;
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Solution {
public:
    int minLengthAfterRemovals(vector<int>& nums) {
        unordered_map<int, int> cnt;
        for (int x : nums) {
            ++cnt[x];
        }
        priority_queue<int> pq;
        for (auto& [_, v] : cnt) {
            pq.push(v);
        }
        int ans = nums.size();
        while (pq.size() > 1) {
            int x = pq.top();
            pq.pop();
            int y = pq.top();
            pq.pop();
            x--;
            y--;
            if (x > 0) {
                pq.push(x);
            }
            if (y > 0) {
                pq.push(y);
            }
            ans -= 2;
        }
        return ans;
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
func minLengthAfterRemovals(nums []int) int {
    cnt := map[int]int{}
    for _, x := range nums {
        cnt[x]++
    }
    h := &hp{}
    for _, x := range cnt {
        h.push(x)
    }
    ans := len(nums)
    for h.Len() > 1 {
        x, y := h.pop(), h.pop()
        if x > 1 {
            h.push(x - 1)
        }
        if y > 1 {
            h.push(y - 1)
        }
        ans -= 2
    }
    return ans
}

type hp struct{ sort.IntSlice }

func (h hp) Less(i, j int) bool { return h.IntSlice[i] > h.IntSlice[j] }
func (h *hp) Push(v any)        { h.IntSlice = append(h.IntSlice, v.(int)) }
func (h *hp) Pop() any {
    a := h.IntSlice
    v := a[len(a)-1]
    h.IntSlice = a[:len(a)-1]
    return v
}
func (h *hp) push(v int) { heap.Push(h, v) }
func (h *hp) pop() int   { return heap.Pop(h).(int) }
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function minLengthAfterRemovals(nums: number[]): number {
    const cnt: Map<number, number> = new Map();
    for (const x of nums) {
        cnt.set(x, (cnt.get(x) ?? 0) + 1);
    }
    const pq = new MaxPriorityQueue();
    for (const [_, v] of cnt) {
        pq.enqueue(v);
    }
    let ans = nums.length;
    while (pq.size() > 1) {
        let x = pq.dequeue().element;
        let y = pq.dequeue().element;
        if (--x > 0) {
            pq.enqueue(x);
        }
        if (--y > 0) {
            pq.enqueue(y);
        }
        ans -= 2;
    }
    return ans;
}

评论