算法 字符串

一、字符串类型

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;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值