• 【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
  • 相关阅读:
    tab点击切换
    下拉收起
    倒计时
    边框三角形
    jQuery Easing 使用方法及其图解
    网址收藏
    Java遍历Map对象的四种方式
    idea初使用之自动编译
    Mysql 存储引擎中InnoDB与Myisam的主要区别
    spring-boot-devtools在Idea中热部署方法
  • 原文地址:https://www.cnblogs.com/seyjs/p/12204923.html
Copyright © 2020-2023  润新知