题目与题解
344.反转字符串
题目链接:344.反转字符串
代码随想录题解:344.反转字符串
解题思路:
字符串就是一个数组,反转就是改变其顺序。方法很简单,设置两个指针,分别从字符串头部和尾部出发向中间走,每次交换一下头尾指针指向的字符,直到两个指针相遇。
class Solution {
public void reverseString(char[] s) {
for (int i = 0; i < s.length/2; i++) {
char temp = s[i];
s[i] = s[s.length - i - 1];
s[s.length - i - 1] = temp;
}
}
}
看完代码随想录之后的想法
while循环更好理解一点,^方式交换看不懂,不学了。
遇到的困难
无
541. 反转字符串II
题目链接:541. 反转字符串II
代码随想录题解:541. 反转字符串II
解题思路:
与反转字符串类似,但是加上了限制条件。可以用每2k个数作为一个数组单位,交换前k个数的值。
public String reverseStr(String s, int k) {
char[] string = s.toCharArray();
for (int i = 0; i < string.length; i = i + 2*k) {
int charLeft = string.length - i;
if (charLeft >= k) {
for (int j = i, m = 1; j < i + k/2; j++, m++) {
char temp = string[j];
string[j] = string[i+k-m];
string[i+k-m] = temp;
}
} else {
for (int j = i, m = 1; j < i + charLeft/2; j++, m++) {
char temp = string[j];
string[j] = string[string.length - m];
string[string.length - m] = temp;
}
}
}
return new String(string);
}
}
看完代码随想录之后的想法
随想录写法更简洁一点,不需要判断写两次for循环,只需找到实际需要交换的数组末尾,即可进行双指针运行交换。
public String reverseStr(String s, int k) {
char[] string = s.toCharArray();
for (int i = 0; i < string.length; i = i + 2*k) {
int charLeft = string.length - i;
int end = Math.min(string.length - 1, i + k - 1);
int begin = i;
while (begin < end) {
char temp = string[begin];
string[begin] = string[end];
string[end] = temp;
begin++;
end--;
}
}
return new String(string);
}
}
遇到的困难
由于Java的限制,String类型是不可修改的,因此需要用StringBuilder类型或char[]替换。写的时候,无论是for循环还是while循环,都要注意边界条件的取值是多少,避免多换或少换。
卡码网:54.替换数字
题目链接:卡码网:54.替换数字
代码随想录题解:卡码网:54.替换数字
解题思路:
先用StringBuilder类型替换输入的String,然后遍历其每一个字符元素进行修改。如果元素为数字,则删除该元素后用insert方法插入“number”,并且下一次遍历的指针向后移动6格。
import java.util.*;
public class ID54Kama {
public static void main (String[] args) {
/* code */
Scanner scanner = new Scanner(System.in);
String string = scanner.nextLine();
StringBuilder sb = new StringBuilder(string);
int i = 0;
while (i < sb.length()) {
if (sb.charAt(i) >= '0' && sb.charAt(i) <= '9') {
sb.deleteCharAt(i);
sb.insert(i, "number");
i += 6;
} else {
i++;
}
}
System.out.println(sb);
}
}
看完代码随想录之后的想法
不同语言会有一些自己的函数,可以方便使用,java的库函数更优秀,可以简化代码。这里的思路采用新建一个StringBuilder类型,根据string里面是否为数字,判断是将当前字符放入sb还是将number放入sb,更简单。
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String s = in.nextLine();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
if (Character.isDigit(s.charAt(i))) {
sb.append("number");
} else sb.append(s.charAt(i));
}
System.out.println(sb);
}
}
C++的方法利用了resize函数先扩展数组,然后再填充number。
遇到的困难
已经很久没有自己写过输入输出了,完全忘光。要记住java的输入是用scanner类型接收的,如果输入为字符串则用scanner.nextLine()接收,如果是整数则用scanner.nextInt()接收。
151.翻转字符串里的单词
题目链接:151.翻转字符串里的单词
代码随想录题解:151.翻转字符串里的单词
解题思路:
一开始想利用java自己的库函数,先用trim去除前后空格,再用split把单词分隔开后,把非空格的单词插入到新的string数组中,然后把每个单词reverse,最后将其拼成字符串输出。只能说,非常繁琐而且时间空间利用率都极低,后来放弃了这个想法。
稍微看了一眼随想录的思路,要求要原地修改数组,于是我就直接把它当成一个char数组去处理,先去除头尾的空格,再根据之前做过的移除元素的双指针法,去掉多余空格,得到新的数组start和end位置,然后再对其进行操作。
这题的核心思想是:反转单词,可以先反转整个字符串,再把里面的每个单词再反转一次,非常巧妙。我自己没有想到这个思路,得到提示以后才写下了正确的代码。
class Solution {
public String reverseWords(String s) {
char[] ss = s.toCharArray();
// 去除头尾的空格
int start = 0, end = ss.length - 1;
while (ss[start] == ' ') {
start++;
}
while (ss[end] == ' ' && end > start) {
end--;
}
// 去除中间的空格
int i = start+1, j = start+1;
while (j <= end) {
if (ss[j-1] == ' ' && ss[j] == ' ') {
j++;
} else {
ss[i] = ss[j];
i++;
j++;
}
}
end = i - 1;
// 反转单词 - 先反转整个字符串,再反转其中的每个单词
reverse(ss, start, end);
i = start;
j = start;
while (j <= end) {
while (ss[j] != ' ' && j < end) {
j++;
}
if (j == end) reverse(ss, i, j);
else reverse(ss, i, j - 1);
i = ++j;
}
return new String(ss, start, end - start + 1);
}
public void reverse(char[] chars, int start, int end) {
int i = start, j = end;
while (i < j) {
char temp = chars[i];
chars[i] = chars[j];
chars[j] = temp;
i++;
j--;
}
}
}
看完代码随想录之后的想法
这道题的本质是模拟,操作没有太多困难的地方,但是步骤较多,需要考虑的方方面面也比较多,要用耐心去完成。
同样随想录的方法更精简,移除多余空格时,采用for循环,也将i++融入到等式中,行数可以更少;在求解反转单词的每个下标时,我写的条件是ss[j] != ' ' && j < end,解答给的是ss[j] != ' ' || j == end,相比我的,就不用再判断一次j是否到end了,直接用reverse(ss, i, j - 1)就可以覆盖两种情况。
遇到的困难
审题最重要,做题要耐心。记住这题的思路,以后最好再练习几次。
55.右旋转字符串
题目链接:55.右旋转字符串
代码随想录题解:55.右旋转字符串
解题思路:
想复杂了,没想通,直接看答案。
看完代码随想录之后的想法
同样也是巧妙的利用多次反转解决长度不一的数组元素交换问题,了解了思路就很好写了。
import java.util.*;
public class ID55Kama {
public static void main (String[] args) {
/* code */
Scanner scanner = new Scanner(System.in);
int k = scanner.nextInt();
scanner.nextLine();
String s = scanner.nextLine();
char[] ss = s.toCharArray();
reverseString(ss, 0, ss.length - 1);
reverseString(ss, 0, k - 1);
reverseString(ss, k, ss.length - 1);
System.out.println(new String(ss));
}
public static void reverseString(char[] chars, int start, int end) {
int i = start, j = end;
while (i < j) {
char temp = chars[i];
chars[i] = chars[j];
chars[j] = temp;
i++;
j--;
}
}
}
遇到的困难
其实这道题思路几乎跟上一道一样,但是没有这个sense,很难想到方便的方法。下次要记住,碰到这种涉及到花式反转的题,先整体再局部反转是个好方法。
另外,java的scanner应用还是不熟,碰到这种先输入数字再输入字符串的就有点懵了。百度了一下,才知道可以用多写一条scanner.nextLine()的方法,就可以接收下一行的字符串了。
今日收获
字符串相关的题多为模拟实际操作的题,相比之下涉及到的数学公式较少,写起来也不会很复杂,但是操作一多,代码量就会上去。关键是要有耐心去一步步想,把每一步落实到代码上。