字符串
- 简介
- [简单] 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;
}
}