文章目录
344.反转字符串
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
示例 1:
- 输入:s = [“h”,“e”,“l”,“l”,“o”]
- 输出:[“o”,“l”,“l”,“e”,“h”]
示例 2:
- 输入:s = [“H”,“a”,“n”,“n”,“a”,“h”]
- 输出:[“h”,“a”,“n”,“n”,“a”,“H”]
提示:
- 1 <= s.length <= 105
- s[i] 都是 ASCII 码表中的可打印字符
解题思路
很基础的题,就是实现反转的库函数。可以暴力直接两层循环解,也可以双指针
源码
class Solution {
public void reverseString(char[] s) {
// 双指针
int left=0;
int right=s.length-1;
char temp;
while(left<right){
temp = s[left];
s[left]=s[right];
s[right]=temp;
left++;
right--;
}
}
}
时间复杂度: O(n)
空间复杂度: O(1)
541. 反转字符串 II
给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。
如果剩余字符少于 k 个,则将剩余字符全部反转。
如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
示例 1:
- 输入:s = “abcdefg”, k = 2
- 输出:“bacdfeg”
示例 2:
- 输入:s = “abcd”, k = 2
- 输出:“bacd”
提示:
- 1 <= s.length <= 104
- s 仅由小写英文组成
- 1 <= k <= 104
解题思路
使用双指针法就可以,是上个题的进阶版,重点在于怎么减少for循环的轮数降低时间复杂度。
当需要固定规律一段一段去处理字符串的时候,要想想在在for循环的表达式上做做文章。
源码
class Solution {
public String reverseStr(String s, int k) {
char[] str = s.toCharArray();
int i=0;
int left, right;
while(i<str.length){
left=i;
if(i+k<str.length && str.length<i+(2*k)){
right=i+k-1;
while(left<right){
char temp;
temp=str[left];
str[left]=str[right];
str[right]=temp;
left++;
right--;
}
String result = new String(str);
return result;
}
right=Math.min(str.length - 1,i + k - 1);
while(left<right){
char temp;
temp=str[left];
str[left]=str[right];
str[right]=temp;
left++;
right--;
}
i+=(2*k);
}
String result = new String(str);
return result;
}
}
时间复杂度: O(n)
空间复杂度: O(1)
54. 替换数字(卡码网)
题目描述
给定一个字符串 s,它包含小写字母和数字字符,请编写一个函数,将字符串中的字母字符保持不变,而将每个数字字符替换为number。 例如,对于输入字符串 “a1b2c3”,函数应该将其转换为 “anumberbnumbercnumber”。
输入描述
输入一个字符串 s,s 仅包含小写字母和数字字符。
输出描述
打印一个新的字符串,其中每个数字字符都被替换为了number
输入示例
a1b2c3
输出示例
anumberbnumbercnumber
提示
数据范围:
1 <= s.length < 10000。
解题思路
用双指针法从后往前填充数据(从前往后需要挪动元素),C++做的话可以不用辅助空间的,但是java里字符串不能修改所以必须要用辅助空间
源码
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);
}
}
151. 反转字符串中的单词
解题思路
源码
class Solution {
public String reverseWords(String 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++;
}
// 先把字符从后往前全部反转,然后再把每个单词的字符转回来
reverseString(sb, 0, sb.length() - 1);
start = 0;
end = 1;
int n = sb.length();
while (start < n) {
while (end < n && sb.charAt(end) != ' ') {
end++;
}
reverseString(sb, start, end - 1);
start = end + 1;
end = start + 1;
}
return sb.toString();
}
// 反转字符串
public void reverseString(StringBuilder sb, int start, int end) {
while (start < end) {
char temp = sb.charAt(start);
sb.setCharAt(start, sb.charAt(end));
sb.setCharAt(end, temp);
start++;
end--;
}
}
}
时间复杂度: O(n)
空间复杂度: O(1)
55. 右旋字符串(卡码网)
解题思路
右旋就是相当于把字符串分成两段,后面转到前面的部分和不变的部分。可以整个字符串反转然后再单独反转前后两段。
源码
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = Integer.parseInt(in.nextLine());
String s = in.nextLine();
int len = s.length();
char[] chars = s.toCharArray();
reverseString(chars, 0, len - 1); //反转整个字符串
//反转前一段字符串,此时的字符串首尾尾是0,n - 1
reverseString(chars, 0, n - 1);
//反转后一段字符串,此时的字符串首尾尾是n,len - 1
reverseString(chars, n, len - 1);
System.out.println(chars);
}
public static void reverseString(char[] ch, int start, int end) {
char temp;
while (start < end) {
temp=ch[start];
ch[start]=ch[end];
ch[end]=temp;
start++;
end--;
}
}
}
总结
开始学习字符串了,基础还要再巩固一下好多基础函数都用的有点问题。后两道题周末再回来复习一下,调了太久最后还是看了答案才改出来