leetcode详解——衣橱整理

72 阅读3分钟

1.题目详解 LCR 130.衣橱整理

2.题目描述

家居整理师将待整理衣橱划分为 m x n 的二维矩阵 grid,其中 grid[i][j] 代表一个需要整理的格子。整理师自 grid[0][0] 开始 逐行逐列 地整理每个格子。

整理规则为:在整理过程中,可以选择 向右移动一格 或 向下移动一格,但不能移动到衣柜之外。同时,不需要整理 digit(i) + digit(j) > cnt 的格子,其中 digit(x) 表示数字 x 的各数位之和。

请返回整理师 总共需要整理多少个格子

示例 1:

输入: m = 4, n = 7, cnt = 5
输出: 18

提示:

  • 1 <= n, m <= 100
  • 0 <= cnt <= 20

3.算法思路

这是一道很典型的深度搜索类问题。 看思路:

  • 首先是要从(0,0)坐标出发,需要满足在矩阵内,即不越界。以及坐标数位之和要 <= cnt
  • 若满足上面条件,则次数+1
  • 按照深度搜索DFS的顺序进行遍历搜索查找(下、右)
  • 与此同时,要考虑已访问过的(i,j)不能重复访问,即要做剪枝处理。可以用一个二维数组arr[i][j],存放已访问过的格子。若已访问过,arr[i][j]设为true。每次访问前需要先判断格子是否已访问过,避免重复访问。

终止条件

(1)数组越界|| 行坐标与列坐标数位之和 > cnt || 当前[i][j]已访问过

(2)其他条件 +1

4. 代码实现

class Solution {

    /**
     *
     * 终止条件
     * (1)数组越界||超过不需要整理的数值|| 行坐标与列坐标数位之和 > cnt || 当前[i][j]已访问过
     * (2)其他条件 +1
     * 
     *
     * 实现流程:
     * (1)从(0,0)出发,需要满足在矩阵内与数位之和<=cnt。若超出边界或者行坐标与列坐标数位之和 > cnt, +0
     * (2)判断格子是否已整理过,做剪枝处理
     *  将每个坐标对应的值存储到一个boolean二维数组中,如果没有整理过,就置为true且+1;每次整理前先判断该格是否已整理
     * (3)按照DFS的顺序进行搜索查找(下、右)
     *
     */
    int count = 0;
    public int wardrobeFinishing(int m, int n, int cnt) {
         //用来做标记的数组
        boolean[][] arr = new boolean[m][n];
        //从(0,0)坐标开始
        dfs(0,0,m,n,cnt,arr);
        return count;

    }
     public void dfs(int i, int j, int m, int n, int cnt, boolean[][] arr){
          int sum = getSum(i) + getSum(j);
        //1、数组越界;i与j数位之和 > cnt;各自已经被整理过,不需要整理,直接跳过
        if(i >= m || j >= n || i < 0 || j < 0 || sum > cnt || arr[i][j]) return;

        //2、格子没有整理过,标记为整理true,次数+1。防止重复整理
        arr[i][j] = true;
        count++;

        //3、DFS深度向下遍历
        dfs(i+1,j,m,n,cnt,arr);
        dfs(i,j+1,m,n,cnt,arr);
    }
     /**
     * 获取各数位之和
     **/
    private int getSum(int x){
        int res = 0;
        while(x != 0){
            res += x % 10;
            x = x / 10;
        }
        return res;
    }
}