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
  • 相关阅读:
    Linux常用命令英文全称与中文解释
    输入一个URL之后发生了什么?
    四种基本的数据结构
    关于深拷贝
    TCP的三次握手和四次挥手
    利用正则表达式去掉字符串的前后空格
    用canvas画一个等腰三角形
    三种隐藏元素方法的区别
    消息中间件-activemq安全机制
    Netty学习(十)-Netty文件上传
  • 原文地址:https://www.cnblogs.com/seyjs/p/12204923.html
Copyright © 2011-2022 走看看