數(shù)據(jù)結構與算法學習筆記(訓練營四)-經(jīng)典面試18(ppt-5)

  • 對于一個字符串, 從前開始讀和從后開始讀是一樣的, 我們就稱這個字符串是回文串。例如"ABCBA","AA", "A" 是回文串, 而"ABCD", "AAB"不是回文串。牛牛特別喜歡回文串, 他手中有一個字符串s, 牛牛在思考能否從字 符串中移除部分(0個或多個)字符使其變?yōu)榛匚拇?,并且牛牛認為空串不是回文串。牛牛發(fā)現(xiàn)移除的方案可能有 很多種, 希望你來幫他計算一下一共有多少種移除方案可以使s變?yōu)榛匚拇?。對于兩種移除方案, 如果移除的字 符依次構成的序列不一樣就是不同的方案。
    例如,XXY 4種 ABA 5種
    【說明】 這是今年的原題,提供的說明和例子都很讓人費解?,F(xiàn)在根據(jù)當時題目的所有測試用例,重新解釋當時的題目 含義: 1)"1AB23CD21",你可以選擇刪除A、B、C、D,然后剩下子序列{1,2,3,2,1},只要剩下的子序列是同一個,那 么就只算1種方法,和A、B、C、D選擇什么樣的刪除順序沒有關系。 2)"121A1",其中有兩個{1,2,1}的子序列,第一個{1,2,1}是由{位置0,位置1,位置2}構成,第二個{1,2,1} 是由{位置0,位置1,位置4}構成。這兩個子序列被認為是不同的子序列。也就是說在本題中,認為字面值一樣 但是位置不同的字符就是不同的。 3)其實這道題是想求,str中有多少個不同的子序列,每一種子序列只對應一種刪除方法,那就是把多余的東 西去掉,而和去掉的順序無關。
    4)也許你覺得我的解釋很荒謬,但真的是這樣,不然解釋不了為什么,XXY 4種 ABA 5種,而且其他的測 試用例都印證了這一點。
public class PalindromeNum {

    // 范圍上的嘗試模型
    public static int palindromeNum(String str){
        if(str == null || str.equals("")){
            return 0;
        }

        char[] c = str.toCharArray();
        int n = c.length;
        int[][] dp = new int[n][n];
        // 對角線全是1
        for (int i = 0; i < c.length; i++) {
            dp[i][i] = 1;
        }

        // 倒數(shù)第二條對角線
        for (int i = 0; i < n-1; i++) {
            dp[i][i+1] = c[i] == c[i+1] ? 3 : 2;
        }

        // 普遍位置,倒數(shù)前二行都已經(jīng)填過了,不用填,
        for (int i = n - 3; i >= 0 ; i--) {
            for (int j = i+2; j < n; j++) {
                dp[i][j] = dp[i+1][j] + dp[i][j-1] - dp[i+1][j-1];
                if(c[i] == c[j]){
                    dp[i][j] += dp[i+1][j-1] + 1;
                }
            }
        }

        return dp[0][n-1];
    }


    public static void main(String[] args) {
        String str1 = "xxy";
        String str2 = "ABA";
        System.out.println(palindromeNum(str1));
        System.out.println(palindromeNum(str2));
    }
}
  • 給定一個字符串str,求最長回文子序列長度。
/**
 * 給定一個字符串str,求最長回文子序列長度。
 */
public class MaxLenPalindromeSubSeq {

    public static int maxLenPalindromeSubSeq(String str){
        if(str == null || str.equals("")){
            return  0;
        }
        // 范圍上嘗試的模型
        // dp[i][j] 表示以開頭,j結尾的子串中最長回文子序列是多少
        // 由于是范圍上的嘗試模型,則左下部分無效
        int n = str.length();
        char[] c = str.toCharArray();
         int[][] dp = new int[n][n];
        // 對角線
        for (int i = 0; i < n; i++) {
            dp[i][i] = 1;
        }

        // 倒數(shù)第二條對角線
        for (int i = 0; i < n-1; i++) {
            dp[i][i+1] = c[i] == c[i+1] ? 2 : 1;
        }

        // 普遍位置
        // 1.i...j的回文子串以不以i,j結尾dp[i][j] = dp[i+1][j-1]
        // 2.i...j的回文子串以i開頭,不以j結尾 dp[i][j] = dp[i][j-1]
        // 3.i...j的回文子串不以i開頭,以j結尾 dp[i][j] = dp[i+1][j]
        // 4.i...j的回文子串以i開頭,以j結尾 dp[i][j] = dp[i+1][j-1](i,j位置字符相等)

        // 從下往上,從左往右
        // 倒數(shù)第三行開始
        for (int i = c.length-3; i >= 0; i--) {
            for (int j = i+2; j < n; j++) {
                dp[i][j] = Math.max(dp[i+1][j-1],Math.max(dp[i][j-1],dp[i+1][j]));
                if(c[i] == c[j]){
                    dp[i][j] = Math.max(dp[i][j],dp[i+1][j-1]+2);
                }
            }
        }
        return dp[0][n-1];
    }
    
}

  • 給定一個二維數(shù)組matrix,每個單元都是一個整數(shù),有正有負。最開始的時候小Q操縱 一條長度為0的蛇蛇從矩陣最左側任選一個單元格進入地圖,蛇每次只能夠到達當前位 置的右上相鄰,右側相鄰和右下相鄰的單元格。蛇蛇到達一個單元格后,自身的長度會 瞬間加上該單元格的數(shù)值,任何情況下長度為負則游戲結束。小Q是個天才,他擁有一 個超能力,可以在游戲開始的時候把地圖中的某一個節(jié)點的值變?yōu)槠湎喾磾?shù)(注:最多 只能改變一個節(jié)點)。問在小Q游戲過程中,他的蛇蛇最長長度可以到多少?
    比如:
    1 -4 10
    3 -2 -1
    2 -1 0
    0 5 -2
    最優(yōu)路徑為從最左側的3開始,3 -> -4(利用能力變成4) -> 10。所以返回17。
  • 給定一個字符串str,str表示一個公式,公式里可能有整數(shù)、加減乘除符號和左右 括號,返回公式的計算結果。
    【舉例】
    str="48((70-65)-43)+81",返回-1816。
    str="3+14",返回7。
    str="3+(1
    4)",返回7。
    【說明】 1.可以認為給定的字符串一定是正確的公式,即不需要對str做公式有效性檢查。 2.如果是負數(shù),就需要用括號括起來,比如"4(-3)"。但如果負數(shù)作為公式的開頭 或括號部分的開頭,則可以沒有括號,比如"-34"和"(-3*4)"都是合法的。 3.不用考慮計算過程中會發(fā)生溢出的情況。
