package y2019.Algorithm.str.hard; import java.util.Stack; /** * @ProjectName: cutter-point * @Package: y2019.Algorithm.str.hard * @ClassName: LongestValidParentheses * @Author: xiaof * @Description: 32. Longest Valid Parentheses * * Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring. * * Example 1: * * Input: "(()" * Output: 2 * Explanation: The longest valid parentheses substring is "()" * Example 2: * * Input: ")()())" * Output: 4 * Explanation: The longest valid parentheses substring is "()()" * * 求最長有效括號對,那麼就是要確保子串是連續 * @Date: 2019/8/6 9:51 * @Version: 1.0 */ public class LongestValidParentheses { public int solution(String s) { //用來統計最大的括號數,咱們只要能匹配成功就行 Stack<Integer> stack = new Stack(); char[] ss = s.toCharArray(); int n = ss.length, res = 0; //遍歷 for (int i = 0; i < ss.length; ++i) { if (ss[i] == '(') { stack.push(i); //用來存放int位置 } else { if (!stack.isEmpty()) { //若是不爲空,那麼就能夠進行匹配 if (ss[stack.peek()] == '(') stack.pop(); else stack.push(i); } else { stack.push(i); } } } //咱們只須要統計剩下沒法匹配的連續的(的數據比較就能夠了 //若是棧爲空,那麼正好徹底匹配 if (stack.isEmpty()) { res = n; } else { //若是不是徹底匹配,那麼就要計算連續兩個(的間隔 int r = n, l = 0; while (!stack.isEmpty()) { //不斷獲取最後的結束符號位置 l = stack.pop(); //取最長的串位置 res = Math.max(r - l - 1, res); r = l; //更新位置 } //最後還要判斷從起始位置開始到當前位置消掉的長度 res = Math.max(r, res); } return res; } }
package y2019.Algorithm.str.hard; /** * @ProjectName: cutter-point * @Package: y2019.Algorithm.str.hard * @ClassName: MinDistance * @Author: xiaof * @Description: 72. Edit Distance * Given two words word1 and word2, find the minimum number of operations required to convert word1 to word2. * * You have the following 3 operations permitted on a word: * * Insert a character * Delete a character * Replace a character * Example 1: * * Input: word1 = "horse", word2 = "ros" * Output: 3 * Explanation: * horse -> rorse (replace 'h' with 'r') * rorse -> rose (remove 'r') * rose -> ros (remove 'e') * Example 2: * * Input: word1 = "intention", word2 = "execution" * Output: 5 * Explanation: * intention -> inention (remove 't') * inention -> enention (replace 'i' with 'e') * enention -> exention (replace 'n' with 'x') * exention -> exection (replace 'n' with 'c') * exection -> execution (insert 'u') * @Date: 2019/8/7 11:42 * @Version: 1.0 */ public class MinDistance { public int solution(String word1, String word2) { int w1 = word1.length(), w2 = word2.length(); char w1s[] = word1.toCharArray(), w2s[] = word2.toCharArray(); int[][] dpcost = new int[w1 + 1][w2 + 1]; //初始化 for (int i = 0; i <= w1; ++i) { dpcost[i][0] = i; //標識要把word1的i個字符化爲0個,那就刪i次 } for (int j = 0; j <= w2; ++j) { dpcost[0][j] = j; } //這題動態規劃了,比較複雜說實話 //遍歷 for (int i = 1; i < dpcost.length; ++i) { for (int j = 1; j < dpcost[i].length; ++j) { //咱們把動態規劃遞增的量設置爲,word1前i個字符,轉換爲word2前j個字符須要的最小操做數 //f(i,j) = f(i-1, j-1) 當word1[i] == word2[j]的時候,相等字符,那麼當前字符就不須要花費操做次數 if (w1s[i - 1] == w2s[j - 1]) { dpcost[i][j] = dpcost[i - 1][j - 1]; } else { //當word1[i] != word2[j]的時候 分三種狀況平衡 //1.進行插入操做, 那就是新增一個同樣的字符和word2進行匹配,那就是word2的j位就直接新增進去,就不用比較了,咱們取沒有j號的次數 // f(i,j) = f(i, j-1) + 1; int insert = dpcost[i][j - 1]; //2.當進行刪除操做,那就是把word1當前字符刪除掉,當前位置至關於不比較 // f(i,j)=f(i-1,j) + 1; int remove = dpcost[i - 1][j]; //3.當進行替換操做,那就是把當前字符徹底替換,那麼就是新增一個操做,其他和以前同樣 // f(i,j)=f(i-1,j-1) + 1; int replace = dpcost[i - 1][j - 1]; dpcost[i][j] = Math.min(insert, Math.min(remove, replace)) + 1; } } } return dpcost[w1][w2]; } }
package y2019.Algorithm.str.hard; import java.util.HashMap; import java.util.Map; /** * @ProjectName: cutter-point * @Package: y2019.Algorithm.str.hard * @ClassName: MinWindow * @Author: xiaof * @Description: 76. Minimum Window Substring * Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n). * * Example: * * Input: S = "ADOBECODEBANC", T = "ABC" * Output: "BANC" * Note: * * If there is no such window in S that covers all characters in T, return the empty string "". * If there is such window, you are guaranteed that there will always be only one unique minimum window in S. * @Date: 2019/8/7 15:15 * @Version: 1.0 */ public class MinWindow { public String solution(String s, String t) { if (s == null || t == null || s.length() < t.length() || s.length() == 0 || t.length() == 0) { return ""; } //用索引,而且是單次循環 int l = 0, r = 0, count = t.length(), minle = s.length(), minl = 0, minr = 0; Map<Character, Integer> map = new HashMap(); boolean pipeiok = false; //第一次循環,初始化map for (int i = 0; i < t.length(); ++i) { map.put(t.charAt(i), map.getOrDefault(t.charAt(i), 0) + 1); } //循環遍歷字符串 while (r < s.length()) { //計算是否存在全部字符的子串 char curc = s.charAt(r); if (map.containsKey(curc)) { //若是包含 map.put(curc, map.get(curc) - 1); if (map.get(curc) >= 0) { //若是有效匹配 --count; } } //若是所有匹配完成,存在單字符匹配 while (count == 0 && l <= r) { pipeiok = true; int curlen = r - l + 1; if (curlen <= minle) { //存在更小值 minl = l; minr = r; minle = curlen; } //更新最左邊索引 char leftc = s.charAt(l); if (map.containsKey(leftc)) { //若是包含,那麼就找到了最左邊的第一個字符 //咱們把這個位置的字符剔除掉,而後看是否能夠找到更小的子串 map.put(leftc, map.get(leftc) + 1); if (map.get(leftc) >= 1) { //加一以後恢復到正常狀態 count++; } } //吧最左邊右移一次 l++; } r++; //日後遍歷 } return pipeiok == true ? s.substring(minl, minr + 1) : ""; } public static void main(String[] args) { String s[] = {"ADOBECODEBANC", "ABC"}; String s1[] = {"aa", "aa"}; MinWindow fuc = new MinWindow(); fuc.solution(s1[0], s1[1]); } }