算法分析与设计课程作业第十四周#1#2#3

来源:互联网 发布:淘宝电工工具袋 编辑:程序博客网 时间:2024/05/01 04:17

算法分析与设计课程作业第十四周#1#2#3

这周选了几道有关矩阵的题目,其中有medium题也有hard题,有的与线性规划有关,有的与搜索有关,以下上题。

200. Number of Islands

Given a 2d grid map of ‘1’s (land) and ‘0’s (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.
Example 1:
11110
11010
11000
00000
Answer: 1
Example 2:
11000
11000
00100
00011
Answer: 3

思路

其实就相当于求一个无向图的连通分量的数目,可以每遇到没找到过的‘1’就深度优先搜索,将一个个毗邻的‘1’搜索完毕(用一个found数组表示),就确定找到一个连通分量了,如此就可确定矩阵中岛的数目。

代码

class Solution {public:    void dfs(vector<vector<char>>& grid,int m,int n,int i,int j,vector<vector<bool>>& found){        found[i][j]=true;        if(grid[i][j] == '0'){            return;        }        if(i>0 && found[i-1][j] == false) dfs(grid, m, n, i-1, j, found);        if(i<m-1 && found[i+1][j] == false) dfs(grid, m, n, i+1, j, found);        if(j>0 && found[i][j-1] == false) dfs(grid, m, n, i, j-1, found);        if(j<n-1 && found[i][j+1] == false) dfs(grid, m, n, i, j+1, found);    }    int numIslands(vector<vector<char>>& grid) {        int m = grid.size();        if(m == 0) return 0;        int n = grid[0].size();        if(n == 0) return 0;        int num = 0;        vector<vector<bool>> found(m, vector<bool>(n, false));        for(int i = 0; i < m; i++){            for(int j = 0; j < n; j++){                if(found[i][j] == false){                    dfs(grid, m, n, i, j, found);                    if(grid[i][j] == '1') num++;                }            }        }        return num;    }};

240. Search a 2D Matrix II

Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:

Integers in each row are sorted in ascending from left to right.
Integers in each column are sorted in ascending from top to bottom.

For example,
Consider the following matrix:
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
Given target = 5, return true.
Given target = 20, return false.

思路

本来想尝试用类似二分法的方法,但矩阵与序列不同,似乎无法有效分为两个子矩阵。但可以观察到,矩阵所有从任一元素开始,先向右,再向下得到的序列都是递增的,如果巧妙设计,将target与这序列的某一元素比较,可以舍弃到这个序列的一大部分。如果从矩阵度右上角的元素开始,进行上述操作,每次都可得到舍去某一行或列一部分的子矩阵,在O(m+n)时间内即可完成搜索。

代码

class Solution {public:    bool searchMatrix(vector<vector<int>>& matrix, int target) {        int m = matrix.size();        if(m == 0) return false;        int n = matrix[0].size();        if(n == 0) return false;        int i = 0, j = n-1;        while(i<m&&j>=0){            if(matrix[i][j] == target){                return true;            }            if(matrix[i][j] > target){                j--;            }            else{                i++;            }        }        return false;    }};

329. Longest Increasing Path in a Matrix

Given an integer matrix, find the length of the longest increasing path.
From each cell, you can either move to four directions: left, right, up or down. You may NOT move diagonally or move outside of the boundary (i.e. wrap-around is not allowed).
Example 1:
nums = [
[9,9,4],
[6,6,8],
[2,1,1]
]

Return 4
The longest increasing path is [1, 2, 6, 9].
Example 2:
nums = [
[3,4,5],
[3,2,6],
[2,2,1]
]

Return 4
The longest increasing path is [3, 4, 5, 6]. Moving diagonally is not allowed.

思路

这道题刚开始做时我害怕直接深度优先搜索会进入死循环,但仔细看发现他找的是递增子序列,所以一个位置如果能转移到另一个位置(递增),那么从转移到的那个位置是不会转移回去的。那么可以用一个dp数组(可减少重复计算),记录从某一点开始能走的最长递增序列长度,那么其相邻的点也可由这个长度+1并比较得到自己开始的最长递增子序列长度。最后最大的dp值即为答案。

代码

class Solution {public:    int dfs(vector<vector<int>>& matrix, int i, int j, vector<vector<int>>& dp, int m, int n){        if(dp[i][j] != 1) return dp[i][j];        int large = 1;        if(i-1>=0&&matrix[i-1][j]>matrix[i][j]){            large = max(large,dfs(matrix, i-1, j, dp, m, n)+1);        }        if(j+1<n&&matrix[i][j+1]>matrix[i][j]){            large = max(large,dfs(matrix, i, j+1, dp, m, n)+1);        }        if(j-1>=0&&matrix[i][j-1]>matrix[i][j]){            large = max(large,dfs(matrix, i, j-1, dp, m, n)+1);        }        if(i+1<m&&matrix[i+1][j]>matrix[i][j]){            large = max(large,dfs(matrix, i+1, j, dp, m, n)+1);        }        dp[i][j] = large;//关键,这个赋值如果在下面的循环中写就不是动态规划了,而且会浪费多许多时间导致TLE        return large;    }    int longestIncreasingPath(vector<vector<int>>& matrix) {        int m = matrix.size();        if(m==0){            return 0;        }        int n = matrix[0].size();        if(n==0){            return 0;        }        int large = 0;        vector<vector<int>> dp(m, vector<int>(n, 1));        for(int i = 0; i < m; i++){            for(int j = 0; j < n; j++){                large = max(large, dfs(matrix, i, j, dp, m, n));            }        }        return large;    }};
原创粉丝点击