/**
 * 給定一個字符串str,str表示一個公式,公式里可能有整數(shù)、加減乘除符號和左右 括號,返回公式的計算結果。
 * 【舉例】
 * str="48*((70-65)-43)+8*1",返回-1816。
 * str="3+1*4",返回7。
 * str="3+(1*4)",返回7。
 * 【說明】 1.可以認為給定的字符串一定是正確的公式,即不需要對str做公式有效性檢查。 2.如果是負數(shù),
 * 就需要用括號括起來,比如"4*(-3)"。但如果負數(shù)作為公式的開頭 或括號部分的開頭,則可以沒有括號,比
 * 如"-3*4"和"(-3*4)"都是合法的。 3.不用考慮計算過程中會發(fā)生溢出的情況。
 */
public class Calculate {
    public static int calculate(String str){
        char[] c = str.toCharArray();
        return process(c,0)[0];
    }

    // 從index開始算,返回index開始計算的有效結果,和計算到的位置
    //0位置,結果;1位置,此次計算到的位置
    public static int[] process(char[] c,int index){
        // 當前的數(shù)字
        int cur = 0;
        LinkedList<String> stack = new LinkedList<>();
        int[] res = new int[2];
        // 越界或者遇到右括號停止
        while (index < c.length && c[index] != ')'){
            // 如果遇到的是數(shù)字就收集數(shù)字
            if(c[index] >= '0' && c[index] <= '9'){
                // 數(shù)字
                cur = cur * 10 + (c[index] - '0');
                index ++;
            }else if(c[index] == '+' || c[index] == '-' || c[index] == '*' || c[index] == '/'){
                // 如果棧頂是乘除先計算在放
                if("*".equals(stack.peekFirst()) || "/".equals(stack.peekFirst())){
                    String op = stack.pop();
                    String num = stack.pop();
                    int re = 0;
                    if("*".equals(op)){
                        re = cur*Integer.parseInt(num);

                    }else {
                        re = cur/Integer.parseInt(num);
                    }
                    stack.push(re+"");
                    stack.push(String.valueOf(c[index]));
                    cur = 0;
                }else{
                    stack.push(cur+"");
                    stack.push(String.valueOf(c[index]));
                    cur = 0;
                }
                index++;
            }else{
                //左括號調用遞歸過程
                int[] process = process(c, index + 1);
                if("*".equals(stack.peekFirst()) ||"/".equals(stack.peekFirst())){
                    String op = stack.pop();
                    String num = stack.pop();
                    int re = 0;
                    if("*".equals(op)){
                        re = process[0]*Integer.parseInt(num);

                    }else {
                        re = process[0]/Integer.parseInt(num);
                    }
                    cur = re;
                    index = process[1]+1;
                }else{
                    cur = process[0];
                    index = process[1]+1;
                }
            }
        }

        int d = 0;
        if("*".equals(stack.peekFirst()) || "/".equals(stack.peekFirst())){
            String op = stack.pop();
            String num = stack.pop();
            int re = 0;
            if("*".equals(op)){
                re = cur*Integer.parseInt(num);

            }else {
                re = cur/Integer.parseInt(num);
            }
            stack.push(re+"");
        }else{
            stack.push(cur+"");
        }

        while (stack.size() >=2){
            int one = Integer.valueOf(stack.pollLast());
            String op = stack.pollLast();
            int two = Integer.valueOf(stack.pollLast());
            if(op.equals("+")){
                d = one + two;
            }else{
                d = one - two;
            }
            stack.addLast(d+"");
        }

        return new int[]{d,index};
    }


    public static void main(String[] args) {
       String str = "48*((70-65)-43)+8*1";
        System.out.println(calculate(str));
    }
}

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容