leetcode-1417. 重新格式化字符串

121 阅读2分钟

题目

1417. 重新格式化字符串

难度简单

给你一个混合了数字和字母的字符串 s,其中的字母均为小写英文字母。

请你将该字符串重新格式化,使得任意两个相邻字符的类型都不同。也就是说,字母后面应该跟着数字,而数字后面应该跟着字母。

请你返回 重新格式化后 的字符串;如果无法按要求重新格式化,则返回一个 空字符串 。

示例 1:

输入: s = "a0b1c2"
输出: "0a1b2c"
解释: "0a1b2c" 中任意两个相邻字符的类型都不同。 "a0b1c2", "0a1b2c", "0c2a1b" 也是满足题目要求的答案。

示例 2:

输入: s = "leetcode"
输出: ""
解释: "leetcode" 中只有字母,所以无法满足重新格式化的条件。

示例 3:

输入: s = "1229857369"
输出: ""
解释: "1229857369" 中只有数字,所以无法满足重新格式化的条件。

思路

先扫描一遍字符串以统计输入字符串中字母和数字的个数,如果两者差的绝对值大于1,则无法满足格式化的条件,直接返回空串

如果可以满足格式化的条件,则将字母和数字交替放入结果字符串,数量多的字符类型放在奇数位

可以的进一步优化:不必额外单独存储字母和数字,生成结果字符串时直接利用双指针在原串上获取字符即可。实现部分的代码中额外分别存储了字母和数字字符,这都是没有必要的重复信息。

实现

func reformat(s string) string {
    var (
        digits []rune
        letters []rune
        ret []rune
        digitsFirst bool
        left string
    )
    

    for _, c := range s {
        if unicode.IsDigit(c) {
            digits = append(digits, c)
        } else {
            letters = append(letters, c)
        }
    }

    sub := len(digits) - len(letters)
    switch sub {
        case 1:
            digitsFirst = true
            left =  string(digits[len(digits)-1])
        case -1:
            left =  string(letters[len(letters)-1])
        case 0:
        default:
            return ""
    }
    
    for i := 0; i < len(digits) && i < len(letters); i++ {
        ret = append(ret, digits[i], letters[i])
    }

    if digitsFirst {
        return string(ret) + left
    }
    return left + string(ret)
}