动态规划,dfs

鸡蛋掉落问题

你将获得 K 个鸡蛋,并可以使用一栋从 1 到 N 共有 N 层楼的建筑。
每个蛋的功能都是一样的,如果一个蛋碎了,你就不能再把它掉下去。
你知道存在楼层 F ,满足 0 <= F <= N 任何从高于 F 的楼层落下的鸡蛋都会碎,从 F 楼层或比它低的楼层落下的鸡蛋都不会破。
每次移动,你可以取一个鸡蛋(如果你有完整的鸡蛋)并把它从任一楼层 X 扔下(满足 1 <= X <= N)。
你的目标是确切地知道 F 的值是多少。
无论 F 的初始值如何,你确定 F 的值的最小移动次数是多少?
思路:这个问题和智力题里,猜数字大小很像。遍历1-N层,计算在每一层扔鸡蛋的最小值,用递归的方式。假设在i层扔鸡蛋,对应鸡蛋碎了,没碎两种可能

public static int superEggDrop(int K, int N) {
    if( N == 0 || N == 1 || K ==1){
        return N;
    }
    int minimun = N;
    for(int i = 1; i <= N; i++){ // 依次遍历从第1层到第N层开始扔第1个鸡蛋的情况
        int tMin = Math.max(superEggDrop(K-1, i-1), superEggDrop(K, N-i));
        minimun = Math.min(minimun, 1 + tMin);
    }
    return minimun;
}

// 以上是最简单的解法,改进的办法是加入中间表,减少重复的节点计算, 如下所示:
class Solution {
    public int superEggDrop(int K, int N) {
        int[][] middleResults = new int[K + 1][N + 1];
        for (int i = 1; i <= N; i++) {
            middleResults[1][i] = i; // only one egg
            middleResults[0][i] = 0; // no egg
        }
        for (int i = 1; i <= K; i++) {
            middleResults[i][0] = 0; // zero floor
        }

        for (int k = 2; k <= K; k++) { // start from two egg
            for (int n = 1; n <= N; n++) {
                int tMinDrop = N * N;
                for (int x = 1; x <= n; x++) {
                    tMinDrop = Math.min(tMinDrop, 1 + Math.max(middleResults[k - 1][x - 1], middleResults[k][n - x]));
                }
                middleResults[k][n] = tMinDrop;
            }
        }

        return middleResults[K][N];
    }
}

最大正方形

输入:
1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
输出: 4
思路:动态规划,如果是最大矩阵,就是dfs

 int maximalSquare(vector<vector<char>>& matrix) {
        if (matrix.empty() || matrix[0].empty()) return 0;
        int m = matrix.size(), n = matrix[0].size(), res = 0;
        vector<vector<int>> dp(m, vector<int>(n, 0));
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if (i == 0 || j == 0) dp[i][j] = matrix[i][j] - '0';
                else if (matrix[i][j] == '1') {
                    dp[i][j] = min(dp[i - 1][j - 1], min(dp[i][j - 1], dp[i - 1][j])) + 1;
                }
                res = max(res, dp[i][j]);
            }
        }
        return res * res;
    }

俄罗斯套娃

输入: envelopes = [[5,4],[6,4],[6,7],[2,3]]
输出: 3
解释: 最多信封的个数为 3, 组合为: [2,3] => [5,4] => [6,7]。
思路:先对vector<pair>排序,然后动态规划

    int maxEnvelopes(vector<pair<int, int>>& envelopes) {
        vector<int> dp(envelopes.size(), 1);
        sort(envelopes.begin(), envelopes.end());
        int res = 0;
        for (int i = 0; i < envelopes.size(); ++i){
            for (int j = 0; j < i; ++j){
                if (envelopes[i].first > envelopes[j].first && envelopes[i].second > envelopes[j].second)
                    dp[i] = max(dp[i], dp[j] + 1);
            }
            res = max(res, dp[i]);
        }
        return res;
    }

岛屿的最大面积

示例 1:
[[0,0,1,0,0,0,0,1,0,0,0,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,1,1,0,1,0,0,0,0,0,0,0,0],
[0,1,0,0,1,1,0,0,1,0,1,0,0],
[0,1,0,0,1,1,0,0,1,1,1,0,0],
[0,0,0,0,0,0,0,0,0,0,1,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,0,0,0,0,0,0,1,1,0,0,0,0]]
对于上面这个给定矩阵应返回 6。注意答案不应该是11,因为岛屿只能包含水平或垂直的四个方向的‘1’。
示例 2:
[[0,0,0,0,0,0,0,0]]
对于上面这个给定的矩阵, 返回 0。
解题思路:
此题与下面岛屿数量的思路类似,遍历二维数组,当遇到一个岛屿时进入岛屿将这个位置的置为0然后统计他周围陆地的1的个数,依次递归。

public int maxAreaOfIsland(int[][] grid) {
        int max = 0;
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[i].length; j++) {
                if (grid[i][j] == 1) {
                    int num = depthSearch(grid,i,j);
                    max = Math.max(num, max);
                }
            }
        }
        return max;
    }

    public int depthSearch(int[][] grid, int i, int j) {
        if (i >= 0 && i < grid.length && j >= 0 && j < grid[i].length && grid[i][j] == 1) {
            grid[i][j] = 0;
            int num = 1 + depthSearch(grid, i + 1, j) + depthSearch(grid, i - 1, j) + depthSearch(grid, i, j + 1) + depthSearch(grid, i, j - 1);
             return num;
        }
        return 0;
    }

岛屿数量

输入:
11000
11000
00100
00011
输出: 3
思路:这道求岛屿数量的题,本质是求矩阵中连续区域的个数,很容易想到需要用深度优先搜索 DFS 来解,我们需要建立一个 visited 数组用来记录某个位置是否被访问过,对于一个为 ‘1’ 且未被访问过的位置,我们递归进入其上下左右位置上为 ‘1’ 的数,将其 visited 对应值赋为 true,继续进入其所有相连的邻位置,这样可以将这个连通区域所有的数找出来,并将其对应的 visited 中的值赋 true,找完次区域后,我们将结果 res 自增 1,然后我们在继续找下一个为 ‘1’ 且未被访问过的位置,以此类推直至遍历完整个原数组即可得到最终结果。

public int numIslands(char[][] grid) {
        if (grid.length == 0 || grid[0].length == 0) return 0;
        int n = grid.length, m = grid[0].length;
        boolean[][] visited = new boolean[n][m];
        int count = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (grid[i][j] == '1' && !visited[i][j]) {
                    numIslandsDFS(grid, visited, i, j);
                    count++;
                }
            }
        }
        return count++;
    }
    void numIslandsDFS(char[][] grid, boolean[][] visited, int x, int y) {
        if (x < 0 || x >= grid.length) return;
        if (y < 0 || y >= grid[0].length) return;
        if (grid[x][y] != '1' || visited[x][y]) return;
        
        visited[x][y] = true;
        
        numIslandsDFS(grid, visited, x - 1, y);
        numIslandsDFS(grid, visited, x + 1, y);
        numIslandsDFS(grid, visited, x, y - 1);
        numIslandsDFS(grid, visited, x, y + 1);
    }

岛屿的周长

输入:
[[0,1,0,0],
[1,1,1,0],
[0,1,0,0],
[1,1,0,0]]
输出: 16
解释: 它的周长是下面图片中的 16 个黄色的边:

image

重点关注前面遍历过得方格,如果之前有相邻方格,就-2;

int islandPerimeter(vector<vector<int>>& grid) {
      if (grid.size() == 0) {
           return 0;
       }
       int rsp = 0;
       for (int i = 0; i < grid.size(); i++) {
           for (int j = 0; j < grid[i].size(); j++) {
               if (grid[i][j] == 1) {
                   rsp += 4;
                   if (i > 0 && grid[i - 1][j] == 1) {
                       rsp -= 2;
                   }
                   if (j > 0 && grid[i][j - 1] == 1) {
                       rsp -= 2;
                   }
               }
           }
       } 
       return rsp;
   }

图像渲染,洪水泛滥

输入:
image = [[1,1,1],[1,1,0],[1,0,1]]
sr = 1, sc = 1, newColor = 2
输出: [[2,2,2],[2,2,0],[2,0,1]]
解析:
在图像的正中间,(坐标(sr,sc)=(1,1)),
在路径上所有符合条件的像素点的颜色都被更改成2。
注意,右下角的像素没有更改为2,
因为它不是在上下左右四个方向上与初始点相连的像素点。

public int[][] floodFill(int[][] image, int sr, int sc, int newColor) {
     int initColor=image[sr][sc];    
        if(newColor == initColor)return image;//原来的颜色和渲染后的颜色竟然一样?!
     dfs(image ,sr,sc,newColor,initColor);
     return image;
 }
 private void dfs(int[][] image, int sr, int sc, int newColor,int initColor){
     image[sr][sc]=newColor;
     if(sr>0&& image[sr - 1][sc] == initColor)
         dfs(image ,sr-1,sc,newColor,initColor);
       if(sr<image.length-1&& image[sr + 1][sc] == initColor)
         dfs(image ,sr+1,sc,newColor,initColor);
       if(sc>0&& image[sr][sc-1] == initColor)
         dfs(image ,sr,sc-1,newColor,initColor);
       if(sc<image[0].length-1&& image[sr][sc+1] == initColor)
         dfs(image ,sr,sc+1,newColor,initColor);
 }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容