第一种思路,将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];
}
}