【LEETCODE】66、字符串分類,hard級別,題目:32,72,76

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]);

    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章