一、字符串类型
1.1 要点
StringBuilder,StringBuffer类
1.2 常见类型
- 规则判断
- 数字运算
- 与数组有关的操作
- 字符计数
哈希表
字符数组 - 动态规划类型
最长公共子串
最长公共子序列
最长回文子串
最长回文子序列 - 搜索类型
宽度优先搜索
深度优先搜索 - 高级算法与数据结构
二、经典例题
2.1 判断树中是否包含子树
- 注意:决定对不能用层次遍历,层次遍历是错的
- 思路:
树序列化成字符串然后判断是否包含子树
错误演示:
public class contaun_tree {
static StringBuilder tree1 = new StringBuilder();
static StringBuilder tree2 = new StringBuilder();
public static void main(String[] args) {
Node A = new Node("A");
Node B = new Node("B");
Node C = new Node("C");
Node D = new Node("D");
Node E = new Node("E");
Node F = new Node("F");
Node G = new Node("G");
A.setlNode(B);
A.setrNode(C);
B.setlNode(D);
B.setrNode(E);
E.setrNode(F);
C.setrNode(G);
Node B1 = new Node("B1");
Node D1 = new Node("D1");
Node E1 = new Node("E1");
Node F1 = new Node("F1");
B1.setlNode(D1);
B1.setrNode(E1);
E1.setrNode(F1);
String treeA = serializable(A);
tree1 = new StringBuilder();
String treeB = serializable(B1);
System.out.println(treeA);
System.out.println(treeB);
}
public static String serializable(Node node){
Queue<Node> stack = new LinkedList<>();
Node last = node;
Node Nlast = node;
if(node != null){
stack.offer(node);
tree1.append(node.getValue() + "!");
}
while (!stack.isEmpty()) {
Node pop = stack.poll();
if (pop.getlNode() != null) {
tree1.append(pop.getlNode().getValue() + "!");
stack.offer(pop.getlNode());
Nlast = pop.getlNode();
}
if (pop.getlNode() == null) {
tree1.append("#!");
}
if (pop.getrNode() != null) {
tree1.append(pop.getrNode().getValue() + "!");
stack.offer(pop.getrNode());
Nlast = pop.getrNode();
}
if (pop.getrNode() == null) {
tree1.append("#!");
}
if(pop == last){
last = Nlast;
}
}
return new String(tree1);
}
}
结果:
A!B!C!D!E!#!G!#!#!#!F!#!#!#!#!
B1!D1!E1!#!#!#!F1!#!#!
正确演示:
public class Bucket {
static StringBuilder tree1 = new StringBuilder();
static StringBuilder tree2 = new StringBuilder();
public static void main(String[] args) {
Node A = new Node("A");
Node B = new Node("B");
Node C = new Node("C");
Node D = new Node("D");
Node E = new Node("E");
Node F = new Node("F");
Node G = new Node("G");
A.setlNode(B);
A.setrNode(C);
B.setlNode(D);
B.setrNode(E);
E.setrNode(F);
C.setrNode(G);
Node B1 = new Node("B");
Node D1 = new Node("D");
Node E1 = new Node("E");
Node F1 = new Node("F");
B1.setlNode(D1);
B1.setrNode(E1);
E1.setrNode(F1);
String s = frontSort(A,tree1);
System.out.println(s);
String s1 = frontSort(B1, tree2);
System.out.println(s1);
if(s.contains(s1)){
System.out.println("tree1包含子树tree2");
}
}
public static String frontSort(Node node, StringBuilder str) {
if(node != null){
str.append(node.getValue() + "!");
}
if( node.getlNode() != null){
frontSort(node.getlNode(), str);
}
if(node.getlNode() == null){
str.append("#!");
}
if( node.getrNode() != null){
frontSort(node.getrNode(), str);
}
if(node.getrNode() == null){
str.append("#!");
}
return new String(str);
}
}
结果:
A!B!D!#!#!E!#!F!#!#!C!#!G!#!#!
B!D!#!#!E!#!F!#!#!
tree1包含子树tree2
2.2 如果字符串str1与字符串str2出现的字符种类一样且每种字符出现的次数一样,则str1与str2互为变形词。判断两个字符串是否为变形词。
思路:给两个字符串建立一个哈希表,可以用数组模拟哈希表
public class Array_test {
public static void main(String[] args) {
String str1 = "qweq2F3E";
String str2 = "qqF2w23eE";
if(str1.length() != str2.length())
System.out.println("不是变形词");
char[] array1 = new char[256];
char[] array2 = new char[256];
for (int i = 0; i < str1.length(); i++) {
array1[str1.charAt(i)] = array1[str1.charAt(i)]++;
array2[str2.charAt(i)] = array2[str2.charAt(i)]++;
}
for (int i = 0; i < array1.length; i++) {
if(array1[i] != array2[i]){
System.out.println("不是变形词");
}
}
}
}
2.3 判断两个字符串是否为旋转词
思路:
- 长度是否相等
- 将2个str1拼接起来,判断该大字符串是否包含str2
public class Array_test {
public static void main(String[] args) {
String str1 = "1234567890";
String str2 = "0123456789";
judge(str1, str2);
}
public static void judge(String str1, String str2){
if(str1.length() != str2.length()){
System.out.println("不是旋转词");
return;
}
String str3 = str1 + str1;
if(str3.contains(str2)){
System.out.println("是旋转词");
}else {
System.out.println("不是旋转词");
}
}
}
2.4 字符串的单词间进行逆序
比如:“i am a student”
,逆序的结果就是"student a am i"
一种思路是:
将字符串整体逆序,再把所有单词逆序。
public class Array_test {
public static void main(String[] args) {
String str1 = "i am a student";
String judge = judge(str1);
String trim = judge.trim();
System.out.println(trim);
System.out.println(judge);
}
public static String judge(String str1){
StringBuilder str2 = new StringBuilder();
String[] s = str1.split(" ");
for (int i = 0; i < s.length; i++) {
str2.append(s[s.length - i -1]).append(" ");
}
return new String(str2);
}
}
2.5 指定字符串的位置,将字符串左右移位,如:ABCDE,i=2,结果是:DEABC
要求:时间复杂度为o[n],额外空间复杂度为o[1]
思路:将0~i的字符逆序, i ~ n-1的位置逆序,再整体逆序
public class Array_test {
public static void main(String[] args) {
String str = "ABCDE";
String move = move(str, 2);
}
public static String move(String str,int i){
if(i == str.length()){
return str;
}
char[] chars = str.toCharArray();
judge(chars,0,i);
judge(chars,i + 1,chars.length-1);
judge(chars,0,chars.length-1);
for (int i1 = 0; i1 < chars.length; i1++) {
System.out.print(chars[i1] + " ");
}
return new String(chars);
}
public static void judge(char[] str, int start, int end) {
int left = start;
int right = end;
while (left < right) {
char flag;
flag = str[left];
str[left] = str[right];
str[right] = flag;
right--;
left++;
}
}
}
2.6 求两个字符串的最优拼接的排序算法,如"abc",“de”,最优排序的结果是"abcde"。
- 最优的时间复杂度:o(n*logN)
- 不能直接按照字典顺序排
如:b,ba
思路:str1+str2 < str2 + str1,则按照str1str2的顺序排
public class Array_test {
public static void main(String[] args) {
String str = "ABC";
String str1 = "DE";
System.out.println(sort(str, str1));
}
public static String sort(String str1, String str2){
if((str1 + str2).compareTo(str2 + str1) < 0){
return str1 + str2;
}
else{
return str2 + str1;
}
}
}
3.7 将字符串中所有的空格字符替换成"%20",字符串有足够大的空间
思路:遍历字符串,计算空格的数量,计算出所需空间的大小,从后往前复制
public class Array_test {
public static void main(String[] args) {
String str = "A B C";
System.out.println(sort(str.toCharArray()));
}
public static String sort(char[] str){
int len = str.length;
int count = 0;
for (int i = 0; i < len; i++) {
if(str[i] == ' '){
count ++;
}
}
char[] array = new char[len + 2*count];
int len1 = array.length - 1;
for (int i = len-1; i >= 0; i--) {
if(str[i] != ' '){
array[len1 -- ] = str[i];
}
else {
array[len1--] = '0';
array[len1--] = '2';
array[len1--] = '%';
}
}
return new String(array);
}
}
3.8 给定字符串,判断是不是整体有效的括号字符串
最优解:时间复杂度o(N),额外空间复杂度:o(1)
public class Array_test {
public static void main(String[] args) {
String str = "(()a()";
System.out.println(sort(str));
}
public static Boolean sort(String string){
int num = 0;
for (int i = 0; i < string.length(); i++) {
if(string.charAt(i) == '(' && num >= 0){
num ++;
}
if(string.charAt(i) == ')' && num >= 0){
num --;
}
if(num < 0){
return false;
}
if(string.charAt(i) != '(' && string.charAt(i) != ')'){
return false;
}
}
if(num != 0){
return false;
}
return true;
}
}
3.9 求字符串的最长无重复字符子串的长度
最优解:时间复杂度为o(N),额外空间复杂度为o(N)。
思路:遍历字符串的每一个字符,以该字符为尾字符,向前找最大不重复字符串
public class Array_test {
public static void main(String[] args) {
String str = "abcdefg123abcdefg123456";
System.out.println(maxStr(str));
}
public static int maxStr(String str){
int max = 0;
for (int i = 2; i < str.length(); i++) {
int flag = sort(str, i);
if(flag > max){
max = flag;
}
}
return max;
}
public static int sort(String str, int i) {
int right = i - 1;
char[] chars = str.toCharArray();
int left = str.lastIndexOf(chars[i], right);
if(left == i - 1){
return 1;
}
if(left == i-2 && i - 2 >= 0){
return 2;
}
while (right > left){
int mid = str.lastIndexOf(chars[right--], right - 1);
if(mid <= left){
}else {
left = mid;
}
}
return i - left;
}
}