字符串
- 简介
- [简单] 344. 反转字符串
- [简单] 541. 反转字符串 II
- [中等] 151. 反转字符串中的单词
简介
记录一下自己刷题的历程以及代码。写题过程中参考了 代码随想录。会附上一些个人的思路,如果有错误,可以在评论区提醒一下。
[简单] 344. 反转字符串
原题链接
方法①:
class Solution {public void reverseString(char[] s) {for(int i = 0; i < s.length / 2; i++){swap(s, i,s.length - 1 - i);}}private void swap(char[] s, int i, int j){char temp = s[i];s[i] = s[j];s[j] = temp;}
}
方法②:
class Solution {public void reverseString(char[] s) {int i = 0;while(i < s.length - 1 - i){swap(s, i,s.length - 1 - i);i++;}}private void swap(char[] s, int i, int j){char temp = s[i];s[i] = s[j];s[j] = temp;}
}
[简单] 541. 反转字符串 II
原题链接
一开始想到比较差的方法:就是给到一个新的StringBuilder,然后按照结果的顺序依次再加入到StringBuilder中去,时间复杂度比较高,因为对那一部分不需要转置的字符也做了处理。
public String reverseStr(String s, int k) {StringBuilder sb = new StringBuilder(s.length());int over = -1; //标记已经完成处理的下标for (int i = 0; i < s.length(); i++) {if (i - over == 2 * k) {for (int j = over + k; j > over; j--) {sb.append(s.charAt(j));}for (int j = over + k + 1; j <= over + 2 * k; j++) {sb.append(s.charAt(j));}over = over + 2 * k;}}if(s.length() - 1 - over < k){for (int j = s.length() - 1; j > over; j--) {sb.append(s.charAt(j));}}else{for (int j = over + k; j > over; j--) {sb.append(s.charAt(j));}for (int j = over + k + 1; j < s.length(); j++) {sb.append(s.charAt(j));}}return sb.toString();}
这里首先提取了反转部分的代码,看起来更清晰,同时,也避开了对不需要转换的那一部分做处理的时间复杂度,效率更高
class Solution {public String reverseStr(String s, int k) {char[] c = s.toCharArray();int i = 2 * k - 1;int n = s.length();for (; i < n; i += 2 * k) {reverse(c, i-2*k+1, i-k);}if(i-2*k+1 < n) {reverse(c, i - 2 * k + 1, n - 1 < i - k ? n - 1 : i - k);}return new String(c);}private void reverse(char[] c, int left, int right){while(left < right){char temp = c[left];c[left] = c[right];c[right] = temp;left++;right--;}}
}
[中等] 151. 反转字符串中的单词
原题链接
总共分三步:删除空格,整体反转,单词反转。
deleteSpace():删除空格,先是删除后置空格,删除前置空格,再删除中间的空格,因为中间的空格需要保留一个,与删除前置后置逻辑上不同
使用StringBuilder类的话需要注意:
①:delete函数的右边界end对应下标并不会被删除,比如sb.delete(5,8)
,删除的是5,6,7
下标对应元素。
②:先删除前导空格的话,会导致整个字符串的所有下标都左移,不利于判断,先删除后置空格则没有这个问题。
//先删除后置再删除前置
if(r + 1 < s.length() - 1) sb = sb.delete(r + 1, s.length()); //删除后置空格
if(l > 0) sb = sb.delete(0, l); //删除前导空格
③:StringBuilder使用一个String类型构造的时候,分配的空间不完全是String本身的长度,所以在delete操作中,删除右边空格的end边界应该是String的长度边界,而不是StringBuilder的。
class Solution {public String reverseWords(String s) {StringBuilder sb = deleteSpace(s);sb = reverse(sb, 0, sb.length()-1);int start = 0;int i = 0;for(; i < sb.length(); i++){if(sb.charAt(i) == ' '){sb = reverse(sb, start, i - 1);start = i + 1;}}sb = reverse(sb, start, i - 1);return sb.toString();}private StringBuilder deleteSpace(String s){int l = 0;int r = s.length() - 1;while(s.charAt(l) == ' ') l++;while(s.charAt(r) == ' ') r--;StringBuilder sb = new StringBuilder(s);if(r + 1 < s.length() - 1) sb = sb.delete(r + 1, s.length()); //删除后置空格if(l > 0) sb = sb.delete(0, l); //删除前导空格int i = 0;while(i < sb.length()){if(sb.charAt(i) == ' ') {int start = ++i;while (sb.charAt(i) == ' ') i++;int end = i;if (end - start >= 0) {sb = sb.delete(start, end);i = start;}}i++;}return sb;}private StringBuilder reverse(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;}
}