目录
151.翻转字符串里的单词
解题分析
本题可以考虑先把字符串整体逆序,再把每个单词逆序处理。但是还要考虑可能出现字符串有前导空格、尾随空格、单词间多余空格,所以要先处理冗余空格。
可以创建三个方法,最后进行调用。
1.去掉首位及单词中间的冗余空格
2.反转整体字符串
3.反转每个单词
本题代码
class Solution {
public String reverseWords(String s) {
StringBuilder sb = removeSpace(s);
reverseString(sb, 0, sb.length() - 1);
reverseEachWord(sb);
return sb.toString();
}
//去掉首位及单词中间的冗余空格
public StringBuilder removeSpace(String s){
int start = 0;
int end = s.length() - 1;
StringBuilder sb = new StringBuilder();
while(s.charAt(start) == ' '){
start++; //去首空格
}
while(s.charAt(end) == ' '){
end--; //去尾空格
}
while(start <= end){
char c = s.charAt(start);
if(c != ' ' || sb.charAt(sb.length() - 1) != ' '){ //本字符不为空格或上一个添加的字符不为空格
sb.append(c); //去单词之间冗余空格
}
start++;
}
return sb;
}
//反转整体字符串
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--;
}
}
//反转每个单词
public void reverseEachWord(StringBuilder sb){
int start = 0;
int 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;
}
}
}
卡码网:55.右旋转字符串
题目链接:https://kamacoder.com/problempage.php?pid=1065
解题分析
1.字符串整体反转
2.字符串分组反转
第一段为前k个:0到k-1
第二段为后n-k个:k到n-1
反转的方法可同151.翻转字符串里的单词里的reverseString,用StringBuilder实现
本题代码
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
int k = scan.nextInt();
String str = scan.next();
StringBuilder sb = new StringBuilder(str);
int n = str.length();
reverseString(sb, 0, n - 1);
reverseString(sb, 0, k - 1);
reverseString(sb, k, n - 1);
System.out.println(sb.toString());
}
public static void reverseString(StringBuilder s, int start, int end){
while(start < end){
char temp = s.charAt(start);
s.setCharAt(start, s.charAt(end));
s.setCharAt(end, temp);
start++;
end--;
}
}
}
28. 实现 strStr()
文章讲解:https://programmercarl.com/0028.%E5%AE%9E%E7%8E%B0strStr.html
解题分析
本题是经典的KMP算法,此处推荐B站左程云老师讲的KMP算法,看完即可理解代码
本题代码
class Solution {
public int strStr(String haystack, String needle) {
if(haystack == null || needle == null || needle.length() < 1 ||
haystack.length() < needle.length()){
return -1;
}
char[] str1 = haystack.toCharArray();
char[] str2 = needle.toCharArray();
int[] next = getNextArray(str2);
int x = 0; //str1的位置
int y = 0; //str2的位置
while(x < str1.length && y < str2.length){
if(str1[x] == str2[y]){ //相同,比下一位
x++;
y++;
}else if(next[y] == -1){ //str2已到头,str1另起下一位,重比
x++;
}else{
y = next[y]; //遇到不同,y往前滑
}
}
//y越界表示找到了,起始位置为此时x位置减去y的长度
//y没越界表示没找到
return y == str2.length ? x-y : -1;
}
public int[] getNextArray(char[] str2){
if(str2.length == 1){
return new int[]{-1};
}
int[] next = new int[str2.length];
next[0] = -1;
next[1] = 0;
int i = 2; //目前在哪个位置上求next数组的值
int cn = 0; //可理解为next[i-1]的值,也是主字符串跟str2[i-1]比较的字符的位置
while(i < str2.length){
if(str2[i-1] == str2[cn]){
next[i++] = ++cn;
}else if(cn > 0){
cn = next[cn];
}else{
next[i++] = 0;
}
}
return next;
}
}
459.重复的子字符串
解题分析
如果s为重复子串构成,那么将两个 s 连在一起,移除第一个和最后一个字符,那么得到的字符串一定包含 s。
比如字符串s = "abcabc",s + s = "abcabcabcabc",去掉首尾字母后为"bcabcabcab",中间是包含原字符串abcabc的,所以是由重复子串构成。
在代码中,可以用indexOf从角标为1的位置去查找s(等价于去掉首字母),如果查询结果不为位置 n,即小于n,代表在n位置之前找到有s,就返回true。这与移除字符串的第一个和最后一个字符是等价。
本题代码
class Solution {
public boolean repeatedSubstringPattern(String s) {
return(s + s).indexOf(s,1) != s.length();
}
}