LeetCode 1054 距离相等的条形码

LeetCode 1054 距离相等的条形码

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/distant-barcodes

博主Githubhttps://github.com/GDUT-Rp/LeetCode

题目:

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

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

示例 1:

输入:barcodes = [1,1,1,2,2,2]
输出:[2,1,2,1,2,1]

示例 2:

输入:barcodes = [1,1,1,1,2,2,3,3]
输出:[1,3,1,3,2,1,2,1]

示例 3:

输入:matrix = [[7,8],[1,2]]
输出:[7]

提示:

  • 1 <= barcodes.length <= 10000
  • 1 <= barcodes[i] <= 10000

解题思路:

方法一:频数表取剩余最多元素

将数据整理出<number, count>的频数表,每次取的时候取剩余最多的值,思路可行但耗时过大,是一个会超时的算法。

Golang
func rearrangeBarcodes(barcodes []int) []int {
    numCount := make(map[int]int)
    for _, code := range(barcodes) {
        numCount[code] += 1
    }
    
    var codes []int
    for i, _ := range(barcodes) {
        if i == 0 {
            codes = append(codes, peakMaxCountNum(0, numCount))
            continue
        }
        codes = append(codes, peakMaxCountNum(codes[i - 1], numCount))
    }

    return codes
}

func peakMaxCountNum(code int, numCount map[int]int) int {
    var (
        selectNum int
        selectNumCount int
    )
    for num, count := range(numCount) {
        if selectNumCount > count {
            continue
        }
        if num != code {
            selectNum = num
            selectNumCount = count
        }
    }
    numCount[selectNum] -= 1
    return selectNum
}

在这里插入图片描述

复杂度分析

时间复杂度: O ( n 2 ) O(n^2) O(n2)

空间复杂度: O ( n ) O(n) O(n),1个map的空间。

方法二:最大堆

思路与方法一差不多,但是用了最大堆来存储,利用这个数据结构可以将“取剩余最多的元素”的 N N N 变成 log ⁡ N \log N logN

统计频数表,插入最大堆,这样堆顶就是剩余元素最多的元素。
然后我们每次从堆顶拿出一个剩余最多的元素,放入排序中,再更新剩余数量,重新放入最大堆中。如果这个元素与排列结果中的最后一个元素相同,那么我们就需要再从最大堆中取出第二多的元素,放入排序中,之后再把这两个元素放入最大堆中。

Golang
type PriorityQueue [][]int

func (pq PriorityQueue) Len() int {
    return len(pq)
}

func (pq PriorityQueue) Less(i, j int) bool {
    return pq[i][0] > pq [j][0]
}

func (pq PriorityQueue) Swap(i, j int) {
    pq[i], pq[j] = pq[j], pq[i]
}

func (pq *PriorityQueue) Push(x interface{}) {
    item := x.([]int)
    *pq = append(*pq, item)
}

func (pq *PriorityQueue) Pop() interface{} {
    old := *pq
    n := len(old)
    item := old[n-1]
    *pq = old[:n-1]
    return item
}

func rearrangeBarcodes(barcodes []int) []int {
    count := make(map[int]int)
    for _, b := range barcodes {
        count[b]++
    }

    q := &PriorityQueue{}
    heap.Init(q)
    for k, v := range count {
        heap.Push(q, []int{v, k})
    }

    n := len(barcodes)
    res := make([]int, n)

    for i := 0; i < n; i++ {
        p := heap.Pop(q).([]int)
        count, num := p[0], p[1]
        if i == 0 || res[i-1] != num {
            // 第一个元素符合的情况下
            res[i] = num
            if count > 1 {
                heap.Push(q, []int{count-1, num})
            }
            continue
        }
        // 与前一元素相同的情况,再取一个出来
        p2 := heap.Pop(q).([]int)
        count2, num2 := p2[0], p2[1]
        res[i] = num2
        if count2 > 1 {
            heap.Push(q, []int{count2-1, num2})
        }
        heap.Push(q, []int{count, num})
    }
    return res
}

复杂度分析

时间复杂度: O ( n log ⁡ N ) O(n\log N) O(nlogN)

空间复杂度: O ( n ) O(n) O(n),1个map的空间。

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值