# [算法总结] 13 道题搞定 BAT 面试——字符串

### 1.1 BM 算法

BM算法也是一种精确字符串匹配算法，它采用从右向左比较的方法，同时应用到了两种启发式规则，即坏字符规则 和好后缀规则 ，来决定向右跳跃的距离。基本思路就是从右往左进行字符匹配，遇到不匹配的字符后从坏字符表和好后缀表找一个最大的右移值，将模式串右移继续匹配。

### 2. 替换空格

``public class Solution { public String replaceSpace(StringBuffer str) { StringBuffer res = new StringBuffer(); int len = str.length() - 1; for(int i = len; i >= 0; i--){ if(str.charAt(i) == ' ') res.append("02%"); else res.append(str.charAt(i)); } return res.reverse().toString(); } }``

### 3. 最长公共前缀

Leetcode: 最长公共前缀

``class Solution { public String longestCommonPrefix(String[] strs) { if(strs == null || strs.length == 0) return ""; Arrays.sort(strs); char [] first = strs[0].toCharArray(); char [] last = strs[strs.length - 1].toCharArray(); StringBuffer res = new StringBuffer(); int len = first.length < last.length ? first.length : last.length; int i = 0; while(i < len){ if(first[i] == last[i]){ res.append(first[i]); i++; } else break; } return res.toString(); } }``

### 4. 最长回文串

LeetCode: 最长回文串

``class Solution { public int longestPalindrome(String s) { HashSet<Character> hs = new HashSet<>(); int len = s.length(); int count = 0; if(len == 0) return 0; for(int i = 0; i<len; i++){ if(hs.contains(s.charAt(i))){ hs.remove(s.charAt(i)); count++; }else{ hs.add(s.charAt(i)); } } return hs.isEmpty() ? count * 2 : count * 2 + 1; } }``

### 4.1 验证回文串

Leetcode: 验证回文串

``class Solution { public boolean isPalindrome(String s) { if(s.length() == 0) return true; int l = 0, r = s.length() - 1; while(l < r){ if(!Character.isLetterOrDigit(s.charAt(l))){ l++; }else if(!Character.isLetterOrDigit(s.charAt(r))){ r--; }else{ if(Character.toLowerCase(s.charAt(l)) != Character.toLowerCase(s.charAt(r))) return false; l++; r--; } } return true; } }``

### 4.2 最长回文子串

LeetCode: 最长回文子串

``class Solution { private int index, len; public String longestPalindrome(String s) { if(s.length() < 2) return s; for(int i = 0; i < s.length()-1; i++){ PalindromeHelper(s, i, i); PalindromeHelper(s, i, i+1); } return s.substring(index, index+len); } public void PalindromeHelper(String s, int l, int r){ while(l >= 0 && r < s.length() && s.charAt(l) == s.charAt(r)){ l--; r++; } if(len < r - l - 1){ index = l + 1; len = r - l - 1; } } }``

### 4.3 最长回文子序列

LeetCode: 最长回文子序列

dp[i][j] = dp[i+1][j-1] + 2 if s.charAt(i) == s.charAt(j)
otherwise, dp[i][j] = Math.max(dp[i+1][j], dp[i][j-1])

``class Solution { public int longestPalindromeSubseq(String s) { int len = s.length(); int [][] dp = new int[len][len]; for(int i = len - 1; i>=0; i--){ dp[i][i] = 1; for(int j = i+1; j < len; j++){ if(s.charAt(i) == s.charAt(j)) dp[i][j] = dp[i+1][j-1] + 2; else dp[i][j] = Math.max(dp[i+1][j], dp[i][j-1]); } } return dp[0][len-1]; } }``

### 5. 字符串的排列

Leetcode: 字符串的排列

``class Solution { public boolean checkInclusion(String s1, String s2) { int l1 = s1.length(); int l2 = s2.length(); int [] count = new int [128]; if(l1 > l2) return false; for(int i = 0; i<l1; i++){ count[s1.charAt(i) - 'a']++; count[s2.charAt(i) - 'a']--; } if(allZero(count)) return true; for(int i = l1; i<l2; i++){ count[s2.charAt(i) - 'a']--; count[s2.charAt(i-l1) - 'a']++; if(allZero(count)) return true; } return false; } public boolean allZero(int [] count){ int l = count.length; for(int i = 0; i < l; i++){ if(count[i] != 0) return false; } return true; } }``

### 6. 打印字符串的全排列

``public class Solution { ArrayList<String> res = new ArrayList<String>(); public ArrayList<String> Permutation(String str) { if(str == null) return res; PermutationHelper(str.toCharArray(), 0); Collections.sort(res); return res; } public void PermutationHelper(char[] str, int i){ if(i == str.length - 1){ res.add(String.valueOf(str)); }else{ for(int j = i; j < str.length; j++){ if(j!=i && str[i] == str[j]) continue; swap(str, i, j); PermutationHelper(str, i+1); swap(str, i, j); } } } public void swap(char[] str, int i, int j) { char temp = str[i]; str[i] = str[j]; str[j] = temp; } }``

