forked from azl397985856/leetcode
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* 2019-08-05题解 * 2019-08-05 leetcode-105题解 * 2019-08-05 readme.md更新 * 2019-08-05 readme.md更新 * 201-08-08 1123题解 * 2019-08-08 readme.md更新 * 2019-08-09 leetcode-64题解 * readme更新 * 2019-08-11题解和2019-08-09题解修正 * 2019-08-09改正
- Loading branch information
1 parent
de5b224
commit c27bb57
Showing
3 changed files
with
178 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# 毎日一题 - 64.最小路径和 | ||
|
||
## 信息卡片 | ||
|
||
* 时间:2019-08-09 | ||
* 题目链接:https://leetcode-cn.com/problems/minimum-path-sum/ | ||
- tag:`动态规划` `Array` | ||
## 题目描述 | ||
给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。 | ||
**说明**:每次只能向下或者向右移动一步。 | ||
**示例:** | ||
``` | ||
输入: | ||
[ | ||
[1,3,1], | ||
[1,5,1], | ||
[4,2,1] | ||
] | ||
输出: 7 | ||
解释: 因为路径 1→3→1→1→1 的总和最小。 | ||
``` | ||
## 参考答案 | ||
动态规划求解,时间复杂度O(n*m) | ||
> | ||
我们新建一个额外的dp数组,与原矩阵大小相同。在这个矩阵中,dp(i,j)表示从坐标(i,j)到右下角的最小路径权值。我们初始化右下角的dp值为对应的原矩阵值,然后去填整个矩阵,对于每个元素考虑移动到右边或者下面,因此获得最小路径和我们有如下递推公式:`dp(i,j)=grid(i,j)+min(dp(i+1,j),dp(i,j+1))` | ||
```c++ | ||
class Solution { | ||
public: | ||
int minPathSum(vector<vector<int>>& grid) { | ||
//剪枝 | ||
int n = grid.size(); | ||
if(n==0) | ||
return 0; | ||
int m = grid[0].size(); | ||
if(m==0) | ||
return 0; | ||
//初始化第一列 | ||
for(int i=1;i<m;i++) | ||
{ | ||
grid[0][i] += grid[0][i-1]; | ||
} | ||
//初始化第一排 | ||
for(int i=1;i<n;i++) | ||
{ | ||
grid[i][0] += grid[i-1][0]; | ||
} | ||
|
||
for(int i=1;i<n;i++) | ||
{ | ||
for(int j=1;j<m;j++) | ||
{ | ||
//计算出到当前位置的最小值 | ||
grid[i][j]+=min(grid[i-1][j],grid[i][j-1]); | ||
} | ||
} | ||
return grid[n-1][m-1]; | ||
} | ||
}; | ||
``` | ||
## 其他优秀解答 | ||
> 暂缺 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
# 毎日一题 - 547.朋友圈 | ||
|
||
## 信息卡片 | ||
|
||
* 时间:2019-08-11 | ||
* 题目链接:https://leetcode-cn.com/problems/friend-circles | ||
- tag:`并查集` `BFS` | ||
## 题目描述 | ||
班上有 N 名学生。其中有些人是朋友,有些则不是。他们的友谊具有是传递性。如果已知 A 是 B 的朋友,B 是 C 的朋友,那么我们可以认为 A 也是 C 的朋友。所谓的朋友圈,是指所有朋友的集合。 | ||
|
||
给定一个 N * N 的矩阵 M,表示班级中学生之间的朋友关系。如果M[i][j] = 1,表示已知第 i 个和 j 个学生互为朋友关系,否则为不知道。你必须输出所有学生中的已知的朋友圈总数。 | ||
|
||
**示例 1:** | ||
``` | ||
输入: | ||
[[1,1,0], | ||
[1,1,0], | ||
[0,0,1]] | ||
输出: 2 | ||
说明:已知学生0和学生1互为朋友,他们在一个朋友圈。第2个学生自己在一个朋友圈。所以返回2。 | ||
``` | ||
**示例 2:** | ||
``` | ||
输入: | ||
[[1,1,0], | ||
[1,1,1], | ||
[0,1,1]] | ||
输出: 1 | ||
说明:已知学生0和学生1互为朋友,学生1和学生2互为朋友,所以学生0和学生2也是朋友,所以他们三个在一个朋友圈,返回1。 | ||
``` | ||
注意: | ||
1. N 在[1,200]的范围内。 | ||
2. 对于所有学生,有M[i][i] = 1。 | ||
3. 如果有M[i][j] = 1,则有M[j][i] = 1。 | ||
|
||
## 参考答案 | ||
### 解法一:并查集 | ||
遍历邻接矩阵M,如果M[i][j]==1即二者是朋友,那么合并i,j集合,遍历完整个矩阵M后则剩余的集合数量就是有多少个朋友圈。其中路径压缩能大大降低算法的时间复杂度:合并时让当前节点归属指向朋友圈的根节点,下次查询时就能快许多。 | ||
```c++ | ||
class Solution { | ||
public: | ||
int findCircleNum(vector<vector<int>>& M) { | ||
if (M.empty()) | ||
return 0; | ||
vector<int> pre(M.size()); | ||
for(int i=0; i<M.size(); i++) | ||
pre[i] = i;//先各自为组,组名也为自己的序号 | ||
int group = M.size();//一开始有多少人就有多少个朋友圈,当每出现一对朋友时就减1,最后就是总的朋友圈数量了。 | ||
for(int i=0; i<M.size(); i++) | ||
{ | ||
for(int j=0; j<M.size(); j++) | ||
{ | ||
if (i != j && M[i][j] == 1) | ||
{ | ||
int x1 = find(i, pre);//x1为i所属的组 | ||
int x2 = find(j, pre);//x2为j所属的组 | ||
if (x1 != x2) | ||
{ | ||
//如果不属于同个朋友圈的话就把i归为j的组 | ||
pre[x1] = x2; | ||
group--; | ||
} | ||
} | ||
} | ||
} | ||
return group; | ||
} | ||
private: | ||
int find(int x, vector<int>& pre) | ||
{ | ||
//“pre[x] = ”这句为路径压缩,直接指向组的根节点,下次查询时就快很多了。 | ||
return pre[x]==x ? x : pre[x] = find(pre[x], pre); | ||
} | ||
}; | ||
``` | ||
### 解法二:BFS | ||
时间复杂度O(n²) | ||
> | ||
可以将题目转换为是在一个图中求连通子图的问题,给出的N*N的矩阵就是邻接矩阵,建立N个节点的visited数组,从not visited的节点开始深度优先遍历,遍历就是在邻接矩阵中去遍历,如果在第i个节点的邻接矩阵那一行中的第j个位置处M[i][j]==1 and not visited[j],就应该dfs到这个第j个节点的位置, | ||
```java | ||
public class Solution { | ||
public void dfs(int[][] M, int[] visited, int i) { | ||
for (int j = 0; j < M.length; j++) { | ||
if (M[i][j] == 1 && visited[j] == 0) { | ||
visited[j] = 1; | ||
dfs(M, visited, j); | ||
} | ||
} | ||
} | ||
public int findCircleNum(int[][] M) { | ||
int[] visited = new int[M.length]; | ||
int count = 0; | ||
for (int i = 0; i < M.length; i++) { | ||
if (visited[i] == 0) { | ||
dfs(M, visited, i); | ||
count++; | ||
} | ||
} | ||
return count; | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters