代码随想录算法训练营第八天 | LeetCode 344.反转字符串 541. 反转字符串II 剑指Offer 05.替换空格 151.翻转字符串里的单词 剑指Offer58-II.左旋转字符
一、 LeetCode 344.反转字符串
1. 题目链接
2. 学习资料:
3. 思路
- 和反转链表的思想一样,也是用双指针
- 写一个交换函数
- 左指针指向数组的初始位置,右指针指向数组的末位索引位置
- 每次交换完成左指针++,右指针–。
- 当左指针的值 > =右指针的值时停止循环。
4. 代码
class Solution {
public void reverseString(char[] s) {
int left =0;
int right = s.length-1;
while(left<right){
swap(s,left,right);
left++;
right--;
}
}
public void swap(char[]s,int index1 ,int index2){
char temp = s[index1];
s[index1] = s[index2];
s[index2] = temp;
}
}
二、 LeetCode 541. 反转字符串II
1. 题目链接
2. 学习资料:
3. 思路
4. 代码
class Solution {
//题目的意思其实概括为 每隔2k个反转前k个,尾数不够k个时候全部反转
public String reverseStr(String s, int k) {
char[] c = s.toCharArray();
for(int i=0;i<c.length;i+=2*k){
int start = i;
//判断尾数是否还有k个位置,来决定end指针的位置
int end = Math.min(c.length-1,start+k-1);
while(start < end){
swap(c,start,end);
start++;
end--;
}
}
return new String(c);
}
public void swap(char[] c, int index1,int index2){
char temp = c[index1];
c[index1] = c[index2];
c[index2] = temp;
}
}
三、 剑指Offer 05.替换空格
1. 题目链接
2. 学习资料:
3. 思路
此时算上本题,我们已经做了七道双指针相关的题目了分别是:
27.移除元素
15.三数之和
18.四数之和
206.翻转链表
142.环形链表II
344.反转字符串
4. 代码
class Solution {
public String replaceSpace(String s) {
if(s.length() == 0 || s == null){
return s;
}
StringBuilder sb = new StringBuilder();
//双指针法第一步,先扩容字符串长度大小,为空格数量的两倍
for(int i =0; i < s.length();i++){
if(s.charAt(i) == ' '){
sb.append(" ");
}
}
if(sb.length() == 0){
return s;
}
int left = s.length()-1;
s += sb.toString();
int right = s.length()-1;
char[] ch = s.toCharArray();
while(left >= 0){
if(ch[left] == ' '){
ch[right--] = '0';
ch[right--] = '2';
ch[right] = '%';
}else{
ch[right] = ch[left];
}
right--;
left--;
}
return new String(ch);
}
}
四、 LeetCode 151.翻转字符串里的单词
1. 题目链接
2. 学习资料:
3. 思路
- 倒序遍历字符串,记录单词的左右索引为i,j
- 移动指针i,直到遇到空格停止,这时候 i+1 到 j 这个位置就是一个单词的位置了
- 将每一个单词加入到返回结果的变量中
4. 代码
class Solution {
public String reverseWords(String s) {
//去除字符串首尾空格
s = s.trim();
int j = s.length()-1;
int i = j;
StringBuilder sb = new StringBuilder();
while(i>=0){
//倒着查找单词的首字母,遇到空格说明这个位置的下一个位置就是后边单词的起始位置
while(i>=0 && s.charAt(i) != ' '){
i--;
}
//将单词添加进结果中
sb.append(s.substring(i+1,j+1)+" ");
//让i向前移动寻找下一个单词的末位字幕
while(i>=0 && s.charAt(i) == ' '){
i--;
}
//移动j指针到i处
j=i;
}
return sb.toString().trim();
}
}
五、 LeetCode 剑指Offer58-II.左旋转字符
1. 题目链接
2. 学习资料:
3. 思路
- 先把整个字符串翻转
- 再翻转字符串从0到倒数第n个位置前一个位置
- 再翻转字符串从倒数第n个位置到最后
4. 代码
class Solution {
public String reverseLeftWords(String s, int n) {
char[] ch = s.toCharArray();
//先把整个字符串翻转
reverse(ch,0,ch.length-1);
//再翻转字符串从0到倒数第n个位置的前一个位置
reverse(ch,0,ch.length-1-n);
//再翻转字符串从倒数第n个位置到最后
reverse(ch,ch.length-n,ch.length-1);
return new String(ch);
}
//这里的两个值的交换很有意思,都不需要用一个额外变量了
// 举个例子 a^b a异或b会得到一个值 -> a^b
// a^b 这个值再异或一下b 也就是 a^b^b, 这个值是a 因为一个数和自己异或就会变为0
// 但是任何数和0进行异或运算得出的值还是自己 因此 a^b^b这个操作的最终结果变回了a
//因此我们用了这个异或运算的原理,可以进行两个数的交换
public void reverse(char[] s,int left,int right){
while(left<right){
s[left] ^= s[right];
s[right] ^= s[left];
s[left] ^= s[right];
left++;
right--;
}
}
}