代码随想录算法训练营 Day8 | 字符串 |344.反转字符串、541. 反转字符串II、剑指Offer 05.替换空格、151.翻转字符串里的单词、剑指Offer58-II.左旋转字符串
继续补打卡,补博客。。。。
344. 反转字符串
有库函数的语言,一行代码reverse就完事。。。或者直接切片倒过来就行
当然如果真直接用库函数那么做本题就失去其意义了,这里还是不用库函数去实现
双指针思路,左右指针向中间靠齐,交换左右指针(没看题解直接就秒写出来的,一次就ac没有debug有点受宠若惊。。。)
java没有swap可以用只能自己实现
class Solution {
public void reverseString(char[] s) {
int left = 0;
int right = s.length - 1;
while(left < right){
char temp = s[left];
s[left] = s[right];
s[right] = temp;
left++;
right--;
}
}
}
swap用异或实现
class Solution {
public void reverseString(char[] s) {
int l = 0;
int r = s.length - 1;
while (l < r) {
s[l] ^= s[r]; //构造 a ^ b 的结果,并放在 a 中
s[r] ^= s[l]; //将 a ^ b 这一结果再 ^ b ,存入b中,此时 b = a, a = a ^ b
s[l] ^= s[r]; //a ^ b 的结果再 ^ a ,存入 a 中,此时 b = a, a = b 完成交换
l++;
r--;
}
}
}
541. 反转字符串II
最近写模拟题都很抽象,自己的思路总是非常奇特罗嗦,都调用了库函数去实现反转写出来的代码还那么复杂
自己第一次写的版本:
class Solution {
public String reverseStr(String s, int k) {
StringBuilder sb ;
StringBuilder resSb = new StringBuilder();
ArrayList<String> res = new ArrayList<>();
int len = s.length();
int end = 0;;
for(int i = 0; i < len; i+= (2*k)){
if(i + (2*k) > len) break;
end = i + (2*k);
sb = new StringBuilder(s.substring(i, i + k));
res.add(sb.reverse().toString());
res.add(s.substring(i + k, end));
}
System.out.println(res.toString());
int lastLen = len - end;
if(lastLen < k){
sb = new StringBuilder(s.substring(end));
res.add(sb.reverse().toString());
}else if (lastLen < 2*k && lastLen >= k){
sb = new StringBuilder(s.substring(end,end + k));
res.add(sb.reverse().toString());
res.add(s.substring(end + k));
}
for(String str : res){
resSb.append(str);
}
return resSb.toString();
}
}
双指针实现翻转,然后模拟过程
看题解后重写的:
class Solution {
public String reverseStr(String s, int k) {
char[] ch = s.toCharArray();
int len = s.length();
for(int i = 0; i < s.length(); i+=(2*k)){
if(len - i < k){
reverseCh(ch,i,len - 1);
}else {
reverseCh(ch,i,i + k -1);
}
}
return String.valueOf(ch);
}
public void reverseCh(char[] ch, int l ,int r){
while(l < r){
char temp = ch[l];
ch[l] = ch[r];
ch[r] = temp;
l++;
r--;
}
}
}
剑指 Offer 05. 替换空格
调用库函数split一行代码AC
class Solution {
public String replaceSpace(String s) {
return s.replace(" ","%20");
}
}
当然这样没啥意义,还是自己模拟实现。不过也还是简单,遍历遇到空格时加一个%20就可以了
java中的string不允许更改,所以只能借助StringBuilder
class Solution {
public String replaceSpace(String s) {
StringBuilder sb = new StringBuilder();
for(int i =0; i < s.length(); i++){
if(s.charAt(i) == ' '){
sb.append("%20");
continue;
}
sb.append(s.charAt(i));
}
return sb.toString();
}
}
151. 反转字符串中的单词
java中String不可变,没法用O(1)原地修改
1、使用split解决:
string类的split方法的使用:
split() 方法根据匹配给定的正则表达式来拆分字符串。
注意: . 、 $、 | 和 * 等转义字符,必须得加 \。
注意:多个分隔符,可以用 | 作为连字符。
public String[] split(String regex, int limit)
以一个空格分割:
str.split("\\s");
以多个空格分割:
str.split("\\s+");
本题代码:
class Solution {
public String reverseWords(String s) {
List<String> list = Arrays.asList(s.trim().split("\\s+"));
Collections.reverse(list);
return String.join(" ",list);
}
}
2、不用split解决,双指针解法:
来源于力扣题解:
class Solution {
public String reverseWords(String s) {
char[] charArray=s.toCharArray();
int left=0,right=s.length()-1;
// 清除字符串两边的空格
// 清除左边
while(charArray[left]==' '){
left++;
}
// 清除右边
while(charArray[right]==' '){
right--;
}
StringBuilder sb=new StringBuilder();
// 开始添加单词
while(left<=right){
int index=right;
// index 向左遍历找到第一个空格
while(index>=left&&charArray[index]!=' '){
index--;
}
// 现在 index 已经找到第一个空格,i=index+1 后移到字符串出现的位置
// 添加字符串
for(int i=index+1;i<=right;i++){
sb.append(charArray[i]);
}
// 如果不是最后一个单词,就添加空格
if(index>left) sb.append(' ');
// 使用 index 指针 跳过中间可能出现的空格
while(index>=left&&charArray[index]==' '){
index--;
}
// 把 right 放到下一个单词出现的位置,继续循环
right=index;
}
return sb.toString();
}
}
剑指 Offer 58 - II. 左旋转字符串
用库函数substring
class Solution {
public String reverseLeftWords(String s, int n) {
StringBuilder sb = new StringBuilder();
sb.append(s.substring(n)).append(s.substring(0,n));
return sb.toString();
}
}
为了让本题有点难度,不调用库函数,不借助新的字符串解决
实现reverse函数,然后:
1. 先把第一个区间反转,再把第二个区间反转
2. 再把整体反转
感觉这种做法自己挺难想得到
class Solution {
public String reverseLeftWords(String s, int n) {
StringBuilder sb = new StringBuilder(s);
sb = reverseStr(sb , 0 , n - 1 );
sb = reverseStr(sb , n , s.length() - 1);
sb = reverseStr(sb , 0 , s.length() - 1);
return sb.toString();
}
public StringBuilder reverseStr(StringBuilder sb , int l ,int r){
while(l < r){
char temp = sb.charAt(l);
sb.setCharAt(l,sb.charAt(r));
sb.setCharAt(r,temp);
l++;
r--;
}
return sb;
}
}