zoukankan      html  css  js  c++  java
  • 【leetcode】1320. Minimum Distance to Type a Word Using Two Fingers

    题目如下:

    You have a keyboard layout as shown above in the XY plane, where each English uppercase letter is located at some coordinate, for example, the letter A is located at coordinate (0,0), the letter B is located at coordinate (0,1), the letter P is located at coordinate (2,3) and the letter Z is located at coordinate (4,1).

    Given the string word, return the minimum total distance to type such string using only two fingers. The distance between coordinates (x1,y1) and (x2,y2) is |x1 - x2| + |y1 - y2|. 

    Note that the initial positions of your two fingers are considered free so don't count towards your total distance, also your two fingers do not have to start at the first letter or the first two letters.

    Example 1:

    Input: word = "CAKE"
    Output: 3
    Explanation: 
    Using two fingers, one optimal way to type "CAKE" is: 
    Finger 1 on letter 'C' -> cost = 0 
    Finger 1 on letter 'A' -> cost = Distance from letter 'C' to letter 'A' = 2 
    Finger 2 on letter 'K' -> cost = 0 
    Finger 2 on letter 'E' -> cost = Distance from letter 'K' to letter 'E' = 1 
    Total distance = 3
    

    Example 2:

    Input: word = "HAPPY"
    Output: 6
    Explanation: 
    Using two fingers, one optimal way to type "HAPPY" is:
    Finger 1 on letter 'H' -> cost = 0
    Finger 1 on letter 'A' -> cost = Distance from letter 'H' to letter 'A' = 2
    Finger 2 on letter 'P' -> cost = 0
    Finger 2 on letter 'P' -> cost = Distance from letter 'P' to letter 'P' = 0
    Finger 1 on letter 'Y' -> cost = Distance from letter 'A' to letter 'Y' = 4
    Total distance = 6
    

    Example 3:

    Input: word = "NEW"
    Output: 3
    

    Example 4:

    Input: word = "YEAR"
    Output: 7

    Constraints:

    • 2 <= word.length <= 300
    • Each word[i] is an English uppercase letter.

    解题思路:首先把A-Z分别用0~25下标来代替,记dp[i][j][k] 为输入完第i个字符后左手在第j个位置,右手在第k个位置的时候移动的次数最小。这里只需要和dp[i-1]建立状态转移方程,可以分为以下四种情况:

    1. word[i]和word[i-1]都是左手输入的,那么左手一定是从word[i-1]的索引位置移动到word[i]的索引位置,而右手可以处在任意索引位置j上面, 有 dp[i][inx][j] = min(dp[i][inx][j], dp[i-1][pervious_inx][j] + calcDis(pervious_inx,inx)) ; 其中inx为第word[i]个字符的索引,pervious_inx是word[i-1]的索引,calcDis 计算的是从 pervious_inx到 inx需要移动的距离。

    2.word[i]是左手输入并且word[i-1]是右手输入,那么右手还处于word[i-1]的索引位置,而左手可能从任意的索引位置j移动到 word[i]索引位置,有 dp[i][inx][pervious_inx] = min(dp[i][inx][pervious_inx], dp[i-1][j][pervious_inx] + calcDis(j, inx)) 。

    3.word[i]是右手输入并且word[i-1]是左手输入,有dp[i][pervious_inx][inx] = min(dp[i][pervious_inx][inx], dp[i-1][pervious_inx][j] + calcDis(j, inx)) 。

    4.word[i]和word[i-1]都是右手输入的,有 dp[i][j][inx] = min(dp[i][j][inx], dp[i-1][j][pervious_inx] + calcDis(pervious_inx,inx)) 

    代码如下:

    class Solution(object):
        def minimumDistance(self, word):
            """
            :type word: str
            :rtype: int
            """
            def getInx(char):
                return ord(char) - ord('A')
    
            def calcDis(inx1,inx2):
                if inx1 / 6 == inx2 / 6:
                    return abs(inx2 - inx1)
                dis = abs(inx1 / 6 - inx2 / 6)
                min_inx = min(inx1,inx2)
                max_inx = max(inx1,inx2)
                min_inx += dis * 6
                return dis + abs(max_inx - min_inx)
    
    
            dp = [[[float('inf')] * 26 for _ in range(26)] for _ in word]
    
            for k in range(26):
                # the first letter input by left hand
                dp[0][getInx(word[0])][k] = 0
                # the first letter input by right hand
                #print k,getInx(word[0])
                dp[0][k][getInx(word[0])] = 0
    
            res = float('inf')
            for i in range(1,len(word)):
                for j in range(26):
                    inx = getInx(word[i])
                    pervious_inx = getInx(word[i-1])
    
                    # input via left hand,pervious is left too
                    dp[i][inx][j] = min(dp[i][inx][j], dp[i-1][pervious_inx][j] + calcDis(pervious_inx,inx))
    
                    # input via left hand,pervious is right
                    dp[i][inx][pervious_inx] = min(dp[i][inx][pervious_inx], dp[i-1][j][pervious_inx] + calcDis(j, inx))
    
                    # input via right hand,pervious is left
                    dp[i][pervious_inx][inx] = min(dp[i][pervious_inx][inx], dp[i-1][pervious_inx][j] + calcDis(j, inx))
    
                    # input via right hand,pervious is right too
                    dp[i][j][inx] = min(dp[i][j][inx], dp[i-1][j][pervious_inx] + calcDis(pervious_inx,inx))
    
            last_inx = getInx(word[-1])
            for i in range(26):
                res = min(res,dp[-1][last_inx][i])
                res = min(res,dp[-1][i][last_inx])
    
            #print dp
    
            return res
  • 相关阅读:
    保留最大的数
    彩色宝石项链
    [leetcode] 403. Frog Jump
    [leetcode] 402. Remove K Digits
    Linux 更改时区、时间
    Linux系统时间同步方法
    mysql 5.7.28 地理位置计算详解
    springboot微服务项目集成为单体
    地理空间数据Geometry在MySQL中使用(一)
    mysql中geometry类型的简单使用
  • 原文地址:https://www.cnblogs.com/seyjs/p/12204923.html
Copyright © 2011-2022 走看看