博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
字符串题目
阅读量:5328 次
发布时间:2019-06-14

本文共 6307 字,大约阅读时间需要 21 分钟。

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

 

转载于:https://www.cnblogs.com/TIMHY/p/8343820.html

你可能感兴趣的文章
core--线程池
查看>>
B+树介绍
查看>>
redux-effect
查看>>
Swift和OC混编
查看>>
深度学习文献阅读笔记(6)
查看>>
Android轻量级的开源缓存框架ASimpleCache
查看>>
他山之石:加载图片的一个小问题
查看>>
shell - 常识
查看>>
[PHP] excel 的导入导出
查看>>
SDL(01-10)
查看>>
网络爬虫基本原理(一)
查看>>
IM开发通信协议基础知识(一)---TCP、UDP、HTTP、SOCKET
查看>>
Android Studio 创建/打开项目时一直处于Building“project name”Gradle project info 的解决...
查看>>
mssql sqlserver 使用sql脚本 清空所有数据库表数据的方法分享
查看>>
分层图最短路【bzoj2763】: [JLOI2011]飞行路线
查看>>
FastReport.Net使用:[18]形状(Shape)控件用法
查看>>
asp.net学习笔记1
查看>>
linux下编译复数类型引发的错误:expected unqualified-id before '(' token
查看>>
sed用法
查看>>
codeforces 1041A Heist
查看>>