代码随想录算法训练营第八天|344.反转字符串、541. 反转字符串II、卡码网:54.替换数字、51.翻转字符串里的单词、卡码网:55.右旋转字符串.md
344.反转字符串
问题简述:将字符串数组反转并存在原数组中。
思考:左右两个指针遍历遍历一遍。
算法思路:将左右指针分别指向数组头和尾,不断将头尾字符交换,直到左右指针相等。
时间复杂度 :O(n)
空间复杂度 :O(1)
class Solution {
public void reverseString(char[] s) {
int left = 0, right = s.length - 1;
while (left < right){
char a = s[left];
s[left] = s[right];
s[right] = a;
left++;
right--;
}
return;
}
}
541. 反转字符串II
问题简述:将每2k个字符串中的前k个反转,若剩余不足k个则直接将剩余反转,若剩余大于k小于2k个,则将这k个反转。
思考:java中的字符串String不能改写,只能读取,很多字符的方法都没有,本体选择将字符串存入StringBuilder进程处理。
-
String(字符串):是 Java 中最常用的字符串类型,它是不可变的,一旦创建就不能修改。字符串的字面值可以用双引号引起来,例如:“Hello, World!”。
-
StringBuffer(字符串缓冲区):是一个可变的字符串类型,适用于多线程环境下的字符串操作。它的操作是同步的,可以保证线程安全。StringBuilder 是其非线程安全的版本。
-
StringBuilder(字符串生成器):与 StringBuffer 类似,也是一个可变的字符串类型,但不保证线程安全。在单线程环境下,StringBuilder 的性能比 StringBuffer 更高。
算法思路:依次遍历每个2k,左右指针分别指向2k中的第一个和第k个,翻转前k个字符。如果right指针越界,则right直接指向字符串末尾。
时间复杂度: O(n)
空间复杂度: O(n)
class Solution {
public String reverseStr(String s, int k) {
//定义一个可变字符串
StringBuilder newString = new StringBuilder(s);
int i = 0;
while (i < s.length()){
int left = i;
int right = i + k -1;
//如果r越界,直接指向字符串尾
if (right > s.length() - 1){
right = s.length() - 1;
}
while (left < right){
// 将左右两个字符进行交换
char temp = newString.charAt(left);
newString.setCharAt(left, newString.charAt(right));
newString.setCharAt(right, temp);
right--;
left++;
}
//每次循环处理2k个字符
i += 2 * k;
}
return new String(newString);
}
}
卡码网:54.替换数字
问题简述:给定含有小写字母和数字的字符串,将数字变为"number"。
思考:卡码网需要自己写输入输出,Main文件需要创建同名的Main类,然后接口main是程序运行的主函数。
算法思路:创建空的StringBuilder,遍历输入的s,如果为数字就在StringBuilder中加入字符串"number",如果为字母就直接加入StringBuilder,直到遍历完所有字符。
时间复杂度 O(n)
空间复杂度 O(n)
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
//输入一个字符串
Scanner in = new Scanner(System.in);
String s = in.nextLine();
//创建空的StringBuilder
StringBuilder newString = new StringBuilder();
//遍历s,如果为数字就在StringBuilder加入“number”,如果为字母就直接加入StringBuilder
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (Character.isDigit(c)) {
newString.append("number");
} else {
newString.append(c);
}
}
System.out.println(newString);
}
}
51.翻转字符串里的单词
问题简述:将字符串里的单词翻转,翻转后单词间存在空格,字符串首位不存在空格。
思考:看似复杂,实则需要注意的点确实很多,要不断考虑不要溢出。总的来说就是找到每个单词的首位,再存入新的字符串。
算法思路:创建指针l和r,不断遍历直到指向单词的末尾,再让l指向单词第一个字母,将l到r的字母加入新字符串,再加入空格后,l和r指向单词的前一个空格,以便于下一次循环。不断循环,直到遍历完字符串。
时间复杂度 O(n)
空间复杂度 O(n)
class Solution {
public String reverseWords(String s) {
StringBuilder newString = new StringBuilder();
//应对单个字母的字符串“a”
if(s.length() == 1){
return s;
}
int left = s.length() - 1;
int right = s.length() - 1;
while (right > 0){
//如果l和r都指向空格,则同时向左移动,直到不为空格,且不要溢出
while (right > 0 && s.charAt(right) == ' '){
right--;
left--;
}
//此时left和right都指向单词的最后一个字母,循环结束时,left指向单词第一个字母,注意不要溢出
while (left > 0 && s.charAt(left - 1) != ' ') {
if (left != 0){
left--;
}
}
//将l到r的字母加入,因为append是加入左闭右开的数字,所以右面填入r+1
newString.append(s.substring(left, right + 1));
//单词之间添加空格
newString.append(' ');
//left指向左面的空格
left--;
right = left;
}
while (newString.charAt(newString.length() - 1) == ' '){
newString.deleteCharAt(newString.length() - 1);
}
return new String(newString);
}
}
卡码网:55.右旋转字符串
问题简述:输入字符串s和数字n,将字符串后n位放到字符串最前面。
思考:之前复习数据结构的时候见过,觉得思想很巧妙。这里没有用StringBuilder自带的reverse()方法,因为reverse和系统方法一样,一般都是左闭右开,好像老是溢出,左右自己写了一个左闭右闭的方法。同时选择字符串数组来更方便的处理。
算法思路:将字符串全部翻转,再翻转前n位,再将剩下的字符翻转。
时间复杂度 O(n)
空间复杂度 O(n)
import java.util.Scanner;
public class main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
in.nextLine(); // 消耗换行符
String s = in.nextLine();
int len = s.length(); //获取字符串长度
//用数组进行存储
char[] chars = s.toCharArray();
reverseString(chars, 0, len - 1);
reverseString(chars, 0, n - 1);
reverseString(chars, n, len - 1);
System.out.println(chars);
}
public static void reverseString(char[] s, int left, int right) {
while (left < right){
char a = s[left];
s[left] = s[right];
s[right] = a;
left++;
right--;
}
return;
}
}
感想
字符串不是很熟练,很多自带的方法感觉不是很会,因为没系统的看java基础,比如toString啥的我还没太明白。