### 7. 第一个只出现一次的字符

``import java.util.HashMap; public class Solution { public int FirstNotRepeatingChar(String str) { int len = str.length(); if(len == 0) return -1; HashMap<Character, Integer> map = new HashMap<>(); for(int i = 0; i < len; i++){ if(map.containsKey(str.charAt(i))){ int value = map.get(str.charAt(i)); map.put(str.charAt(i), value+1); }else{ map.put(str.charAt(i), 1); } } for(int i = 0; i < len; i++){ if(map.get(str.charAt(i)) == 1) return i; } return -1; } }``

### 8. 翻转单词顺序列

LeetCode: 翻转字符串里的单词

``public class Solution { public String reverseWords(String s) { if(s.trim().length() == 0) return s.trim(); String [] temp = s.trim().split(" +"); String res = ""; for(int i = temp.length - 1; i > 0; i--){ res += temp[i] + " "; } return res + temp[0]; } }``

### 9. 旋转字符串

Leetcode: 旋转字符串

A 的旋转操作就是将 A 最左边的字符移动到最右边。 例如, 若 A = ‘abcde’，在移动一次之后结果就是’bcdea’ 。如果在若干次旋转操作之后，A 能变成B，那么返回True。

``class Solution { public boolean rotateString(String A, String B) { return A.length() == B.length() && (A+A).contains(B); } }``

### 9.1 左旋转字符串

``public class Solution { public String LeftRotateString(String str,int n) { int len = str.length(); if(len == 0) return ""; n = n % len; String s1 = str.substring(n, len); String s2 = str.substring(0, n); return s1+s2; } }``

### 9.2 反转字符串

LeetCode: 反转字符串

``class Solution { public String reverseString(String s) { if(s.length() < 2) return s; int l = 0, r = s.length() - 1; char [] strs = s.toCharArray(); while(l < r){ char temp = strs[l]; strs[l] = strs[r]; strs[r] = temp; l++; r--; } return new String(strs); } }``

### 10. 把字符串转换成整数

``public class Solution { public int StrToInt(String str) { if(str.length() == 0) return 0; int flag = 0; if(str.charAt(0) == '+') flag = 1; else if(str.charAt(0) == '-') flag = 2; int start = flag > 0 ? 1 : 0; long res = 0; while(start < str.length()){ if(str.charAt(start) > '9' || str.charAt(start) < '0') return 0; res = res * 10 + (str.charAt(start) - '0'); start ++; } return flag == 2 ? -(int)res : (int)res; } }``

### 11. 正则表达式匹配

``public boolean isMatch(String s, String p) { if (s == null || p == null) { return false; } boolean[][] dp = new boolean[s.length()+1][p.length()+1]; dp[0][0] = true; for (int j = 0; i < p.length(); j++) { if (p.charAt(j) == '*' && dp[0][j-1]) { dp[0][j+1] = true; } } for (int i = 0 ; i < s.length(); i++) { for (int j = 0; j < p.length(); j++) { if (p.charAt(j) == '.') { dp[i+1][j+1] = dp[i][j]; } if (p.charAt(j) == s.charAt(i)) { dp[i+1][j+1] = dp[i][j]; } if (p.charAt(j) == '*') { if (p.charAt(j-1) != s.charAt(i) && p.charAt(j-1) != '.') { dp[i+1][j+1] = dp[i+1][j-1]; } else { dp[i+1][j+1] = (dp[i+1][j] || dp[i][j+1] || dp[i+1][j-1]); } } } } return dp[s.length()][p.length()]; }``

### 12. 表示数值的字符串

``public class Solution { public boolean isNumeric(char[] str) { int len = str.length; boolean sign = false, decimal = false, hasE = false; for(int i = 0; i < len; i++){ if(str[i] == '+' || str[i] == '-'){ if(!sign && i > 0 && str[i-1] != 'e' && str[i-1] != 'E') return false; if(sign && str[i-1] != 'e' && str[i-1] != 'E') return false; sign = true; }else if(str[i] == 'e' || str[i] == 'E'){ if(i == len - 1) return false; if(hasE) return false; hasE = true; }else if(str[i] == '.'){ if(hasE || decimal) return false; decimal = true; }else if(str[i] < '0' || str[i] > '9') return false; } return true; } }``

### 13. 字符流中第一个不重复的字符

``import java.util.HashMap; public class Solution { HashMap<Character, Integer> map = new HashMap<Character, Integer>(); StringBuffer s = new StringBuffer(); //Insert one char from stringstream public void Insert(char ch) { s.append(ch); if(map.containsKey(ch)){ map.put(ch, map.get(ch)+1); }else{ map.put(ch, 1); } } //return the first appearence once char in current stringstream public char FirstAppearingOnce() { for(int i = 0; i < s.length(); i++){ if(map.get(s.charAt(i)) == 1) return s.charAt(i); } return '#'; } }``
原文作者：老莫offer
原文地址: https://www.cnblogs.com/jobbible/p/10253802.html
本文转自网络文章，转载此文章仅为分享知识，如有侵权，请联系博主进行删除。