[LeetCode] Freedom Trail 自由之路
In the video game Fallout 4, the quest "Road to Freedom" requires players to reach a metal dial called the "Freedom Trail Ring", and use the dial to spell a specific keyword in order to open the door.
Given a string ring, which represents the code engraved on the outer ring and another string key, which represents the keyword needs to be spelled. You need to find the minimum number of steps in order to spell all the characters in the keyword.
Initially, the first character of the ring is aligned at 12:00 direction. You need to spell all the characters in the string key one by one by rotating the ring clockwise or anticlockwise to make each character of the string key aligned at 12:00 direction and then by pressing the center button.
At the stage of rotating the ring to spell the key character key[i]:
- You can rotate the ring clockwise or anticlockwise one place, which counts as 1 step. The final purpose of the rotation is to align one of the string ring's characters at the 12:00 direction, where this character must equal to the character key[i].
- If the character key[i] has been aligned at the 12:00 direction, you need to press the center button to spell, which also counts as 1 step. After the pressing, you could begin to spell the next character in the key (next stage), otherwise, you've finished all the spelling.
Example:
Input: ring = "godding", key = "gd"
Output: 4
Explanation:
For the first key character 'g', since it is already in place, we just need 1 step to spell this character.
For the second key character 'd', we need to rotate the ring "godding" anticlockwise by two steps to make it become "ddinggo".
Also, we need 1 more step for spelling.
So the final output is 4.
Note:
- Length of both ring and key will be in range 1 to 100.
- There are only lowercase letters in both strings and might be some duplcate characters in both strings.
- It's guaranteed that string key could always be spelled by rotating the string ring.
这道题是关于辐射4这款游戏出的,博主虽然没有玩过这款游戏,但是知道确实有些游戏中需要破解一些谜题才能继续通关,像博主很早以前玩过的恐龙危机啊,生化危机啊啥的,都有一些机关需要破解,博主大部分都要靠看攻略来通关哈哈。这道题讲的是一种叫做自由之路的机关,我们需要将密码字符串都转出来,让我们求最短的转动步数。博主最先尝试的用贪婪算法来做,就是每一步都选最短的转法,但是OJ中总有些test case会引诱贪婪算法得出错误的结果,因为全局最优解不一定都是局部最优解,而贪婪算法一直都是在累加局部最优解,这也是为啥DP解法这么叼的原因。贪婪算法好想好实现,但是不一定能得到正确的结果。DP解法难想不好写,但往往才是正确的解法,这也算一个trade off吧。这道题可以用DP来解,难点还是写递推公式,博主在充分研究网上大神们的帖子后尝试着自己理理思路,如果有不正确或者不足的地方,也请各位不吝赐教。此题需要使用一个二维数组dp,其中dp[i][j]表示转动从i位置开始的key串所需要的最少步数(这里不包括spell的步数,因为spell可以在最后统一加上),此时表盘的12点位置是ring中的第j个字符。不得不佩服这样的设计的确很巧妙,我们可以从key的末尾往前推,这样dp[0][0]就是我们所需要的结果,因为此时是从key的开头开始转动,而且表盘此时的12点位置也是ring的第一个字符。现在我们来看如何找出递推公式,对于dp[i][j],我们知道此时要将key[i]转动到12点的位置,而此时表盘的12点位置是ring[j],我们有两种旋转的方式,顺时针和逆时针,我们的目标肯定是要求最小的转动步数,而顺时针和逆时针的转动次数之和刚好为ring的长度n,这样我们求出来一个方向的次数,就可以迅速得到反方向的转动次数。为了将此时表盘上12点位置上的ring[j]转动到key[i],我们要将表盘转动一整圈,当转到key[i]的位置时,我们计算出转动步数diff,然后计算出反向转动步数,并取二者较小值为整个转动步数step,此时我们更新dp[i][j],更新对比值为step + dp[i+1][k],这个也不难理解,因为key的前一个字符key[i+1]的转动情况suppose已经计算好了,那么dp[i+1][k]就是当时表盘12点位置上ring[k]的情况的最短步数,step就是从ring[k]转到ring[j]的步数,也就是key[i]转到ring[j]的步数,用语言来描述就是,从key的i位置开始转动并且此时表盘12点位置为ring[j]的最小步数(dp[i][j])就等价于将ring[k]转动到12点位置的步数(step)加上从key的i+1位置开始转动并且ring[k]已经在表盘12点位置上的最小步数(dp[i+1][k])之和。突然发现这不就是之前那道Reverse Pairs中解法一中归纳的顺序重现关系的思路吗,都做了总结,可换个马甲就又不认识了,泪目中。。。
解法一:
class Solution {
public:
int findRotateSteps(string ring, string key) {
int n = ring.size(), m = key.size();
vector<vector<int>> dp(m + , vector<int>(n));
for (int i = m - ; i >= ; --i) {
for (int j = ; j < n; ++j) {
dp[i][j] = INT_MAX;
for (int k = ; k < n; ++k) {
if (ring[k] == key[i]) {
int diff = abs(j - k);
int step = min(diff, n - diff);
dp[i][j] = min(dp[i][j], step + dp[i + ][k]);
}
}
}
}
return dp[][] + m;
}
};
下面这种解法是用DFS来解的,我们需要做优化,也就是用memo数组来保存已经计算过的结果,否则大量的重复运算是无法通过OJ的。其实这里的memo数组也起到了跟上面解法中的dp数组相类似的作用,还有就是要注意数组v的作用,记录了每个字母在ring中的出现位置,由于ring中可能有重复字符,而且麻烦的情况是当前位置向两个方向分别转动相同的步数会分别到达两个相同的字符,这也是贪婪算法会失效的一个重要原因,而且也是上面的解法在找到ring[k] == key[i]并处理完之后不break的原因,因为后面还有可能找到。上面的迭代解法中使用到的变量i和j可以直接访问到,而在递归的写法中必须要把位置变量x和y当作参数导入进去,这样才能更新正确的地方,参见代码如下:
解法二:
class Solution {
public:
int findRotateSteps(string ring, string key) {
int n = ring.size(), m = key.size();
vector<vector<int>> v();
vector<vector<int>> memo(n, vector<int>(m));
for (int i = ; i < n; ++i) v[ring[i] - 'a'].push_back(i);
return helper(ring, key, , , v, memo);
}
int helper(string ring, string key, int x, int y, vector<vector<int>>&v, vector<vector<int>>& memo) {
if (y == key.size()) return ;
if (memo[x][y]) return memo[x][y];
int res = INT_MAX, n = ring.size();
for (int k : v[key[y] - 'a']) {
int diff = abs(x - k);
int step = min(diff, n - diff);
res = min(res, step + helper(ring, key, k, y + , v, memo));
}
return memo[x][y] = res + ;
}
};
参考资料:
https://discuss.leetcode.com/topic/81684/concise-java-dp-solution
https://discuss.leetcode.com/topic/82720/evolve-from-brute-force-to-dp
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] Freedom Trail 自由之路的更多相关文章
- 514 Freedom Trail 自由之路
详见:https://leetcode.com/problems/freedom-trail/description/ C++: class Solution { public: int findRo ...
- [Swift]LeetCode514. 自由之路 | Freedom Trail
In the video game Fallout 4, the quest "Road to Freedom" requires players to reach a metal ...
- Leetcode 514.自由之路
自由之路 视频游戏"辐射4"中,任务"通向自由"要求玩家到达名为"Freedom Trail Ring"的金属表盘,并使用表盘拼写特定关键词 ...
- Java实现 LeetCode 514 自由之路
514. 自由之路 视频游戏"辐射4"中,任务"通向自由"要求玩家到达名为"Freedom Trail Ring"的金属表盘,并使用表盘拼写 ...
- 514. Freedom Trail
In the video game Fallout 4, the quest "Road to Freedom" requires players to reach a metal ...
- LeetCode 514----Freedom Trail
问题描述 In the video game Fallout 4, the quest "Road to Freedom" requires players to reach a ...
- 【美】范·K·萨普曼 - 通向财务自由之路(2013年11月26日)
<通向财务自由之路> 作 者:[美]范·K·萨普曼 译 者:董梅 系 列: 出 版:机械工业出版社 字 数:约40千字 阅读完成:2013年11月26日
- [LeetCode] Judge Route Circle 判断路线绕圈
Initially, there is a Robot at position (0, 0). Given a sequence of its moves, judge if this robot m ...
- 动态规划——Freedom Trail
题目:https://leetcode.com/problems/freedom-trail/ 额...不解释大意了,题目我也不想写过程了有点繁琐,直接给出代码: public int findRot ...
随机推荐
- 如何从零开始学习区块链技术——推荐从以太坊开发DApp开始
很多人迷惑于区块链和以太坊,不知如何学习,本文简单说了一下学习的一些方法和资源. 一. 以太坊和区块链的关系 从区块链历史上来说,先诞生了比特币,当时并没有区块链这个技术和名词,然后业界从比特币中提取 ...
- WCF跨域解决方法及一些零碎的东西。
之前发过一篇随笔,说的WCF配置文件配置问题.里面也配了跨域支持,但是jsoncollback只支持Get请求,Post请求是解决不了,所以这里把真正的WCF跨域问题贴出来. 话不多说,直接帖配置文件 ...
- C语言嵌套循环
题目一:7-3 编程打印空心字符菱形 1.提交列表 2.设计思路: 1.定义整型变量循环控制变量i,j,k,x,y,z,e及菱形的高度height: 2.定义字符型变量letter: 3.输入字符型变 ...
- Beta版本敏捷冲刺每日报告——Day2
1.情况简述 Beta阶段第二次Scrum Meeting 敏捷开发起止时间 2017.11.3 08:00 -- 2017.11.3 22:00 讨论时间地点 2017.11.3晚9:00,软工所实 ...
- 简单的C语言编译器--语法分析器
语法分析算是最难的一部分了.总而言之,语法分析就是先设计一系列语法,然后再用设计好的语法去归约词法分析中的结果.最后将归约过程打印出来,或者生成抽象语法树. 1. 设计文法 以下是我的文法(引入的 ...
- TSP-旅行商问题
#include <iostream> #include <vector> #include <algorithm> using namespace std; in ...
- mysql基础篇 - 数据库及表的修改和删除
基础篇 - 数据库及表的修改和删除 修改和删除 一.实验简介 本节实验中,我们将学习并实践如何对数据库的内容做修改,删除,重命名等操作. 二.实验准备 在正式开始本实验内容之前,需要先 ...
- httpClient 中的post或者get请求
httpClient相对于java自带的请求功能更加强大,下面就以例子的形式给出: //HttpClient Get请求 private static void register() { try { ...
- Golang学习--开篇
最近开始接收一个新项目,是使用Golang写的,需要重新捡起Golang来,于是就有了这个系列博客. Golang的环境配置,我就不说了,让我们直接开始. Golang官网:https://golan ...
- Mysql必须知道的知识
最近在准备面试,所以也整理了一些Mysql数据库常用的知识,供大家参考. 1.MySQL的复制原理以及流程 (1).复制基本原理流程 1. 主:binlog线程--记录下所有改变了数据库数据的语句,放 ...