题目
难度简单
给你一个混合了数字和字母的字符串 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)
}