leetcode 18


第一种思路,将str倒过来设置为str2.将str和str2的最长公共子序列求出来就可以了,一个做行 一个做列 dp操作
第二个思路,两个位置 一个L 一个R 同样一个行 一个列,不用倒过来,一个str就够了,
分为四种情况 包含LR 只包含L 只包含R 都不包含 dp操作

在这里插入图片描述

public class SnakeGam {
    public static int walk1(int[][] matrix){
        if(matrix == null || matrix.length == 0){
            return 0;
        }
        int res = Integer.MIN_VALUE;
        for (int i = 0; i < matrix.length; i++) {
            for(int j =0;j < matrix[0].length;j++){
                int[] ans = process(matrix,i,j);
                res = Math.max(res,Math.max(ans[0],ans[1]));
            }
        }
        return res;
    }

    /**
     *
     * @param m
     * @param i
     * @param j
     * @return 返回的第一个代表不使用能力的情况 第二个代表使用一次能力的情况
     */
    public static int[] process(int[][] m,int i,int j){
       if(j == 0){
           return new int[]{m[i][j],-m[i][j]};
       }

       //j>0的 左边肯定有路的 因为前面的判断已经隐含了
        //下面是左边路的情况
        int[] preAns = process(m,i,j-1);
       int preUnuse = preAns[0];
       int preUse = preAns[1];

       //左上角的情况
       if(i-1 >= 0){
           preAns = process(m,i-1,j-1);
           preUnuse = Math.max(preUnuse,preAns[0]);
           preUse = Math.max(preUse,preAns[1]);
       }

       //右下角的情况
        if(i+1 <m.length){
            preAns = process(m,i+1,j-1);
            preUnuse = Math.max(preUnuse,preAns[0]);
            preUse  = Math.max(preUse,preAns[1]);
        }

        int no= -1;//之前没有使用过能力,当前位置也不使用能力
        int yes = -1;//之前使用过能力,当前不适用,或者 之前没有使用过能力,这次使用,所以有两种情况

        //如果下面两个判断都小于0,说明这条蛇没有路可以走了,所以返回-1
        if(preUnuse >= 0){
            no = m[i][j] + preUnuse;
            yes = -m[i][j] + preUnuse;
        }
        
        if(preUse>=0){
            yes = Math.max(yes,m[i][j] + preUse);
        }
        return new int[] {no,yes};
    }
}

在这里插入图片描述

import java.util.LinkedList;


public class ExpressionCompute {

   public static int[] value(char[] str,int i){
       //双端队列模拟栈
       LinkedList<String> que = new LinkedList<>();
       int cur=  0;
       int[] bra = null;

       while(i < str.length && str[i] != ')'){
           if(str[i] >= '0' && str[i] <= '9'){
               cur = cur * 10 + str[i++] - '0';
           }else if(str[i] != '('){//是运算符的情况
               addNum(que,cur); 
               que.addLast(String.valueOf(str[i++]));
               cur = 0;
           }else{//是左括号的情况
               bra = value(str,i+1);
               cur = bra[0];
               i = bra[1]+1;
           }
       }
       //比如 1+3*2  它这个处理是 1+处理了  3*处理了 还有个2
       //所以这一行是处理剩下的数字
       addNum(que,cur);
       //getNum自己实现就可以了
       return new int[]{getNum(que),i};
   }

    public static void addNum(LinkedList<String> que,int num){
        if(!que.isEmpty()){
           int cur = 0;
           String top = que.pollLast();
            if (top.equals("+") || top.equals("-")) {
                que.addLast(top);
            }else{
                cur = Integer.valueOf(que.pollLast());
                num = top.equals("*")?(cur*num):(cur/num);
            }
        }
        que.addLast(String.valueOf(num));
    }
}

回文子序列
普遍方案:
1.不保留LR【ABCBD]
2.保留L 不保留R 【ABCAD]
3.不保留L 保留R
4.既保留L 也保留R
dp[L+1][R] 一定不包含L,可以含有R,或者不还有R 所以是1和3的情况相加
dp[L][R-1] 同理,是1和2的情况相加

如果L位置和R位置相等 dp[L][R] =dp[L+1][R-1】 + 1.中间是空串的情况

public class PalindromeWays {
    public static int way2(String str){
        char[] s = str.toCharArray();
        int n = str.length();
        int[][] dp = new int[n][n];
        for (int i = 0; i < n; i++) {
            dp[i][i] = 1;
        }
        for (int i = 0; i < n - 1; i++) {
            dp[i][i+1] =  s[i] == s[i+1] ? 3 : 2;
        }

        for(int i = n-3;i >=0;i--) {
            for (int j = i + 2; j < n; j++) {
                //第一种情况 依赖dp[L+1][R] a+c
                //第二种情况         a+b
                //求2a+b+c = a+c + a+b -a 所以 是下面的形式 说起来很抽象
                //这个是混合依赖
                dp[i][j] = dp[i + 1][j] + dp[i][j - 1] - dp[i + 1][j - 1];
                if (s[i] == s[j]) {
                    dp[i][j] = dp[i + 1][j - 1] + 1;
                }
            }
        }
        return dp[n-1][n-1];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值