包含子串问题
案例一:子串问题 KMP
private static void example1() {
String str = " aaxaababaaaba";
String sub = " ababaaaba";
int index = JudgeStrContainsSub(str, sub);
System.out.println("index = " + index);
}
private static int JudgeStrContainsSub(String str, String sub) {
char[] strChar = str.toCharArray();
char[] subChar = sub.toCharArray();
int[] subNext = next(subChar);
int i = 1, j = 1;
while ((i <= strChar.length - 1) && (j <= subChar.length - 1)) {
if (j == 0 || strChar[i] == subChar[j]) {
i ++;
j ++;
} else {
j = subNext[j];
}
}
if (j > subChar.length - 1) {
return i - (subChar.length - 1);
}
return 0;
}
private static int[] next(char[] subChar) {
//i前缀, j后缀
int i = 1, j = 0;
int[] next = new int[subChar.length];
next[1] = 0;
while (i < subChar.length - 1) {
if (j == 0 || subChar[i] == subChar[j]) {
i ++;
j ++;
next[i] = j;
} else {
j = next[j];
}
}
return next;
}
旋转词问题
案例二:旋转词
eg:1234 的旋转词:1234、2341、3412、4123
解决:将1234 拼接 12341234,子串(用KMP)就是旋转词
private static void example2() {
String rotateSource = "1234";
String rotateDest = "3421";
String rotate = rotateSource + rotateSource;
if (JudgeStrContainsSub(rotate, rotateDest) != 0) {
System.out.println("是旋转词。");
} else {
System.out.println("不是旋转词");
}
}
以空格位置逆序字符串
案例三:dog loves cat —-> cat loves dog
思路:将所有逆序: tac sevol god,再将每个单词逆序
private static void example3() {
String reverseSource = "dog loves cat";
String reverse1 = reverseStr(reverseSource, 0, reverseSource.length() -1);
int s = 0 , d = 0;
while(d != -1) {
d = reverse1.indexOf(" ", s);
if (d != -1) {
reverse1 = reverseStr(reverse1, s, d - 1);
} else {
reverse1 = reverseStr(reverse1, s, reverse1.length() -1);
}
s = d + 1;
}
System.out.println(reverse1);
}
private static String reverseStr(String reverseSource, int s, int d) {
char[] ch = reverseSource.toCharArray();
char temp;
while (s < d) {
temp = ch[s];
ch[s] = ch[d];
ch[d] = temp;
s ++;
d --;
}
StringBuilder sb = new StringBuilder();
for (char c : ch) {
sb.append(c+"");
}
return sb.toString();
}
根据给定位置逆序字符串
案例四:o(n)
问题:
思路:
private static void example4() {
String selectReverse = "ABCDE";
int i = 2;
selectReverse = reverseStr(selectReverse, 0, i);
selectReverse = reverseStr(selectReverse, i + 1, selectReverse.length() - 1);
selectReverse = reverseStr(selectReverse, 0, selectReverse.length() - 1);
System.out.println(selectReverse);
}
拼接字符串字典顺序最小
案例五:o(n*logn)
思路:str1 + str2 < str2 + str1,则是str1放在前面。
private static void example5() {
String[] str1 = {"ba", "b"};
String[] str2 = {"abc", "ddf", "de"};
System.out.println(findSmallest(str1, str1.length));
System.out.println(findSmallest(str2, str2.length));
}
private static String findSmallest(String[] str, int length) {
if (str == null || length == 0) {
return null;
}
Arrays.sort(str, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return (o1 + o2).compareTo(o2 + o1);
}
});
StringBuilder stitch = new StringBuilder();
for (String s : str) {
stitch.append(s);
}
return stitch.toString();
}
把空格替换成其他字符串
案例六:将空格替换成%20
从后往前
private static void example6() {
String str = "a b c";
String repl = "%20";
int count= 0, from = 0, index = -1;
while ((index = str.indexOf(" ", from)) > 0) {
count++;
from = index + 1;
}
char[] chs = new char[str.length() + count * (repl.length() - 1)];
int i = str.length() - 1, j = repl.length() - 1, k = chs.length - 1;
while(i >= 0) {
if (str.charAt(i) != ' ') {
chs[k] = str.charAt(i);
k --;
} else {
while (j >= 0) {
chs[k] = repl.charAt(j);
j --;
k --;
}
j = repl.length() - 1;
}
i --;
}
for (char c : chs) {
System.out.print(c);
}
}
最长无重复子串
案例七:最长无重复子串
思路:需要一个set,从左往右遍历字符串,
如果不包含,添加到set、并计算现在的子串长度
如果包含,就移除到出现这个字符之后的位置。
private static void example7() {
String str = "ababcdbe";
int n = str.length();
Set<Character> set = new HashSet<Character>();
int ans = 0, i = 0, j = 0;
while (i < n && j < n) {
if (!set.contains(str.charAt(j))){
set.add(str.charAt(j++));
//System.out.println("i:" + i +",j:" + (j - 1));
//System.out.println("add:" + str.charAt(j - 1));
ans = Math.max(ans, j - i);
//System.out.println("ans:" + ans);
}
else {
set.remove(str.charAt(i++));
//System.out.println("i:" + (i - 1) +",j:" + j);
//System.out.println("remove:" + str.charAt(i - 1));
}
}
System.out.println(ans);
}
左右括号匹配
思路: