zoukankan      html  css  js  c++  java
  • 字符串题目

    2018-01-24 20:19:48

    • 重复字符串匹配

    问题描述:

    问题求解:

    使用brute force的方法求解,也就是依次比较,但是差别就是在A到末尾的时候循环从头开始继续进行比较。

        public int repeatedStringMatch(String A, String B) {
            for (int i = 0,j; i < A.length(); i++) {
                for (j = 0; j < B.length() && B.charAt(j) == A.charAt((i+j) % A.length()); j++);
                // i就是A中前面失配的个数,j.length = 部分1 + n * A.length + 部分2
                // i + j = i + 部分1 + n * A.length + 部分2 =(n + 1)* A.length + 部分2
                // 所以其实就是一个向上取整
                if(j == B.length()) return (i+j) / A.length() + ((i + j) % A.length() == 0 ? 0 : 1);
            }
            return -1;
        }
    

    使用brute force的方法求解的运行效率是很低的,可以采用KMP算法加之改进。

        public int repeatedStringMatch(String A, String B) {
            int[] prefix = new int[B.length()];
            for (int i = 1, j = 0; i < B.length(); ) {
                if (B.charAt(i) == B.charAt(j)) prefix[i++] = ++j;
                else if (j == 0) i++;
                else j = prefix[j - 1];
            }
            for (int i = 0, j = 0; i < A.length(); i += j - prefix[j - 1], j = prefix[j - 1]) {
                while (j < B.length() && A.charAt((i + j) % A.length()) == B.charAt(j)) j++;
                if (j == B.length()) return (int)Math.ceil((double)(i + j) / A.length());
                if (j == 0) j++;
            }
            return -1;
        }
    
    • 字符数组压缩

    问题描述:

    问题举例:

     

    问题求解:

    使用双层while循环可以避免使用单层for循环末尾取不到的问题,并且代码显得更加紧凑。

        public int compress2(char[] chars) {
            int indexAns = 0;
            int index = 0;
    
            while(index < chars.length) {
                char currentChar = chars[index];
                int count = 0;
                while(index < chars.length && chars[index] == currentChar) {
                    index++;
                    count++;
                }
                chars[indexAns++] = currentChar;
                if(count != 1) {
                    for(char c : Integer.toString(count).toCharArray()) {
                        chars[indexAns++] = c;
                    }
                }
            }
            return indexAns;
        }
    
    • 回文子串

    问题描述:

    问题求解:

    最初想到的解法就是DP,就是不断从长度1,2,3生成判断是否回文,计数。

        public int countSubstrings(String s) {
            int cnt = 0;
            boolean map[][] = new boolean[s.length()][s.length()];
            for (int i = 0; i < s.length(); i++) {
                map[i][i] = true;
                cnt++;
                if (i + 1 < s.length() && s.charAt(i) == s.charAt(i + 1)) {
                    map[i][i + 1] = true;
                    cnt++;
                }
            }
            for (int i = 2; i < s.length(); i++) {
                for (int j = 0; j < s.length() - i; j++) {
                    if (s.charAt(j) == s.charAt(j + i) && map[j + 1][j + i - 1]) {
                        map[j][j+i] = true;
                        cnt++;
                    }
                    else {
                        map[j][j+i] = false;
                    }
                }
            }
            return cnt;
        }
    

    事实上,也可以使用递归的思路,不断的生成字串进行判断,这种方法也是非常巧妙的。

        int count = 0;
    
        public int countSubstrings2(String s) {
            if (s == null || s.length() == 0) return 0;
    
            for (int i = 0; i < s.length(); i++) { // i is the mid point
                extendPalindrome(s, i, i); // odd length;
                extendPalindrome(s, i, i + 1); // even length
            }
    
            return count;
        }
    
        private void extendPalindrome(String s, int left, int right) {
            while (left >=0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
                count++; left--; right++;
            }
        }
    
    • Implement Magic Dictionary

    问题描述:

    问题求解:

    使用Trie树可以很方便的进行求解,思路清晰。

    public class MagicDictionary {
        class TrieNode {
            TrieNode[] child = new TrieNode[26];
            boolean isWord = false;
        }
    
        TrieNode root;
    
        /** Initialize your data structure here. */
        public MagicDictionary() {
            root = new TrieNode();
        }
    
        /** Build a dictionary through a list of words */
        public void buildDict(String[] dict) {
            for (String i : dict) {
                TrieNode cur = root;
                for (char j : i.toCharArray()) {
                    if(cur.child[j - 'a'] == null) cur.child[j - 'a'] = new TrieNode();
                    cur = cur.child[j - 'a'];
                }
                cur.isWord = true;
            }
        }
    
        /** Returns if there is any word in the trie that equals to the given word after modifying exactly one character */
        public boolean search(String word) {
            char[] s = word.toCharArray();
            for (int i = 0; i < s.length; i++) {
                for (char j = 'a'; j <= 'z'; j++) {
                    if(j == s[i]) continue;
                    char pre = s[i];
                    s[i] = j;
                    if (helper(s, root)) {
                        return true;
                    }
                    s[i] = pre;
                }
            }
            return false;
        }
    
        boolean helper(char[] s, TrieNode root) {
            TrieNode tmp = root;
            for (char c : s) {
                if(tmp.child[c - 'a'] == null) return false;
                tmp = tmp.child[c - 'a'];
            }
            return tmp.isWord;
        }
    }
    
    • 判断子串

    问题描述:

    问题求解:

    方法一、双指针,遍历t一遍,就可以得到结果,代码简洁,时间复杂度为O(n)。

        public boolean isSubsequence(String s, String t) {
            if (s.equals("")) return true;
            if (t.equals("")) return false;
            boolean res = false;
            int idxt = 0;
            int idxs = 0;
            char[] s1 = s.toCharArray();
            char[] t1 = t.toCharArray();
            for(;idxt < t1.length; idxt++) {
                if (t1[idxt] == s1[idxs]) idxs++;
                if (idxs == s1.length) {
                    res = true;
                    break;
                }
            }
            return res;
        }
    

    方法二、follow up里提到,如果问题是一个t,多个s的情况下,使用上述的双指针,算法时间复杂度为O(kn),就不那么理想了。一般来说这种问题,可以使用预处理的方法进行改进。我们可以使用一个HashMap,将每个字符出现的index保存下来。对于每个query,遍历一遍s,对每个字符进行查看,如果Hash中没有的话,直接返回false,如果存在,则寻找其index,进行判断。

        public boolean isSubsequence(String s, String t) {
            if (s.equals("")) return true;
            if (t.equals("")) return false;
            HashMap<Character, List<Integer>> map = new HashMap<>();
            char[] t1 = t.toCharArray();
            char[] s1 = s.toCharArray();
            for (int i = 0; i < t1.length; i++) {
                if (!map.containsKey(t1[i])) map.put(t1[i], new ArrayList<Integer>());
                map.get(t1[i]).add(i);
            }
            int idx = 0;
            for (int i = 0; i < s1.length; i++) {
                if (!map.containsKey(s1[i])) return false;
                int k = Collections.binarySearch(map.get(s1[i]), idx);
                if (k < 0) k = -k - 1;
                if (k == map.get(s1[i]).size()) return false;
                idx = map.get(s1[i]).get(k) + 1;
            }
            return true;
        }
    
  • 相关阅读:
    day34-python-异常
    day33-python-反射、内置方法、元类、 属性查找
    day31/32待补
    day30-mixin、重载、多态、绑定与非绑定方法、内置函数
    day29-python-property、继承、属性查找、多继承带来的菱形问题
    day28-python-封装
    day27-python-面向对象介绍、实现面向对象编程、查找顺序
    luffy项目
    oc基本数据类型
    iOS 入门了解
  • 原文地址:https://www.cnblogs.com/hyserendipity/p/8343820.html
Copyright © 2011-2022 走看看