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

13 篇文章 0 订阅
11 篇文章 0 订阅

距离相等的条形码【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 + n l o g n ) O(n+nlogn) O(n+nlogn),将二元组插入大顶堆的时间复杂度为 O ( l o g n ) O(logn) O(logn),可能需要添加 n n n次。计数的时间复杂度为 O ( n ) O(n) O(n)
      • 空间复杂度: O ( n ) O(n) O(n)
计数+贪心+排序
  • 思路

    由于题目保证存在答案,那么出现最多的条形码的次数一定小于等于 ⌈ n / 2 ⌉ \lceil n/2 \rceil n/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 ( n l o g n ) O(nlogn) O(nlogn)
      • 空间复杂度: O ( M ) O(M) O(M),M为条形码的最大值
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值