惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
Tor Project blog
K
Kaspersky official blog
S
Security Affairs
Hacker News: Ask HN
Hacker News: Ask HN
L
LINUX DO - 最新话题
S
Securelist
Google DeepMind News
Google DeepMind News
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
N
News and Events Feed by Topic
The Last Watchdog
The Last Watchdog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
小众软件
小众软件
Vercel News
Vercel News
博客园 - 叶小钗
量子位
Help Net Security
Help Net Security
C
Cybersecurity and Infrastructure Security Agency CISA
P
Privacy & Cybersecurity Law Blog
T
The Exploit Database - CXSecurity.com
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
美团技术团队
AI
AI
V
V2EX
T
Troy Hunt's Blog
aimingoo的专栏
aimingoo的专栏
Microsoft Azure Blog
Microsoft Azure Blog
A
About on SuperTechFans
D
DataBreaches.Net
H
Help Net Security
V2EX - 技术
V2EX - 技术
T
Tailwind CSS Blog
宝玉的分享
宝玉的分享
MongoDB | Blog
MongoDB | Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
N
News and Events Feed by Topic
阮一峰的网络日志
阮一峰的网络日志
T
Threatpost
J
Java Code Geeks
Recent Announcements
Recent Announcements
T
The Blog of Author Tim Ferriss
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Webroot Blog
Webroot Blog
Cyberwarzone
Cyberwarzone
Google DeepMind News
Google DeepMind News
I
InfoQ
P
Proofpoint News Feed
Spread Privacy
Spread Privacy
Security Latest
Security Latest

Moon's Blog

Java内存 | Moon's Blog Spring Data JPA | Moon's Blog Spring Boot的Java Config | Moon's Blog Java知识点 | Moon's Blog Spring Boot知识点 | Moon's Blog Java异常机制 | Moon's Blog Java的类加载器 | Moon's Blog JVM类加载机制 | Moon's Blog 单体架构与微服务架构 | Moon's Blog 424.替换后的最长重复字符 | Moon's Blog 888.公平的糖果棒交换 | Moon's Blog 839.相似字符串组 | Moon's Blog 778.水位上升的泳池中游泳 | Moon's Blog 724.寻找数组的中心索引 | Moon's Blog 使用Jackson库实现日期序列化 | Moon's Blog 使用Jackson库实现Java多态解析 | Moon's Blog Spring Boot+InfluxDB实现日志管理 | Moon's Blog Java多态+工厂模式实现服务调用 | Moon's Blog 为Spring Boot项目生成OpenAPI3.0文档 | Moon's Blog
1631.最小体力消耗路径 | Moon's Blog
Moon Lou · 2021-01-30 · via Moon's Blog

1631.最小体力消耗路径

题目

你准备参加一场远足活动。给你一个二维 rows x columns 的地图 heights ,其中 heights[row] [col] 表示格子 (row, col) 的高度。一开始你在最左上角的格子 (0, 0) ,且你希望去最右下角的格子 (rows-1, columns-1) (注意下标从 0 开始编号)。你每次可以往 上,下,左,右 四个方向之一移动,你想要找到耗费 体力 最小的一条路径。

一条路径耗费的 体力值 是路径上相邻格子之间 高度差绝对值 的 最大值 决定的。

请你返回从左上角走到右下角的最小 体力消耗值 。

示例 1:

image-20210130230403049

输入:heights = [[1,2,2],[3,8,2],[5,3,5]]
输出:2
解释:路径 [1,3,5,3,5] 连续格子的差值绝对值最大为 2 。
这条路径比路径 [1,2,2,2,5] 更优,因为另一条路径差值最大值为 3 。

示例 2:

image-20210130230419400

输入:heights = [[1,2,3],[3,8,4],[5,3,5]]
输出:1
解释:路径 [1,2,3,4,5] 的相邻格子差值绝对值最大为 1 ,比路径 [1,3,5,3,5] 更优。

示例 3:

image-20210130230434943

输入:heights = [[1,2,1,1,1],[1,2,1,2,1],[1,2,1,2,1],[1,2,1,2,1],[1,1,1,2,1]]
输出:0
解释:上图所示路径不需要消耗任何体力。

提示:

  • rows == heights.length
  • columns == heights[i].length
  • 1 <= rows, columns <= 100
  • 1 <= heights[i] [j]<= 1000000

思路

首先我想到的是深度优先搜索/广度优先搜索,找到最小体力消耗路径。

但是,使用深度/广度优先搜索只能找到符合某个特定条件的路径,没有办法在搜索完毕后同时找到最小路径。

因此可以考虑将复杂问题转化为简单问题,即将原问题转化为两个相对简单的问题

  • 是否存在一条从左上角到右下角的路径,其经过的所有边权(节点间高度差)的最大值不超过 x?
  • 这个x最小是几?

显然对问题1只需要对节点图进行一次深度/广度优先搜索即可解答,复杂度为O(mn)

然后对问题2,我们可以在x的所有候选集的范围中去进行二分搜索,找到这个最小的x,复杂度为O(logC),C是最大高度差999999。

总的复杂度是O(mnlogC)

本题的核心思想是,将一个复杂问题转化为两个相对简单问题的集合。通过分别解决这两个相对简单的问题,最终解决困难问题。

代码

下面代码可以对二分查找广度优先搜索的写法进行一个很好的复习。

class Solution {
private int[][] direction = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}};
public int minimumEffortPath(int[][] heights) {
int rows = heights.length;
int columns = heights[0].length;

int left = 0;
int right = 999999;
int result = 0;
while (left <= right) {
int mid = (left + right)/2;
int[][] seen = new int[rows][columns];
Queue<int[]> queue = new LinkedList<int[]>();

int exist = 0;
queue.offer(new int[]{0, 0});
while (!queue.isEmpty()) {
int[] point = queue.poll();
int x = point[0];
int y = point[1];
for (int[] dir : direction) {
int xnext = x + dir[0];
int ynext = y + dir[1];
if (xnext >= 0 && xnext < rows
&& ynext >= 0 && ynext < columns
&& seen[xnext][ynext] == 0
&& Math.abs(heights[xnext][ynext] - heights[x][y]) <= mid) {
if (xnext == (rows - 1) && ynext == (columns - 1)){
exist = 1;
break;
}
queue.offer(new int[]{xnext, ynext});
seen[xnext][ynext] = 1;
}
}
}
if (exist == 0) {
left = mid + 1;
} else {
result = mid;
right = mid - 1;
}
}
return result;
}
}

版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Moon's Blog