力扣刷题笔记:514. 自由之路

题目514. 自由之路
电子游戏“辐射4”中,任务“通向自由”要求玩家到达名为“Freedom Trail Ring”的金属表盘,并使用表盘拼写特定关键词才能开门。

给定一个字符串 ring,表示刻在外环上的编码;给定另一个字符串 key,表示需要拼写的关键词。您需要算出能够拼写关键词中所有字符的最少步数。

最初,ring 的第一个字符与12:00方向对齐。您需要顺时针或逆时针旋转 ring 以使 key 的一个字符在 12:00 方向对齐,然后按下中心按钮,以此逐个拼写完 key 中的所有字符。

旋转 ring 拼出 key 字符 key[i] 的阶段中:

您可以将 ring 顺时针或逆时针旋转一个位置,计为1步。旋转的最终目的是将字符串 ring 的一个字符与 12:00 方向对齐,并且这个字符必须等于字符 key[i] 。
如果字符 key[i] 已经对齐到12:00方向,您需要按下中心按钮进行拼写,这也将算作 1 步。按完之后,您可以开始拼写 key 的下一个字符(下一阶段), 直至完成所有拼写。
示例:

在这里插入图片描述

输入: ring = “godding”, key = “gd”
输出: 4
解释:
对于 key 的第一个字符 ‘g’,已经在正确的位置, 我们只需要1步来拼写这个字符。
对于 key 的第二个字符 ‘d’,我们需要逆时针旋转 ring “godding” 2步使它变成 “ddinggo”。
当然, 我们还需要1步进行拼写。
因此最终的输出是 4。
提示:

ring 和 key 的字符串长度取值范围均为 1 至 100;
两个字符串中都只有小写字符,并且均可能存在重复字符;
字符串 key 一定可以由字符串 ring 旋转拼出。

思路

  • 首先理解题目意思:ring中有一个可以按下的位置,我们要把key中每个字符在ring中中找到相对应的位置,并移到可以按下的位置,叫我们记录需要转动ring的次数。这个转盘就和以前的电话一样。
  • 这是一道动态规划的题目
  • 首先我们需要找到它的状态:dp[i][j]:代表从前往后 key[i] 中的字符和 ring[j] 的最小转动次数,条件:key[i] == ring[i]。
  • 接着,一个ring可能具有多个相同字符,我们先用 pos[26] 存储ring中每个字符的位置,用利于后面计算距离。
  • 再接着:我们需要用到前面一次的结果来计算这一次的结果所以写出递归方程
  • 解释:因为在ring中可能有重复单词,我们把重复单词对应的dp[i][j]都会计算,并且下一次也会要枚举上一个所有重复单词的位置,并找到对应这次最小的转弯次数
  • dp[i][j]= (范围:k∈pos[key[i−1]])min{dp[i−1][k]+min{abs(j−k),n−abs(j−k)}+1}
  • 时间复杂度:O(mnn); 空间复杂度O(26 + mn)

源代码

class Solution {
    
    
public:
    int findRotateSteps(string ring, string key) {
    
    
        int n = ring.size(), m = key.size();

        vector<int> pos[26];

        //初始话pos数组,保存每个字符对应的位置
        for(int i = 0; i < n; ++i){
    
    
            pos[ring[i] - 'a'].push_back(i);
        }

        vector<vector<int>> dp(m, vector<int>(n, INT_MAX));
        //初始化第一行dp,因为后面需要用到前面的
        //把匹配的位置之间进行比较
        for(int i: pos[key[0] - 'a']){
    
    
            dp[0][i] = min(i, n - i) + 1;
        }

        //进行动态规划
        for(int i = 1; i < m; ++i){
    
    
            for(auto &j: pos[key[i] - 'a']){
    
    
                for(auto &k: pos[key[i - 1] - 'a']){
    
    
                    dp[i][j] = min(dp[i][j], dp[i - 1][k] + min(abs(j - k), n - abs(j - k)) + 1);
                }
            }
        }
        return *min_element(dp[m - 1].begin(), dp[m - 1].end());
    }
};

猜你喜欢

转载自blog.csdn.net/qq_45914759/article/details/109631780