LeetCode 1417: Reformat The String (Two Buckets + Alternating Merge)
LeetCode 1417GreedyToday we solve LeetCode 1417 - Reformat The String.
Source: https://leetcode.com/problems/reformat-the-string/
English
Problem Summary
Given a string containing lowercase letters and digits, rearrange it so adjacent characters have different types. Return any valid result, or empty string if impossible.
Key Insight
Split characters into two buckets: letters and digits.
If their counts differ by more than 1, answer is impossible.
Otherwise, start from the larger bucket and alternately append from both buckets.
Complexity Analysis
Time: O(n).
Space: O(n).
Reference Implementations (Java / Go / C++ / Python / JavaScript)
class Solution {
public String reformat(String s) {
StringBuilder letters = new StringBuilder();
StringBuilder digits = new StringBuilder();
for (char c : s.toCharArray()) {
if (Character.isDigit(c)) digits.append(c);
else letters.append(c);
}
int n = letters.length(), m = digits.length();
if (Math.abs(n - m) > 1) return "";
boolean letterFirst = n >= m;
StringBuilder ans = new StringBuilder(s.length());
int i = 0, j = 0;
while (i < n || j < m) {
if (letterFirst && i < n) ans.append(letters.charAt(i++));
if (!letterFirst && j < m) ans.append(digits.charAt(j++));
letterFirst = !letterFirst;
}
return ans.toString();
}
}func reformat(s string) string {
letters := make([]byte, 0)
digits := make([]byte, 0)
for i := 0; i < len(s); i++ {
c := s[i]
if c >= '0' && c <= '9' {
digits = append(digits, c)
} else {
letters = append(letters, c)
}
}
if abs(len(letters)-len(digits)) > 1 {
return ""
}
letterFirst := len(letters) >= len(digits)
ans := make([]byte, 0, len(s))
i, j := 0, 0
for i < len(letters) || j < len(digits) {
if letterFirst && i < len(letters) {
ans = append(ans, letters[i])
i++
}
if !letterFirst && j < len(digits) {
ans = append(ans, digits[j])
j++
}
letterFirst = !letterFirst
}
return string(ans)
}
func abs(x int) int {
if x < 0 {
return -x
}
return x
}class Solution {
public:
string reformat(string s) {
string letters, digits;
for (char c : s) {
if (isdigit(c)) digits.push_back(c);
else letters.push_back(c);
}
if (abs((int)letters.size() - (int)digits.size()) > 1) return "";
bool letterFirst = letters.size() >= digits.size();
string ans;
ans.reserve(s.size());
int i = 0, j = 0;
while (i < (int)letters.size() || j < (int)digits.size()) {
if (letterFirst && i < (int)letters.size()) ans.push_back(letters[i++]);
if (!letterFirst && j < (int)digits.size()) ans.push_back(digits[j++]);
letterFirst = !letterFirst;
}
return ans;
}
};class Solution:
def reformat(self, s: str) -> str:
letters = [c for c in s if c.isalpha()]
digits = [c for c in s if c.isdigit()]
if abs(len(letters) - len(digits)) > 1:
return ""
letter_first = len(letters) >= len(digits)
i = j = 0
out = []
while i < len(letters) or j < len(digits):
if letter_first and i < len(letters):
out.append(letters[i])
i += 1
if not letter_first and j < len(digits):
out.append(digits[j])
j += 1
letter_first = not letter_first
return "".join(out)var reformat = function(s) {
const letters = [];
const digits = [];
for (const c of s) {
if (c >= '0' && c <= '9') digits.push(c);
else letters.push(c);
}
if (Math.abs(letters.length - digits.length) > 1) return '';
let letterFirst = letters.length >= digits.length;
let i = 0, j = 0;
const out = [];
while (i < letters.length || j < digits.length) {
if (letterFirst && i < letters.length) out.push(letters[i++]);
if (!letterFirst && j < digits.length) out.push(digits[j++]);
letterFirst = !letterFirst;
}
return out.join('');
};中文
题目概述
给定只含小写字母和数字的字符串,重排后要求相邻字符类型不同(字母与数字交替)。若无法做到,返回空字符串。
核心思路
先把字符分成两个桶:字母桶和数字桶。
若两者数量差超过 1,则无解。
否则从数量较多的桶开始,两个桶交替取字符拼接即可。
复杂度分析
时间复杂度:O(n)。
空间复杂度:O(n)。
多语言参考实现(Java / Go / C++ / Python / JavaScript)
class Solution {
public String reformat(String s) {
StringBuilder letters = new StringBuilder();
StringBuilder digits = new StringBuilder();
for (char c : s.toCharArray()) {
if (Character.isDigit(c)) digits.append(c);
else letters.append(c);
}
int n = letters.length(), m = digits.length();
if (Math.abs(n - m) > 1) return "";
boolean letterFirst = n >= m;
StringBuilder ans = new StringBuilder(s.length());
int i = 0, j = 0;
while (i < n || j < m) {
if (letterFirst && i < n) ans.append(letters.charAt(i++));
if (!letterFirst && j < m) ans.append(digits.charAt(j++));
letterFirst = !letterFirst;
}
return ans.toString();
}
}func reformat(s string) string {
letters := make([]byte, 0)
digits := make([]byte, 0)
for i := 0; i < len(s); i++ {
c := s[i]
if c >= '0' && c <= '9' {
digits = append(digits, c)
} else {
letters = append(letters, c)
}
}
if abs(len(letters)-len(digits)) > 1 {
return ""
}
letterFirst := len(letters) >= len(digits)
ans := make([]byte, 0, len(s))
i, j := 0, 0
for i < len(letters) || j < len(digits) {
if letterFirst && i < len(letters) {
ans = append(ans, letters[i])
i++
}
if !letterFirst && j < len(digits) {
ans = append(ans, digits[j])
j++
}
letterFirst = !letterFirst
}
return string(ans)
}
func abs(x int) int {
if x < 0 {
return -x
}
return x
}class Solution {
public:
string reformat(string s) {
string letters, digits;
for (char c : s) {
if (isdigit(c)) digits.push_back(c);
else letters.push_back(c);
}
if (abs((int)letters.size() - (int)digits.size()) > 1) return "";
bool letterFirst = letters.size() >= digits.size();
string ans;
ans.reserve(s.size());
int i = 0, j = 0;
while (i < (int)letters.size() || j < (int)digits.size()) {
if (letterFirst && i < (int)letters.size()) ans.push_back(letters[i++]);
if (!letterFirst && j < (int)digits.size()) ans.push_back(digits[j++]);
letterFirst = !letterFirst;
}
return ans;
}
};class Solution:
def reformat(self, s: str) -> str:
letters = [c for c in s if c.isalpha()]
digits = [c for c in s if c.isdigit()]
if abs(len(letters) - len(digits)) > 1:
return ""
letter_first = len(letters) >= len(digits)
i = j = 0
out = []
while i < len(letters) or j < len(digits):
if letter_first and i < len(letters):
out.append(letters[i])
i += 1
if not letter_first and j < len(digits):
out.append(digits[j])
j += 1
letter_first = not letter_first
return "".join(out)var reformat = function(s) {
const letters = [];
const digits = [];
for (const c of s) {
if (c >= '0' && c <= '9') digits.push(c);
else letters.push(c);
}
if (Math.abs(letters.length - digits.length) > 1) return '';
let letterFirst = letters.length >= digits.length;
let i = 0, j = 0;
const out = [];
while (i < letters.length || j < digits.length) {
if (letterFirst && i < letters.length) out.push(letters[i++]);
if (!letterFirst && j < digits.length) out.push(digits[j++]);
letterFirst = !letterFirst;
}
return out.join('');
};
Comments