【go】力扣767_重构字符串

32 篇文章 0 订阅

题目描述

给定一个字符串S,检查是否能重新排布其中的字母,使得两相邻的字符不同。

若可行,输出任意可行的结果。若不可行,返回空字符串。

示例 1:

输入: S = "aab"
输出: "aba"
示例 2:

输入: S = "aaab"
输出: ""
注意:

S 只包含小写字母并且长度在[1, 500]区间内。

 我的解题思路:遍历字符串用一个长度为26的桶数组记录每个字符的个数,以字符长度为外层for判断,内层遍历数组找到数量最大字母数组下标和数值以及第二大字母在数组下标和数值,将其拼接在新字符串中,在判断如果只剩一种字符的时候,数值如果大于1则返回空字符串,为1则追加数组,后续将数组对应字符数量相减,字符长度相减

func reorganizeString(S string) string {
    var str string
	var array [26]int
	var strLen = len(S)
	for i:=0;i<strLen;i++{
		array[S[i]-97]++
	}
	for strLen>0{
		var firstMax,secondMax int
		var firstIndex,secondIndex int
		for i:=0;i<len(array);i++{
			if array[i]!=0 && array[i]>firstMax{
				secondMax = firstMax
				secondIndex = firstIndex
				firstMax = array[i]
				firstIndex = i
			}else if array[i]!=0 && array[i]>secondMax{
				secondMax = array[i]
				secondIndex = i
			}
		}
		for j:=0;j<secondMax;j++{
			str = str+string(rune(firstIndex+97))+string(rune(secondIndex+97))
		}
		if secondMax == 0 && firstMax>1{
			return ""
		}else if secondMax == 0 && firstMax==1 {
			str = str +string(rune(firstIndex+97))
			strLen = strLen-firstMax
		}
		array[firstIndex] = array[firstIndex]-secondMax
		array[secondIndex] = 0
		strLen = strLen-secondMax*2
	}
	return str
}

官方解题思路一:用堆维护一个非空字符,每次取出两个字符拼接,其中涉及堆的概念和运用还需好好理解

var cnt [26]int

type hp struct{ sort.IntSlice }

func (h hp) Less(i, j int) bool  { return cnt[h.IntSlice[i]] > cnt[h.IntSlice[j]] }
func (h *hp) Push(v interface{}) { h.IntSlice = append(h.IntSlice, v.(int)) }
func (h *hp) Pop() interface{}   { 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) }

func reorganizeString(s string) string {
    n := len(s)
    if n <= 1 {
        return s
    }

    cnt = [26]int{}
    maxCnt := 0
    for _, ch := range s {
        ch -= 'a'
        cnt[ch]++
        if cnt[ch] > maxCnt {
            maxCnt = cnt[ch]
        }
    }
    if maxCnt > (n+1)/2 {
        return ""
    }

    h := &hp{}
    for i, c := range cnt[:] {
        if c > 0 {
            h.IntSlice = append(h.IntSlice, i)
        }
    }
    heap.Init(h)

    ans := make([]byte, 0, n)
    for len(h.IntSlice) > 1 {
        i, j := h.pop(), h.pop()
        ans = append(ans, byte('a'+i), byte('a'+j))
        if cnt[i]--; cnt[i] > 0 {
            h.push(i)
        }
        if cnt[j]--; cnt[j] > 0 {
            h.push(j)
        }
    }
    if len(h.IntSlice) > 0 {
        ans = append(ans, byte('a'+h.IntSlice[0]))
    }
    return string(ans)
}

复杂度分析

时间复杂度:O(nlog∣Σ∣+∣Σ∣),其中 nn 是字符串的长度,Σ 是字符集,在本题中字符集为所有小写字母,∣Σ∣=26。
遍历字符串并统计每个字母的出现次数,时间复杂度是 O(n)。

空间复杂度:O(∣Σ∣),其中Σ 是字符集,在本题中字符集为所有小写字母,∣Σ∣=26。这里不计算存储最终答案字符串需要的空间(以及由于语言特性,在构造字符串时需要的额外缓存空间),空间复杂度主要取决于统计每个字母出现次数的数组和优先队列。

官方思路二:基于计数的贪心算法

func reorganizeString(s string) string {
    n := len(s)
    if n <= 1 {
        return s
    }

    cnt := [26]int{}
    maxCnt := 0
    for _, ch := range s {
        ch -= 'a'
        cnt[ch]++
        if cnt[ch] > maxCnt {
            maxCnt = cnt[ch]
        }
    }
    if maxCnt > (n+1)/2 {
        return ""
    }

    ans := make([]byte, n)
    evenIdx, oddIdx, halfLen := 0, 1, n/2
    for i, c := range cnt[:] {
        ch := byte('a' + i)
        for c > 0 && c <= halfLen && oddIdx < n {
            ans[oddIdx] = ch
            c--
            oddIdx += 2
        }
        for c > 0 {
            ans[evenIdx] = ch
            c--
            evenIdx += 2
        }
    }
    return string(ans)
}

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/reorganize-string/solution/zhong-gou-zi-fu-chuan-by-leetcode-solution/
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值