Day08:344.反转字符串、541.反转字符串Ⅱ、卡码网:54.替换数字、151.翻转字符串里的单词、卡码网:55.右旋转字符串
跟着卡哥训练营练了这些天感觉自己有一点进步了,今天的题几乎全自己写出来了!
344.反转字符串
该题看到的第一眼就想到了使用双指针法,已经形成习惯了属于是。
思路如下:
- 定义一个左指针指向字符串第一个位置,右指针指向字符串最后一个位置
- 接着进入while循环,循环终止条件为
left < right
或者left <= right
都可以(因为当left等于right时等同于没有操作),循环里把左指针指向的字符和右指针指向的字符交换位置,接着再left++; right--;
Java源代码如下:
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--;
}
}
}
541.反转字符串Ⅱ
该题我做的时候用的是一个比较笨的方法,我是定义了一个新字符串,一个一个把源字符串里的元素都操作后放入了新字符串里,虽然最后也是成功了但是我觉得肯定还有更高效的方法,于是去看了代码随想录的解析,看完之后发现直接在原来的字符串上动就可以了,我把问题给想复杂了。
解题思路如下:
-
因为题目是说每计数2k个字符,就反转前k个字符,所以定义的for循环每一步循环过后i都要加2k
-
然后在循环里面定义左右指针,左指针指向当前i,那右指针指向哪儿呢?因为题目说:
-
如果剩余字符少于
k
个,则将剩余字符全部反转。 -
如果剩余字符小于
2k
但大于或等于k
个,则反转前k
个字符,其余字符保持原样。
-
-
所以右指针我们需要比较字符串的长度和当前位置加k之后的长度,因为如果当前位置加k之后比字符串还长了,那么显然会报错;
Java源代码如下:
class Solution {
public String reverseStr(String s, int k) {
char[] ch = s.toCharArray();
for(int i = 0; i < ch.length; i += 2*k){
int left = i;
int right = Math.min(ch.length-1, i+k-1);
while(left < right){
char temp = ch[left];
ch[left] = ch[right];
ch[right] = temp;
left++;
right--;
}
}
return new String(ch);
}
}
卡码网:54.替换数字
第一次在卡哥的网站上做题,居然有代码补齐功能,爽!
第一眼看到这题时,思路一下就出来了,其实很简单,判断字符串里是数字的数,然后把数字替换成number
就行了,但是比较关键的是如何判断,我想到的一个判断方法是既然题目说了字符串只包含小写字母和数字,那么只需判断小写字母就行了,因为其他的都是数字,判断小写字母就简单了,如果当前字符减去字符a在0~25之间,那么该字符就是小写字母,我看代码随想录判断用的是Character封装类的一个isDigit方法,用哪个都可以。
Java源代码如下:
import java.util.Scanner;
class Main{
public static void main(String[] args){
Scanner in = new Scanner(System.in);
String s = in.nextLine();
StringBuffer result = new StringBuffer();
char[] ch = s.toCharArray();
for(int i = 0; i < ch.length; i++){
if(ch[i] - 'a' >= 0 && ch[i] - 'a' <= 25){
result.append(ch[i]);
continue;
}else{
result.append("number");
}
}
System.out.println(result.toString());
}
}
151.翻转字符串里的单词
这道题我最开始是用的一个超级笨的方法:我先是把源字符串去掉空格后把每个单词放入一个新字符串,在每个单词后面都加上一个空格,然后再把该字符串翻转了一遍,之后又把每个单词的字符翻转了一遍得到答案,过程重复且冗余,源代码如下:
class Solution {
public String reverseWords(String s) {
StringBuffer result = new StringBuffer();
char[] ch = s.toCharArray();
int i = 0,num = 0;
while(i < ch.length){
if(ch[i] != ' '){
StringBuffer buffer = new StringBuffer();
while(i < ch.length && ch[i] != ' '){
buffer.append(ch[i]);
i++;
}
result.append(buffer).append(" ");
num ++;
}else{
i++;
}
}
String preResult = result.deleteCharAt(result.length() - 1).toString();
String[] str = new String[num];
char[] cha = preResult.toCharArray();
int j = 0,k = 0;
while(j < cha.length){
if(cha[j] != ' '){
StringBuffer buf = new StringBuffer();
while(j < cha.length && cha[j] != ' '){
buf.append(cha[j]);
j++;
}
str[k++] = buf.toString();
}else{
j++;
}
}
int left = 0;
int right = num - 1;
while(left < right){
String temp = str[left];
str[left] = str[right];
str[right] = temp;
left++;
right--;
}
StringBuffer finallyResult = new StringBuffer();
for(int m = 0; m < num - 1; m++){
finallyResult.append(str[m]).append(" ");
}
finallyResult.append(str[num - 1]);
return finallyResult.toString();
}
}
我写完之后觉得这道题肯定还有更好的解法,于是我想到了另一个方法,就是不需要再新定义字符串,在原来的字符串中进行操作。
第一步先把传入的字符串左右翻转一遍,第二步再把每个单词的字符翻转一遍,最后去掉多余的空格就好了,虽然说起来很简单,但是实际要写代码的时候我发现被最后那步把多余的空格去掉给拦住了,因为我不知道如何不利用一个新字符串而去把多余的空格给去掉,于是我去看了代码随想录的解析,发现果然还是大佬多啊,代码随想录给的解析代码中关于去掉多余的空格我觉得写的超级好,源代码如下:(这里只有去掉多余空格的代码,完整代码详见代码随想录)
private StringBuilder removeSpace(String s) {
// System.out.println("ReverseWords.removeSpace() called with: s = [" + s + "]");
int start = 0;
int end = s.length() - 1;
while (s.charAt(start) == ' ') start++;
while (s.charAt(end) == ' ') end--;
StringBuilder sb = new StringBuilder();
while (start <= end) {
char c = s.charAt(start);
if (c != ' ' || sb.charAt(sb.length() - 1) != ' ') {
sb.append(c);
}
start++;
}
// System.out.println("ReverseWords.removeSpace returned: sb = [" + sb + "]");
return sb;
}
我觉得它最精彩的地方在于while循环里那个if判断,这个判断不但可以删除单词间多余空格,还可以让单词之间只留一个空格,实在是泰裤辣!
卡码网:55.右旋转字符串
真的是有些题想一会会就是会,不会就是不会,这道题我看了之后在草稿纸上实现了一下大致步骤后立马出了思路。
思路如下:
- 先把整体的字符串翻转一下
- 然后把前k个字符进行翻转
- 最后把后面
length-k
个字符翻转即可
Java源代码如下:
import java.util.Scanner;
class Main{
public static char[] rightSpin(String s, int k) {
char[] ch = s.toCharArray();
int left = 0;
int right = ch.length - 1;
while(left < right){
char temp = ch[left];
ch[left] = ch[right];
ch[right] = temp;
left++;
right--;
}
int lleft = 0;
int lright = k - 1;
while(lleft < lright){
char temp = ch[lleft];
ch[lleft] = ch[lright];
ch[lright] = temp;
lleft++;
lright--;
}
int rleft = k;
int rright = ch.length - 1;
while(rleft < rright){
char temp = ch[rleft];
ch[rleft] = ch[rright];
ch[rright] = temp;
rleft++;
rright--;
}
return ch;
}
public static void main(String[] args){
Scanner in = new Scanner(System.in);
int k = Integer.parseInt(in.nextLine());
String s = in.nextLine();
char[] result = rightSpin(s, k);
System.out.println(result);
}
}