【每日一题Day206】LC1054距离相等的条形码 | 计数+大顶堆 计数+排序

文章介绍了如何在仓库条形码排列问题中,确保任意两个相邻的条形码不相等。提供了两种解决方案:一是使用计数、贪心和大顶堆,二是结合计数、贪心和排序策略。这两种方法都确保了在存在解的情况下能有效避免相邻条形码相同。第一种方法通过大顶堆处理出现次数最多的条形码,第二种方法则通过排序和交替放置来达到目标。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

距离相等的条形码【LC1054】

在一个仓库里,有一排条形码,其中第 i 个条形码为 barcodes[i]

请你重新排列这些条形码,使其中任意两个相邻的条形码不能相等。 你可以返回任何满足该要求的答案,此题保证存在答案。

写出了第一种
想做周赛 但是怕脑子动不起来掉分 所以又没做

计数+贪心+大顶堆
  • 思路【计数+贪心+大顶堆】

    需要保证出现次数最多的条形码优先匹配另一个与自身不同的条形码,否则可能会出现相同条形码相邻的情况

    • 首先记录每个条形码的出现次数
    • 然后将二元组[条形码,次数][条形码,次数][条形码,次数]放入大顶堆中,以次数降序排序,保证堆顶元素的出现次数最大
    • 然后将次数第一大和第二大的元素交替放入结果集中,注意:次数第二大的元素存在没有的情况
    • 最后返回结果即可
  • 实现

    class Solution {
        public int[] rearrangeBarcodes(int[] barcodes) {
            int n = barcodes.length;
            int[] res = new int[n];       
            PriorityQueue<int[]> pq = new PriorityQueue<>((o1, o2) -> o2[1] - o1[1]);
            int mx = 0;
            for (int barcode : barcodes){
                mx = Math.max(mx, barcode);
            }
            int[] count = new int[mx + 1];
            for (int barcode : barcodes){
                count[barcode]++;
            }
            // 次数最大的优先匹配第二大的
            for (int j = 1; j <= mx; j++){
                if (count[j] != 0){
                    pq.add(new int[]{j,count[j]});
                }
            }
            int i = 0;
            while (i < n){
                int[] pair1 = pq.poll();
                int[] pair2 = null;
                res[i++] = pair1[0];
                pair1[1]--;                    
                if (!pq.isEmpty()){
                    pair2 = pq.poll();
                    res[i++] = pair2[0];
                    pair2[1]--;
                    
                }
                if (pair1[1] != 0){
                    pq.add(pair1);
                }
                if (pair2 != null && pair2[1] != 0){
                    pq.add(pair2);
                }
            }
            return res;
            
    
        }
    }
    
    • 复杂度
      • 时间复杂度:O(n+nlogn)O(n+nlogn)O(n+nlogn),将二元组插入大顶堆的时间复杂度为O(logn)O(logn)O(logn),可能需要添加nnn次。计数的时间复杂度为O(n)O(n)O(n)
      • 空间复杂度:O(n)O(n)O(n)
计数+贪心+排序
  • 思路

    由于题目保证存在答案,那么出现最多的条形码的次数一定小于等于⌈n/2⌉\lceil n/2 \rceiln/2。那么将出现次数较多的条形码优先交替放置至结果集中,再将出现次数小的条形码放置至其的相邻位置,这样得到的结果一定符合要求

    • 先进行计数
    • 然后将条形码按照出现次数从大到小排序,出现次数相同时按照值从大到小排序
    • 然后将下标分为奇数组和偶数组两组,将相应的条形码依次放入结果集中
  • 实现

    class Solution {
        public int[] rearrangeBarcodes(int[] barcodes) {
            int n = barcodes.length;
            Integer[] t = new Integer[n];
            int mx = 0;
            for (int i = 0; i < n; ++i) {
                t[i] = barcodes[i];
                mx = Math.max(mx, barcodes[i]);
            }
            int[] cnt = new int[mx + 1];
            for (int x : barcodes) {
                ++cnt[x];
            }
            Arrays.sort(t, (a, b) -> cnt[a] == cnt[b] ? a - b : cnt[b] - cnt[a]);
            int[] ans = new int[n];
            for (int k = 0, j = 0; k < 2; ++k) {
                for (int i = k; i < n; i += 2) {
                    ans[i] = t[j++];
                }
            }
            return ans;
        }
    }
    
    作者:ylb
    链接:https://leetcode.cn/problems/distant-barcodes/solutions/2268959/python3javacgotypescript-yi-ti-yi-jie-ji-3or2/
    来源:力扣(LeetCode)
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    
    • 复杂度
      • 时间复杂度:O(nlogn)O(nlogn)O(nlogn)
      • 空间复杂度:O(M)O(M)O(M),M为条形码的最大值
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值