昨天题太简单了。就一个前缀和 懒得写记录了
传送门:https://leetcode-cn.com/problems/path-with-minimum-effort/
从左上角到右下角 求最小相邻差的路径,即保证最小的路径最大差 这个题主要注意是求差
两种做法:
- DFS/BFS搜路径 同时加二分 求能够到达的临界值 即大于等于ans时能够到达 小于ans时不能够到达的值 找这个值用二分去找就好了 差最大为1e6 详细思路见代码
#include <algorithm>
#include <queue>
#include <string.h>
#include <vector>
using namespace std;
const int dir[4][2] = {-1, 0, 1, 0, 0, -1, 0, 1};
class Solution
{
public:
int minimumEffortPath(vector<vector<int>> &heights)
{
int m = heights.size(); //行
int n = heights[0].size(); //列
int l = 0, r = 1e6, ans = 0;
while (l <= r)
{
int mid = l + r >> 1;
queue<pair<int, int>> q;
q.push(make_pair(0, 0)); //起点入栈
int vis[m][n];
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
vis[i][j] = 0;
}
vis[0][0] = 1; //起点访问过
while (!q.empty())
{
pair<int, int> t = q.front();
q.pop();
for (int i = 0; i < 4; i++)
{
int nx = t.first + dir[i][0];
int ny = t.second + dir[i][1];
if (nx >= 0 && nx < m && ny >= 0 && ny < n && !vis[nx][ny] && abs(heights[t.first][t.second] - heights[nx][ny]) <= mid)
{
q.push(make_pair(nx, ny));
vis[nx][ny] = 1; //访问过该结点
}
}
}
if (vis[m - 1][n - 1])
{
ans = mid;
r = mid - 1;
}
else
{
l = mid + 1;
}
}
return ans;
}
};
2. 并查集 个人认为这个做法十分的巧妙 首先将所有边找出来 之后从小到大排序 之后不断地向并查集中加边 (注意:如果权值(两个节点之间的差)为1的边 插入1条和插入n条 对答案的贡献是一样的 所以很有可能 最后成功连通左上角和右下角的点的图有许多多余的边)直到加入到左上角和右下角连通 此时最后加入的边的值即为答案
const int maxn = 1e6 + 5;
// 并查集模板
class UnionFind
{
public:
vector<int> parent;
vector<int> size;
int n;
// 当前连通分量数目
int setCount;
public:
UnionFind(int _n) : n(_n), setCount(_n), parent(_n), size(_n, 1)
{
iota(parent.begin(), parent.end(), 0);
}
int findset(int x)
{
return parent[x] == x ? x : parent[x] = findset(parent[x]);
}
bool unite(int x, int y)
{
x = findset(x);
y = findset(y);
if (x == y)
{
return false;
}
if (size[x] < size[y])
{
swap(x, y);
}
parent[y] = x;
size[x] += size[y];
--setCount;
return true;
}
bool connected(int x, int y)
{
x = findset(x);
y = findset(y);
return x == y;
}
};
struct edg
{
int st, ed;
int n;
};
int cmp(edg a,edg b){
return a.n < b.n;
}
class Solution
{
public:
int minimumEffortPath(vector<vector<int>> &heights)
{
int m = heights.size(); //行
int n = heights[0].size(); //列
vector<edg> mp; //mp存所有边
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
//加入所有边
int id = i * n + j; //计算每个点的哈希
if (i > 0)
{
edg t = {id - n, id, abs(heights[i][j] - heights[i - 1][j])};
mp.push_back(t);
}
if (j > 0)
{
edg t = {id - 1, id, abs(heights[i][j] - heights[i][j - 1])};
mp.push_back(t);
}
}
}
sort(mp.begin(), mp.end(), cmp);//从小到大排序 按照差值
UnionFind uf(m * n);
int ans = 0;
for(auto edge:mp){
uf.unite(edge.st, edge.ed);
if(uf.connected(0,m*n-1)){
ans = edge.n;
break;
}
}
return ans;
}
};







Comments | NOTHING