代码随想录算法训练营第8天 | 字符串部分:344. 反转字符串 , 541. 反转字符串 II, 剑指 Offer 05. 替换空格, 151. 反转字符串中的单词,剑指 Offer 58 - II. 左旋转字符串
字符串部分
344. 反转字符串
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
思路:由于是使用O(1)的额外空间解决问题,所以不能创建新的数组,只能在原始的数组上面改动,所以采用双指针的方法来实现
public void reverseString(char[] s) {
int left=0,right=s.length-1;
while(left<right){
char temp=s[left];
s[left]=s[right];
s[right]=temp;
right--;
left++;
}
}
541. 反转字符串 II
给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。如果剩余字符少于 k 个,则将剩余字符全部反转。如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
思路:数组的翻转操作还是和之前的一样,主要是剩余字符的问题,步长等于2k,当剩下的小于k时,全部翻转,其他情况不变
注意:想着把2k取余的部分留出来,然后在for循环的外面进行判断,但是这样的话,如果剩余的部分为k-2k之间,就会造成这部分的重复翻转也就是不翻转,所以将翻转的结束位置设置为两者中的最小值
补充:字符串—>数组 toCharArray();
数组------>字符串 new String(字符数组);
数组------>字符串 String.valueOf(字符数组);
public String reverseStr(String s, int k) {
char[] res=s.toCharArray();
int sur=0;
for(int i=0;i<res.length;i +=2*k){
//这边的问题
StringRev(res,i,Math.min(i+k-1,res.length-1));
sur=i;
}
String res1=new String(res);
return res1;
}
public void StringRev(char[] s,int start,int end){
int left=start,right=end;
while(left<right){
char temp=s[left];
s[left]=s[right];
s[right]=temp;
right--;
left++;
}
}
剑指 Offer 05. 替换空格
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
样例:
输入:s = “We are happy.”
输出:“We%20are%20happy.”
思路:通过数组来实现的话需要先遍历字符串s,根据空格的个数确定数组的长度,然后一次填入;数组的实现不会写(答案说是采用双指针的写法)
通过StringBuffer实现的话,就是遇到空格就填入,不需要提前计算空格;
public String replaceSpace(String s) {
StringBuffer res=new StringBuffer();
for(int i=0;i<s.length();i++){
if(s.charAt(i)==' '){
res.append("%20");
}else{
res.append(s.charAt(i));
}
}
return res.toString();
}
151. 反转字符串中的单词
给你一个字符串 s ,请你反转字符串中 单词 的顺序。单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。
样例:
输入:s = “the sky is blue”
输出:“blue is sky the”
思路:采用StringBuffer,从字符串的后面开始遍历,从后往前遍历,因为需要翻转,需要使用双指针,因为涉及到一个字符串的移动
public String reverseWords(String s) {
StringBuffer sb=new StringBuffer();
int left=0,right=0;
//首先对字符串前后的空格进行处理
//先不管空格
for(int i=s.length()-1;i>=0;i--){
//因为这边没说会存在多个空格的情况,所以感觉这边不用while也可以,使用一个if感觉就够了,最后还是使用了,题目中并没有说不存在多个连续空格的情况
/*while(i>=0 && s.charAt(right)==' '){
i--;
}
*/
right=i;
while(i>=0 && s.charAt(i)==' '){
i--;
right--;//更新最右边界
}
left=i;//把left的更新放在下面,或者放在上一个while里面,因为是确定不是空格的右边界,
while(i>=0 &&s.charAt(left)!=' '){
left--;//更新最左边界的左边一个
i--;
}
//这边的理解感觉有点问题
//这边刚开始的思路是不加if中的判断,但是总是在转换后的字符串的第一个位置出现空格
//在if里面之前还想添加i>=0这个选项,但此时仅仅是对最后一个空格需不需要加入的判断,而且此时i一定是小于0的,所以如果加上的话可能会导致最后一个字符串都没了
//这个判断是因为哪怕是只有一个字符,left和right也是不相等的,但是如果是空格的话,left=right,所以这个判断是为了防止转换后第一个位置空格的出现
if(left<right){
sb.append(s,left+1,right+1);
sb.append(' ');
}
}
sb.deleteCharAt(sb.length()-1);
return sb.toString();
}
总结:基础好差,数组转换成字符串完全记不得,字符串转换成数组还行,然后就是StringBuffer中对于某个位置元素的删除
数组转换成字符串:new String(res); String.valueOf(res);
StringBuffer中某个位置元素的删除:deleteCharAt(i);
StringBuffer中某个范围元素的删除:delete(int start,int end);左闭右开
StringBuffer中某个位置元素的添加:append(i); 是错误的
StringBuffer中某个范围元素的添加:append(int start,int end);左闭右开 是错误的
理解错了,StringBuffer中的append方法是实现在原始字符串的后面继续添加,阴差阳错使用对了
StringBuffer是线程安全的
之前看漏了一个题目,今天补上
剑指 Offer 58 - II. 左旋转字符串
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。
思路:创建一个新的StringBuilder对象保存转换之后的字符串,从n位置开始添加,遍历到结尾之后,再添加0位置到n-1位置的元素
public String reverseLeftWords(String s, int n) {
StringBuilder sb=new StringBuilder();
int len=s.length();
for(int i=n;i<len;i++){
sb.append(s.charAt(i));
}
for(int i=0;i<n;i++){
sb.append(s.charAt(i));
}
return sb.toString();
}