翻转字符串中的单词 III
- https://leetcode.cn/problems/reverse-words-in-a-string-iii/
描述
给定一个字符串 s ,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。
示例 1:
输入:s = "Let's take LeetCode contest"
输出:"s'teL ekat edoCteeL tsetnoc"
示例 2:
输入: s = "God Ding"
输出:"doG gniD"
提示:
- 1 <= s.length <= 5 * 10410^4104
- s 包含可打印的 ASCII 字符。
- s 不包含任何开头或结尾空格。
- s 里 至少 有一个词。
- s 中的所有单词都用一个空格隔开。
Typescript 版算法实现
1 )方案1
function reverseWords(s: string): string {
return s.length ? (s.match(/[\S]+/g) ?? []).map((item: string) => {
return item.split('').reverse().join('')
}).join(' ') : ''
};
console.log(reverseWords("Let's take LeetCode contest"));
- 不太推荐正则在算法中使用
2 ) 方案2
function reverseWords2(s: string): string {
if (!s.length) return ''
return s.split(' ').map((item:string) => {
return item.split('').reverse().join('')
}).join(' ')
}
console.log(reverseWords2("Let's take LeetCode contest"));
- 推荐
3 ) 方案3
function reverseWords3(s: string): string {
if (!s.length) return ''
return s.split(/\s/g).map((item: string) => {
return item.split('').reverse().join('')
}).join(' ')
}
console.log(reverseWords3("Let's take LeetCode contest")) // blue is sky the
- 不太推荐正则在算法中使用,可通过
4 ) 方案4
function reverseWords4(s: string): string {
if (!s.length) return ''
return (s.match(/[\w']+/g) ?? []).map((item: string) => {
return item.split('').reverse().join('')
}).join(' ')
}
console.log(reverseWords4("Let's take LeetCode contest"))
- 不太推荐正则在算法中使用,这个算法有问题的,部分 case 无法通过
- 注意这里的方案4,是有问题的,能满足示例字符串,但是满足不了一些特殊字符串,有一些英语句子中可以加一些特指字符,比如 @,$, \ 等,语法和写法上会有区别,最简单的来说 , .等字符都没有囊括在内
- 如果非要用 \w 并手动加符号呢?
- 理论上可以写成字符集,比如 [\w<>(),],但你必须穷举所有可能出现的符号,这既不现实也不优雅。所以 直接换用 \S 或 split(’ ') 才是正确的选择。
5 )方案5
function reverseWords5(s: string): string {
const words = s.split(' ');
for (let i = 0; i < words.length; i++) {
words[i] = reverseWord(words[i]);
}
return words.join(' ');
}
function reverseWord(word: string): string {
let chars = word.split('');
let left = 0;
let right = chars.length - 1;
while (left < right) {
[chars[left], chars[right]] = [chars[right], chars[left]];
left++;
right--;
}
return chars.join('');
}
console.log(reverseWords5("Let's take LeetCode contest"));
- 上述是使用双指针的方式来转换
- 这种实际上性能并不高,从算法结构上来看,就不是很高,字符串被切分进行交换
- 没有方案2好,用来扩展思路
相关api
const { split, match } = String.prototype
const { map, reverse, join } = Array.prototype
总结
- 注意边界非空判断
- 将字符串转换成数组,这里是一维数组
- 在数组内的每个字符串元素转换成数组,这里是第二维数组
- 在单个字符串数组元素借助reverse这个api进行反转
- 将单个字符串数组元素再次转换成字符串元素
- 将处理好二维数组元素转换好的字符串在一维数组内作为元素返回
- 注意:使用for循环来做,反而麻烦,代码量大,尽量不用
Python3 版算法实现
1 )简洁版本
class Solution:
def reverseWords(self, s):
return " ".join(word[::-1] for word in s.split(" "))
2 )使用 enumerate
class Solution:
def reverseWords(self, s: str) -> str:
lt = s.split()
# 使用 enumerate 将数组转换成 枚举结构
for i, w in enumerate(lt):
lt[i] = w[:: -1] # 单位内反转
return " ".join(lt) # 转换成字符串
Golang 版算法实现
1 )字符串和数组的组合
func reverseWords(s string) string {
// 拆分数组
words := strings.Split(s, " ")
// 倒序输出
for i := 0; i < len(words); i++ {
words[i] = reverse(words[i])
}
// 最终结果
return strings.Join(words, " ")
}
// 对字符串进行反转
func reverse(word string) string {
// 转成数组
ans := []byte(word)
// 获取前后索引
l, r := 0, len(ans)-1
// 前后翻转
for l < r {
ans[l], ans[r] = ans[r], ans[l]
l++
r--
}
// 获取结果
return string(ans)
}
Java 版算法实现
1 ) 正则匹配与拼接
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main1 {
public static String reverseWords(String s) {
if (s.isEmpty()) {
return "";
}
Pattern pattern = Pattern.compile("[\\S]+");
Matcher matcher = pattern.matcher(s);
List<String> reversedWords = new ArrayList<>();
while (matcher.find()) {
String word = matcher.group();
reversedWords.add(new StringBuilder(word).reverse().toString());
}
return String.join(" ", reversedWords);
}
public static void main(String[] args) {
System.out.println(reverseWords("Let's take LeetCode contest"));
}
}
算法说明:
- 正则提取:使用正则表达式
[\S]+匹配并提取字符串中所有由非空字符组成的单词。 - 逐个反转:遍历匹配到的单词,利用
StringBuilder的reverse()方法对每个单词进行反转。 - 重新拼接:将反转后的单词存入列表,最后使用空格作为分隔符,将所有单词重新拼接成完整的字符串。
2 ) 字符串分割与拼接 (String Splitting and Concatenation)
public class Main2 {
public static String reverseWords2(String s) {
if (s.isEmpty()) {
return "";
}
String[] words = s.split(" ");
StringBuilder result = new StringBuilder();
for (int i = 0; i < words.length; i++) {
result.append(new StringBuilder(words[i]).reverse().toString());
if (i < words.length - 1) {
result.append(" ");
}
}
return result.toString();
}
public static void main(String[] args) {
System.out.println(reverseWords2("Let's take LeetCode contest"));
}
}
算法说明:
- 字符串分割:使用
split(" ")方法按空格将原字符串分割成单词数组。 - 逐个反转:遍历单词数组,利用
StringBuilder的reverse()方法对每个单词进行反转。 - 重新拼接:将反转后的单词依次追加到结果
StringBuilder中,并在单词之间手动添加空格分隔符,最后返回拼接好的完整字符串。
3 ) 空白分割与过滤拼接 (Whitespace Splitting and Filtered Concatenation)
public class Main3 {
public static String reverseWords(String s) {
if (s.isEmpty()) {
return "";
}
String[] words = s.split("\\s");
StringBuilder result = new StringBuilder();
for (int i = 0; i < words.length; i++) {
if (!words[i].isEmpty()) {
result.append(new StringBuilder(words[i]).reverse().toString());
if (i < words.length - 1) {
result.append(" ");
}
}
}
return result.toString();
}
public static void main(String[] args) {
System.out.println(reverseWords("Let's take LeetCode contest"));
}
}
算法说明:
- 空白分割:使用正则表达式
\\s按空白字符将原字符串分割成数组。 - 过滤空串:遍历数组时,跳过因连续空格产生的空字符串,仅处理有效单词。
- 反转与拼接:利用
StringBuilder反转有效单词,将其追加到结果中,并在单词之间手动添加空格分隔符,最后返回完整字符串。
4 ) 正则匹配与拼接 (Regex Matching and Concatenation)
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class Solution {
public String reverseWords(String s) {
if (s.isEmpty()) {
return "";
}
// Pattern pattern = Pattern.compile("[\\w']+"); // 存在错误!
Pattern pattern = Pattern.compile("\\S+"); // 可通过!
Matcher matcher = pattern.matcher(s);
List<String> reversedWords = new ArrayList<>();
while (matcher.find()) {
String word = matcher.group();
reversedWords.add(new StringBuilder(word).reverse().toString());
}
return String.join(" ", reversedWords);
}
}
算法策略名称:
算法说明:
- 正则提取:使用正则表达式
\S+匹配并提取字符串中所有由非空格字符组成的单词。 - 逐个反转:遍历匹配到的单词,利用
StringBuilder的reverse()方法对每个单词进行反转。 - 重新拼接:将反转后的单词存入列表,最后使用空格作为分隔符,将所有单词重新拼接成完整的字符串。
- 这个就是 策略 1 对照不可用的 正则
5 ) 分割与双指针反转 (Splitting and Two-Pointer Reversal)
public class Main5 {
public static String reverseWords(String s) {
String[] words = s.split(" ");
for (int i = 0; i < words.length; i++) {
words[i] = reverseWord(words[i]);
}
return String.join(" ", words);
}
public static String reverseWord(String word) {
char[] chars = word.toCharArray();
int left = 0;
int right = chars.length - 1;
while (left < right) {
char temp = chars[left];
chars[left] = chars[right];
chars[right] = temp;
left++;
right--;
}
return new String(chars);
}
public static void main(String[] args) {
System.out.println(reverseWords("Let's take LeetCode contest"));
}
}
算法说明:
- 字符串分割:使用
split(" ")方法按空格将原字符串分割成单词数组。 - 双指针反转:遍历单词数组,对每个单词使用左右双指针向中间靠拢的方式,交换字符实现反转。
- 重新拼接:使用
String.join方法将反转后的单词数组用空格重新拼接成完整的字符串。
299



被折叠的 条评论
为什么被折叠?



