得到回文串的最少操作次数
难度:
标签:
题目描述
代码结果
运行时间: 40 ms, 内存: 16.2 MB
/*
* 思路:
* 1. 使用双指针法,从字符串的两端向中间遍历。
* 2. 如果两端字符相同,则移动指针。
* 3. 如果不同,则需要在左指针右侧或者右指针左侧找到与另一端匹配的字符,
* 然后交换位置。每次交换位置都计数一次操作次数。
* 4. 使用Java Stream操作字符串数组。
* 5. 重复上述步骤,直到字符串变成回文串。
*/
import java.util.stream.IntStream;
import java.util.stream.Collectors;
import java.util.List;
import java.util.Arrays;
public class SolutionStream {
public int minMovesToMakePalindrome(String s) {
List<Character> list = s.chars().mapToObj(e -> (char)e).collect(Collectors.toList());
int left = 0, right = s.length() - 1;
int moves = 0;
while (left < right) {
if (list.get(left) == list.get(right)) {
left++;
right--;
} else {
int l = right;
while (l > left && !list.get(l).equals(list.get(left))) {
l--;
}
if (l == left) { // swap left with left+1
swap(list, left, left + 1);
moves++;
} else { // swap list.get(l) to right
while (l < right) {
swap(list, l, l + 1);
l++;
moves++;
}
left++;
right--;
}
}
}
return moves;
}
private void swap(List<Character> list, int i, int j) {
char temp = list.get(i);
list.set(i, list.get(j));
list.set(j, temp);
}
}
解释
方法:
这个题解实现了一个递归的方法来将字符串转换为回文串。首先,检查字符串的第一个字符在字符串中最后一次出现的位置。如果这个字符只出现一次(即在字符串的开始位置),则这个字符是回文中心,需要移动到字符串的中心位置,这将消耗 n/2 次操作(n 是字符串的长度)。否则,如果字符在末尾之前的位置出现,将这个字符通过交换移动到末尾,然后递归地在剩余的子字符串(移除了当前处理的两个字符)上应用同样的过程。继续这个过程直到字符串长度小于或等于2,这时不需要更多的操作。通过逐步将匹配的字符移动到开头和结尾,逐渐构建出回文字符串。
时间复杂度:
O(n^2)
空间复杂度:
O(n^2)
代码细节讲解
🦆
在解法中,为什么当第一个字符只出现一次时,将其移动到字符串中心而不是其他位置?
▷🦆
在代码中,为什么选择从字符串的第一个字符开始查找并处理,而不是从中间或其他位置开始?
▷🦆
当递归处理中间部分的字符串时,移除两端已处理的字符后的新字符串是否总是保证能变成回文串?
▷🦆
如何处理字符串长度为奇数时,中心字符的特殊情况?
▷