Leetcode剑指offer
11、机器人的运动范围(13、Medium)
1)题目要求
地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?
示例 1:
输入:m = 2, n = 3, k = 1
输出:3
示例 2:
输入:m = 3, n = 1, k = 0
输出:1
提示:
1 <= n,m <= 100
0 <= k <= 20
2)我的解法
1、DFS
class Solution {
private boolean[][] visited;
public int compute(int i){
if(i==100)return 1;
return i/10+i%10;
}
public int dfs(int i,int j,int m,int n,int k){
if(i<0||i>=m||j<0||j>=n||compute(i)+compute(j)>k||visited[i][j])return 0;
visited[i][j]=true;
int l=dfs(i,j-1,m,n,k);
int r=dfs(i,j+1,m,n,k);
int u=dfs(i-1,j,m,n,k);
int d=dfs(i+1,j,m,n,k);
return l+r+u+d+1;
}
public int movingCount(int m, int n, int k) {
visited=new boolean[m][n];
return dfs(0,0,m,n,k);
}
}
2、BFS
class Solution {
private boolean[][] visited;
public int compute(int i){
if(i==100)return 1;
return i/10+i%10;
}
public int movingCount(int m, int n, int k) {
visited=new boolean[m][n];
Queue<int[]> q=new LinkedList<>();
q.offer(new int[2]);
visited[0][0]=true;
int result=1;
int x=0,y=0;
int[][] tool=new int[][]{{0,-1},{0,1},{-1,0},{1,0}};
while(!q.isEmpty()){
int[] front=q.poll();
for(int i=0;i<4;i++){
x=front[0]+tool[i][0];y=front[1]+tool[i][1];
if(x<0||x>=m||y<0||y>=n||compute(x)+compute(y)>k||visited[x][y])continue;
visited[x][y]=true;
q.offer(new int[]{x,y});
result++;
}
}
return result;
}
}
3)其他解法
1、DFS
class Solution {
int m, n, k;
boolean[][] visited;
public int movingCount(int m, int n, int k) {
this.m = m; this.n = n; this.k = k;
this.visited = new boolean[m][n];
return dfs(0, 0, 0, 0);
}
public int dfs(int i, int j, int si, int sj) {
if(i >= m || j >= n || k < si + sj || visited[i][j]) return 0;
visited[i][j] = true;
return 1 + dfs(i + 1, j, (i + 1) % 10 != 0 ? si + 1 : si - 8, sj) + dfs(i, j + 1, si, (j + 1) % 10 != 0 ? sj + 1 : sj - 8);
}
}
2、BFS
class Solution {
public int movingCount(int m, int n, int k) {
boolean[][] visited = new boolean[m][n];
int res = 0;
Queue<int[]> queue= new LinkedList<int[]>();
queue.add(new int[] { 0, 0, 0, 0 });
while(queue.size() > 0) {
int[] x = queue.poll();
int i = x[0], j = x[1], si = x[2], sj = x[3];
if(i >= m || j >= n || k < si + sj || visited[i][j]) continue;
visited[i][j] = true;
res ++;
queue.add(new int[] { i + 1, j, (i + 1) % 10 != 0 ? si + 1 : si - 8, sj });
queue.add(new int[] { i, j + 1, si, (j + 1) % 10 != 0 ? sj + 1 : sj - 8 });
}
return res;
}
}
作者:jyd
链接: link
来源:力扣(LeetCode)
4)自己的优化代码
class Solution {
private boolean[][] visited;
public int movingCount(int m, int n, int k) {
visited=new boolean[m][n];
Queue<int[]> q=new LinkedList<>();
q.offer(new int[4]);//后两位为数位和,只算增量
visited[0][0]=true;
int result=1;
int x=0,y=0;
int _x=0,_y=0;//数位和
int[][] tool=new int[][]{{0,1},{1,0}};//向右和向下两个方向就够了
while(!q.isEmpty()){
int[] front=q.poll();
for(int i=0;i<2;i++){
x=front[0]+tool[i][0];y=front[1]+tool[i][1];
_x=(tool[i][0]==1)?((front[0]%10==9)?front[2]-8:front[2]+1):front[2];
_y=(tool[i][1]==1)?((front[1]%10==9)?front[3]-8:front[3]+1):front[3];
if(x<0||x>=m||y<0||y>=n||_x+_y>k||visited[x][y])continue;
visited[x][y]=true;
q.offer(new int[]{x,y,_x,_y});
result++;
}
}
return result;
}
}
5)学到的东西
DFS、BFS
剪枝:仅向右和向下即可
只算增量
12、剪绳子(14-1、Meium)
1)题目要求
给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]…k[m-1] 。请问 k[0]k[1]…*k[m-1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
示例 1:
输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1
示例 2:
输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36
提示:
2 <= n <= 58
2)我的解法
找规律+动态规划
class Solution {
public int cuttingRope(int n) {
int[] dp=new int[n+1];
for(int i=2;i<=n;i++){
if(i==2||i==3)dp[i]=i-1;
else dp[i]=Math.max(Math.max(2*dp[i-2],3*dp[i-3]),Math.max(2*(i-2),3*(i-3)));
}
return dp[n];
}
}
3)其他解法
class Solution {
public int cuttingRope(int n) {
if(n <= 3) return n - 1;
int a = n / 3, b = n % 3;
if(b == 0) return (int)Math.pow(3, a);
if(b == 1) return (int)Math.pow(3, a - 1) * 4;
return (int)Math.pow(3, a) * 2;
}
}
作者:jyd
链接:link
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
2、
public int cuttingRope(int n) {
int[] dp = new int[n + 1];
dp[1] = 1;
for (int i = 2; i <= n; i++) {
for (int j = 1; j < i; j++) {
dp[i] = Math.max(dp[i], (Math.max(j, dp[j])) * (Math.max(i - j, dp[i - j])));
}
}
return dp[n];
}
作者:sdwwld
链接:link
来源:力扣(LeetCode)
4)自己的优化代码
1、
class Solution {
public int cuttingRope(int n) {
int[] dp=new int[n+1];
for(int i=2;i<=n;i++){
for(int j=0;j<=i;j++){
dp[i]=Math.max(dp[i],Math.max(Math.max(j*dp[i-j],(i-j)*dp[j]),Math.max(j*(i-j),dp[i-j]*dp[j])));
}
}
return dp[n];
}
}
2、
class Solution {
public int cuttingRope(int n) {
if(n==2||n==3)return n-1;
else if(n%3==0)return (int)Math.pow(3,n/3);
else if(n%3==2)return (int)Math.pow(3,n/3)*2;
else return (int)Math.pow(3,n/3-1)*4;
}
}
5)学到的东西
动态规划、找规律
13、剪绳子 II(14-2、Medium)
1)题目要求
给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]…k[m - 1] 。请问 k[0]k[1]…*k[m - 1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
示例 1:
输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1
示例 2:
输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36
提示:
2 <= n <= 1000
2)我的解法
class Solution {
public int Mypow(int mi){
double result=1;
while(mi>0){
result=(result*3)%1000000007;
mi--;
}
return (int)result;
}
public int cuttingRope(int n) {//double 转 int 精度丢失,分成多个
if(n==2||n==3)return n-1;
double result=0;
if(n%3==0)result=Mypow(n/3);
else if(n%3==2)result=Mypow(n/3)*2;
else result=((Mypow(n/3-1)*2)%1000000007)*2;
return (int)(result%1000000007);
}
}
3)其他解法
class Solution {
public int cuttingRope(int n) {
if(n <= 3) return n - 1;
int b = n % 3, p = 1000000007;
long rem = 1, x = 3;
for(int a = n / 3 - 1; a > 0; a /= 2) {
if(a % 2 == 1) rem = (rem * x) % p;
x = (x * x) % p;
}
if(b == 0) return (int)(rem * 3 % p);
if(b == 1) return (int)(rem * 4 % p);
return (int)(rem * 6 % p);
}
}
作者:jyd
链接: link
来源:力扣(LeetCode)
2、
class Solution {
public int cuttingRope(int n) {
if(n == 2) {
return 1;
}
if(n == 3){
return 2;
}
int mod = (int)1e9 + 7;
long res = 1;
while(n > 4) {
res *= 3;
res %= mod;
n -= 3;
}
return (int)(res * n % mod);
}
}
3、快速幂
class Solution {
private int mod = (int)1e9 + 7;
public int cuttingRope(int n) {
if(n < 4){
return n-1;
}
int cnt3 = n / 3;
if(n % 3 == 0){
return (int)pow(3, cnt3);
} else if(n % 3 == 1){
return (int)((pow(3, cnt3 - 1) * 4) % mod);
} else {
return (int)((pow(3, cnt3) * 2) % mod);
}
}
private long pow(long base, int num){
long res = 1;
while(num > 0){
if((num & 1) == 1){
res *= base;
res %= mod;
}
base *= base;
base %= mod;
num >>= 1;
}
return res;
}
}
作者:HenryLee4
链接:link
来源:力扣(LeetCode)
4)自己的优化代码
1、
class Solution {
public int cuttingRope(int n) {//double 转 int 精度丢失,分成多个
if(n==2||n==3)return n-1;
double result=1;
while(n>4){
result=(result*3)%1000000007;
n=n-3;
}
return (int)((result*n)%1000000007);
}
}
2、
class Solution {
public long Mypow(int mi){
long result=1;//两个必须为long
long base=3;
while(mi>0){
if(mi%2==1){
result*=base;
result%=1000000007;
}
base=(base*base)%1000000007;
mi/=2;
}
return result;
}
public int cuttingRope(int n) {//double 转 int 精度丢失,分成多个
if(n==2||n==3)return n-1;
long result=0;
if(n%3==0)result=Mypow(n/3);
else if(n%3==2)result=Mypow(n/3)*2;
else result=Mypow(n/3-1)*4;
return (int)(result%1000000007);
}
}
5)学到的东西
贪心法
大数求余:循环求余;二分求余
14、二进制中1的个数(15、Easy)
1)题目要求
请实现一个函数,输入一个整数,输出该数二进制表示中 1 的个数。例如,把 9 表示成二进制是 1001,有 2 位是 1。因此,如果输入 9,则该函数输出 2。
示例 1:
输入:00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 ‘1’。
示例 2:
输入:00000000000000000000000010000000
输出:1
解释:输入的二进制串 00000000000000000000000010000000 中,共有一位为 ‘1’。
示例 3:
输入:11111111111111111111111111111101
输出:31
解释:输入的二进制串 11111111111111111111111111111101 中,共有 31 位为 ‘1’。
2)我的解法
public class Solution {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
int result=0,temp=0;
while(n!=0){
temp=n>>>1;
temp=temp<<1;
if((n-temp)==1)result++;
n=n>>>1;//必须用无符号右移
}
return result;
}
}
3)其他解法
1、 Java中的Integer.bitCount(n);
2、
public class Solution {
public int hammingWeight(int n) {
int res = 0;
while(n != 0) {
res += n & 1;
n >>>= 1;
}
return res;
}
}
3、
public class Solution {
public int hammingWeight(int n) {
int res = 0;
while(n != 0) {
res++;
n &= n - 1;
}
return res;
}
}
作者:jyd
链接:link
来源:力扣(LeetCode)
4)自己的优化代码
1、
public class Solution {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
int result=0,temp=0;
while(n!=0){
result++;
n=n&(n-1);
}
return result;
}
}
2、
public class Solution {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
int result=0,temp=0;
while(n!=0){
result+=n&1;
n=n>>>1;
}
return result;
}
}
5)学到的东西
位运算
n&1,检测最低位是否为1
15、 数值的整数次方(16、Medium)
1)题目要求
实现函数double Power(double base, int exponent),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。
示例 1:
输入: 2.00000, 10
输出: 1024.00000
示例 2:
输入: 2.10000, 3
输出: 9.26100
示例 3:
输入: 2.00000, -2
输出: 0.25000
解释: 2-2 = 1/22 = 1/4 = 0.25
说明:
-100.0 < x < 100.0
n 是 32 位有符号整数,其数值范围是 [−231, 231 − 1] 。
2)我的解法
class Solution {
public double myPow(double x, int n) {
double result=1;
while(n!=0){
if(n%2!=0){
if(n>0)result*=x;
else result/=x;
}
x*=x;
n/=2;
}
return result;
}
}
3)其他解法
class Solution {
public double myPow(double x, int n) {
if(x == 0) return 0;
long b = n;
double res = 1.0;
if(b < 0) {
x = 1 / x;
b = -b;
}
while(b > 0) {
if((b & 1) == 1) res *= x;
x *= x;
b >>= 1;
}
return res;
}
}
作者:jyd
链接:link
来源:力扣(LeetCode)
4)自己的优化代码
class Solution {
public double myPow(double x, int n) {
double result=1;
while(n!=0){
if((n&1)==1){
if(n>0)result*=x;
else result/=x;
}
x*=x;
n/=2;
}
return result;
}
}
5)学到的东西
位运算
if((n&1)==1)等价于if(n%2!=0)
16、打印从1到最大的n位数(17、Easy)
1)题目要求
输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。
示例 1:
输入: n = 1
输出: [1,2,3,4,5,6,7,8,9]
说明:
用返回一个整数列表来代替打印
n 为正整数
2)我的解法
1、不考虑大数:
class Solution {
public int[] printNumbers(int n) {
int[] result=new int[(int)(Math.pow(10,n))-1];
for(int i=0;i<result.length;i++)result[i]=i+1;
return result;
}
}
2、考虑大数
class Solution {
public String[] printNumbers(int n) {
char[] r=new char[n];
String[] result=new String[(int)Math.pow(10, n)-1];
for(int i=0;i<result.length;i++){
int j=0;
int temp=i;
while(true){
j++;
if(j==1)r[n-j]=(char)(temp%10+'1');
else r[n-j]=(char)(temp%10+'0');
if(j>1&&r[n-j+1]==':'){
r[n-j+1]='0';
r[n-j]=(char)(temp%10+'1');
}
temp=temp/10;
if(temp==0)break;
}
if(r[n-j]==':'){
r[n-j]='0';
j++;
r[n-j]=(char)(temp%10+'1');
}
result[i]=new String(r,n-j,j);//第三个参数为长度
}
return result;
}
}
3)其他解法
class Solution {
StringBuilder res;
int nine = 0, count = 0, start, n;
char[] num, loop = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
public String printNumbers(int n) {
this.n = n;
res = new StringBuilder();
num = new char[n];
start = n - 1;
dfs(0);
res.deleteCharAt(res.length() - 1);
return res.toString();
}
void dfs(int x) {
if(x == n) {
String s = String.valueOf(num).substring(start);
if(!s.equals("0")) res.append(s + ",");
if(n - start == nine) start--;
return;
}
for(char i : loop) {
if(i == '9') nine++;
num[x] = i;
dfs(x + 1);
}
nine--;
}
}
本题要求输出 int 类型数组。为 运行通过 ,可在添加数字字符串 ss 前,将其转化为 int 类型。代码如下所示:
class Solution {
int[] res;
int nine = 0, count = 0, start, n;
char[] num, loop = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
public int[] printNumbers(int n) {
this.n = n;
res = new int[(int)Math.pow(10, n) - 1];
num = new char[n];
start = n - 1;
dfs(0);
return res;
}
void dfs(int x) {
if(x == n) {
String s = String.valueOf(num).substring(start);
if(!s.equals("0")) res[count++] = Integer.parseInt(s);
if(n - start == nine) start--;
return;
}
for(char i : loop) {
if(i == '9') nine++;
num[x] = i;
dfs(x + 1);
}
nine--;
}
}
作者:jyd
链接:link
来源:力扣(LeetCode)
4)自己的优化代码
class Solution {
public int[] printNumbers(int n) {
char[] r=new char[n];
int[] result=new int[(int)Math.pow(10, n)-1];
for(int i=0;i<result.length;i++){
int j=0;
int temp=i;
while(true){
j++;//倒数第j位
if(j==1)r[n-j]=(char)(temp%10+'1');//从1开始
else r[n-j]=(char)(temp%10+'0');
if(j>1&&r[n-j+1]==':'){//后一位为:,即'9'后面那个字符时,要进位
r[n-j+1]='0';
r[n-j]=(char)(temp%10+'1');
}
temp=temp/10;
if(temp==0)break;
}
if(r[n-j]==':'){//最高位为:
r[n-j]='0';
j++;
r[n-j]=(char)(temp%10+'1');
}
result[i]=Integer.parseInt(new String(r,n-j,j));//第三个参数为长度
}
return result;
}
}
5)学到的东西
new String(char[],int start,int len)最后一个参数为长度
大数字符串拼接
17、删除链表的节点(18、Easy)
1)题目要求
给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
返回删除后的链表的头节点。
注意:此题对比原题有改动
示例 1:
输入: head = [4,5,1,9], val = 5
输出: [4,1,9]
解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.
示例 2:
输入: head = [4,5,1,9], val = 1
输出: [4,5,9]
解释: 给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9.
说明:
题目保证链表中节点的值互不相同
若使用 C 或 C++ 语言,你不需要 free 或 delete 被删除的节点
2)我的解法
class Solution {
public ListNode deleteNode(ListNode head, int val) {
ListNode cur=head;
if(head==null)return null;
if(head.val==val){head=head.next;return head;}
while(cur.next!=null&&cur.next.val!=val){
cur=cur.next;
}
cur.next=cur.next.next;
return head;
}
}
3)其他解法
class Solution {
public ListNode deleteNode(ListNode head, int val) {
if(head.val == val) return head.next;
ListNode pre = head, cur = head.next;
while(cur != null && cur.val != val) {
pre = cur;
cur = cur.next;
}
if(cur != null) pre.next = cur.next;
return head;
}
}
作者:jyd
链接: link
来源:力扣(LeetCode)
4)自己的优化代码
class Solution {
public ListNode deleteNode(ListNode head, int val) {
ListNode cur=head;
if(head.val==val){return head.next;}
while(cur.next!=null&&cur.next.val!=val){
cur=cur.next;
}
cur.next=cur.next.next;
return head;
}
}
5)学到的东西
链表
18、正则表达式匹配(19、Hard)
1)题目要求
请实现一个函数用来匹配包含’. ‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但与"aa.a"和"ab*a"均不匹配。
示例 1:
输入:
s = “aa”
p = “a”
输出: false
解释: “a” 无法匹配 “aa” 整个字符串。
示例 2:
输入:
s = “aa”
p = “a*”
输出: true
解释: 因为 ‘*’ 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 ‘a’。因此,字符串 “aa” 可被视为 ‘a’ 重复了一次。
示例 3:
输入:
s = “ab”
p = “."
输出: true
解释: ".” 表示可匹配零个或多个(’*’)任意字符(’.’)。
示例 4:
输入:
s = “aab”
p = “cab”
输出: true
解释: 因为 ‘*’ 表示零个或多个,这里 ‘c’ 为 0 个, ‘a’ 被重复一次。因此可以匹配字符串 “aab”。
示例 5:
输入:
s = “mississippi”
p = “misisp*.”
输出: false
s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母以及字符 . 和 ,无连续的 '’。
2)我的解法
尽力了。。
“baabbbaccbccacacc”
“c*…baa.*a…*c”
倒在了上面的例子上
class Solution {
public boolean CanDelete(String s,int i,String p,int j){
//若最终s遍历完成,p还剩下东西,判断剩下的东西可否抹去,比如剩个a*就可以抹去
if(j>0&&p.charAt(j)=='*'&&p.charAt(j-1)=='.'&&j<p.length()-1){
int k=s.length()-1;
while(k>=0){
if(isMatch(s.substring(k),p.substring(j+1)))return true;
k--;
}
return false;
}
else if(p.charAt(j)=='*'){
int k=j+1;
while(k<p.length()){
if(p.charAt(k)==s.charAt(s.length()-1))k++;
else if(k<p.length()-1&&p.charAt(k+1)=='*')k=k+2;
else return false;
}
}
else {
if(j+1>=p.length()||p.charAt(j+1)!='*')return false;
if(j+2<p.length())return CanDelete(s,i,p,j+2);
}
return true;
}
public boolean isMatch(String s, String p) {
int i=0,j=0;
if(s.length()!=p.length()&&!p.contains("*"))return false;
char sc,pc;
while(i<s.length()&&j<p.length()){
sc=s.charAt(i);
pc=p.charAt(j);
if(pc=='.'){
i++;j++;
}
else if(pc=='*'){
if(i>0&&sc!=s.charAt(i-1)&&p.charAt(j-1)!='.')j++;
else {
if(!isMatch(s.substring(i-1),p.substring(j+1)))i++;//如果后面的匹配不上,这里就多分配一个
else return true;
}
}
else{
if(j<p.length()-1&&p.charAt(j+1)=='*'&&sc!=pc){j++;j++;continue;}
else if(sc!=pc)return false;
i++;j++;
}
}
if((j<p.length()&&!CanDelete(s,i,p,j))||i<s.length())return false;
return true;
}
}
3)其他解法
class Solution {
public:
bool isMatch(string s, string p) {
int sLen = s.length(), pLen = p.length();
vector<vector<bool> > dp(sLen + 1, vector<bool>(pLen + 1, false));
dp[0][0] = true;
for(int i=1; i<=pLen; ++i)
{
if(i >= 2 && p[i - 1] == '*' && dp[0][i - 2] == true) // 记得加 i >= 2的判断
dp[0][i] = true;
}
for(int i=1; i<=sLen; ++i)
{
for(int j=1; j<=pLen; ++j)
{
if(s[i - 1] == p[j - 1] || p[j - 1] == '.')
dp[i][j] = dp[i - 1][j - 1];
else if(p[j - 1] == '*' && j >= 2) // 记得加 j >= 2的判断,否则 s = aa, p = *a 过不去测试
{
if(p[j - 2] != s[i - 1] && p[j - 2] != '.')
dp[i][j] = dp[i][j - 2];
else
dp[i][j] = dp[i][j - 2] || dp[i][j - 1] || dp[i - 1][j];
}
else dp[i][j] = false;
}
}
return dp[sLen][pLen];
}
};
作者:superkakayong
链接: link
来源:力扣(LeetCode)
4)自己的优化代码
class Solution {
public boolean isMatch(String s, String p) {
int n=s.length(),m=p.length();
boolean[][] dp=new boolean[n+1][m+1];
dp[0][0]=true;
for(int k=1;k<m+1;k++){//初始化dp(当s为空时)
if(p.charAt(k-1)=='*')dp[0][k]=dp[0][k-1];//当前为'*'时
else if(k<p.length()&&p.charAt(k)=='*')dp[0][k]=dp[0][k-1];//当前不为'*'但它的下一个为'*'
else dp[0][k]=false;
}
for(int i=1;i<n+1;i++){
for(int j=1;j<m+1;j++){
//j==0时,dp[i][j]为false
if(p.charAt(j-1)=='*'&&j>=2){//为'*'时
if(p.charAt(j-2)!=s.charAt(i-1)&&p.charAt(j-2)!='.'){
//*前面字符那个与i-1匹配不上,则这两个字符(比如a*)不要了
dp[i][j]=dp[i][j-2];
}
else {//*前面字符那个与i-1匹配上了
//dp[i][j-2]代表a*取0个,dp[i-1][j]代表取多个
dp[i][j]=dp[i-1][j]||dp[i][j-2];//比如aa*和a,即使匹配上了,后面的a*也不能要
}
}
else if(p.charAt(j-1)=='.')dp[i][j]=dp[i-1][j-1];
else{ //正常字符
if(p.charAt(j-1)==s.charAt(i-1)&&i>0)dp[i][j]=dp[i-1][j-1];
//不等的时候为false
}
}
}
return dp[n][m];
}
}
5)学到的东西
动态规划
与前面结果的关系
(此题多刷几次)