class Solution {
// 被访问过的记录
// 【错误点】定义boolean[]而不是定义成Boolean[],因为默认Boolean是null会空指针,而boolean默认是false
boolean[][] visited;
// 棋盘大小m*n
int m;
int n;
// 数位和
int cnt;
public int wardrobeFinishing(int m, int n, int cnt) {
// 首先需要理解各数位之和如何计算?主要就是用当前遍历的下标i和j,比如12和13,那么数位和=1+2+1+3=7
// 遍历方向就是向右和向下,这种就用深度优先用递归去回溯
// 在回溯的过程中重要的一点就是要记录当前节点是否已经被遍历过,就不用进行遍历了,而且是全局唯一被遍历过即可
// 定义数组去存储是否被遍历
visited = new boolean[m][n];
this.m = m;
this.n = n;
this.cnt = cnt;
return dfs(0, 0);
}
public int dfs(int i, int j) {
// 遍历结束的条件:边界,已经遍历过,超过数位和限制
if (i < 0 || i >= m || j < 0 || j >= n) {
return 0;
}
if (visited[i][j]) {
return 0;
}
if (digit(i) + digit(j) > cnt) {
return 0;
}
// 说明当前节点是可以的,进行标记
visited[i][j] = true;
// 继续找下面和右边的
return 1 + dfs(i + 1, j) + dfs(i, j + 1);
}
// 数位的公式
public int digit(int i) {
int tmpt = 0;
while (i != 0) {
tmpt = tmpt + i % 10;
i = i / 10;
}
return tmpt;
}
}
“`java
//思路:使用基本回溯做法即可。
class Solution {
int m;
int n;
boolean[][] visited;
public int wardrobeFinishing(int m, int n, int cnt) {
this.m=m;
this.n=n;
visited=new boolean[m][n];
return dfs(visited,0,0,cnt);
}
int dfs(boolean[][] visited,int i,int j,int cnt){
if(i>m-1||j>n-1||limit(i,j,cnt)||visited[i][j]) return 0;
visited[i][j]=true;
int res=1+dfs(visited,i,j+1,cnt)+dfs(visited,i+1,j,cnt);
return res;
}
boolean limit(int m, int n, int cnt){
int num=0;
while(m!=0){
num=num+m%10;
m/=10;
}
while(n!=0){
num=num+n%10;
n/=10;
}
return num>cnt;
}
class Solution {
int count=0;
public int wardrobeFinishing(int m, int n, int cnt) {
boolean[][] visited=new boolean[m][n];
return dfs(0,0,m,n,cnt,visited);
}
public int dfs(int i,int j,int m,int n,int cnt,boolean[][] visited){
if(i<0||i>=m||j<0||j>=n||(i/10+i%10+j/10+j%10+i/100+j/100)>cnt||visited[i][j]) return 0;
visited[i][j]=true;
return dfs(i+1,j,m,n,cnt,visited)+dfs(i,j+1,m,n,cnt,visited)+1;
}
}
class Solution {
boolean[][] visited;
public int wardrobeFinishing(int m, int n, int cnt) {
visited = new boolean[m][n];
return dfs(m, n, cnt, 0, 0);
}
int dfs(int m, int n, int cnt, int x, int y){
if(x >= m || y >= n || getSum(x) + getSum(y) > cnt || visited[x][y]){
return 0;
}
visited[x][y] = true;
return dfs(m, n, cnt, x+1, y) + dfs(m, n, cnt, x, y+1) + 1;
}
int getSum(int x){
int res = 0;
while(x > 0){
res += x % 10;
x /= 10;
}
return res;
}
class Solution {
public:
int wardrobeFinishing(int m, int n, int cnt) {
vector<vector<bool>> visit(m, vector<bool>(n, false));
return recur(0, 0, cnt, visit);
}
int recur(int i, int j, int cnt, vector<vector<bool>>& visit) {
int m = visit.size();
int n = visit[0].size();
if (i >= m || j >= n || visit[i][j] == true || digit(i) + digit(j) > cnt) {
return 0;
}
visit[i][j] = true;
int res = recur(i + 1, j, cnt, visit) + recur(i, j + 1, cnt, visit) + 1;
return res;
}
int digit(int x) {
int res = 0;
while(x != 0) {
res += x % 10;
x /= 10;
}
return res;
}
};
class Solution {
public:
int res = 0;
int wardrobeFinishing(int m, int n, int cnt) {
vector<vector<int>> valid(m, vector<int>(n, 1));
dfs(m, n, 0, 0, cnt, valid);
return res;
}
void dfs(int m, int n, int i, int j, int cnt, vector<vector<int>>& valid){
if(i<0 || i>=m) return;
if(j<0 || j>=n) return;
if(valid[i][j] == 0) return;
if(digit(i) + digit(j) > cnt) return;
valid[i][j] = 0;
res++;
//cout<<"i= "<<i<<" j= "<<j<<" res= "<<res<<endl;
dfs(m, n, i, j+1, cnt, valid);
dfs(m, n, i+1, j, cnt, valid);
return;
}
int digit(int num){
int sum = 0;
while(num != 0){
sum = sum + (num%10);
num = num/10;
}
return sum;
}
};
共以下 8 个回答
解题思路
– 首先需要理解各数位之和如何计算?主要就是用当前遍历的下标i和j,比如12和13,那么数位和=1+2+1+3=7
– 遍历方向就是向右和向下(题目给的,也是可达性分析得到的结论),这种就用深度优先用递归去回溯
– 在回溯的过程中重要的一点就是要记录当前节点是否已经被遍历过,就不用进行遍历了,而且是全局唯一被遍历过即可
【题解1】
“`java
//思路:使用基本回溯做法即可。
class Solution {
int m;
int n;
boolean[][] visited;
public int wardrobeFinishing(int m, int n, int cnt) {
this.m=m;
this.n=n;
visited=new boolean[m][n];
return dfs(visited,0,0,cnt);
}
int dfs(boolean[][] visited,int i,int j,int cnt){
if(i>m-1||j>n-1||limit(i,j,cnt)||visited[i][j]) return 0;
visited[i][j]=true;
int res=1+dfs(visited,i,j+1,cnt)+dfs(visited,i+1,j,cnt);
return res;
}
}
时间复杂度:O(mn)
空间复杂度:O(mn)
思路:更具题目要求,分别向下向右寻找,若不符合条件则直接返回,若符合条件递归计算
回溯
class Solution {
boolean[][] visited;
public int wardrobeFinishing(int m, int n, int cnt) {
visited = new boolean[m][n];
return dfs(m, n, cnt, 0, 0);
}
}
时间:O(mn)
空间:O(mn)
时间复杂度O(Mn),空间复杂度O(Mn)。
class Solution {
// 计算数字的各数位之和
private int digitSum(int x) {
int sum = 0;
while (x > 0) {
sum += x % 10;
x /= 10;
}
return sum;
}
}
注意点:刚开始没有考虑valid矩阵,会导致回溯时候重复计算,需注意