leetcode 1320. 二指輸入的的最小距離 - leetcode 周賽 171 5310 - python 動歸

賽題連接 英文賽題 題庫題目python

題目描述

img

二指輸入法定製鍵盤在 XY 平面上的佈局如上圖所示,其中每一個大寫英文字母都位於某個座標處,例如字母 A 位於座標 (0,0),字母 B 位於座標 (0,1),字母 P 位於座標 (2,3) 且字母 Z 位於座標 (4,1)數組

給你一個待輸入字符串 word,請你計算並返回在僅使用兩根手指的狀況下,鍵入該字符串須要的最小移動總距離。座標 (x1,y1)(x2,y2) 之間的距離是 |x1 - x2| + |y1 - y2|函數

注意,兩根手指的起始位置是零代價的,不計入移動總距離。你的兩根手指的起始位置也沒必要從首字母或者前兩個字母開始。佈局

示例 1:學習

輸入:word = "CAKE"
輸出:3
解釋:
使用兩根手指輸入 "CAKE" 的最佳方案之一是:
手指 1 在字母 'C' 上 -> 移動距離 = 0
手指 1 在字母 'A' 上 -> 移動距離 = 從字母 'C' 到字母 'A' 的距離 = 2
手指 2 在字母 'K' 上 -> 移動距離 = 0
手指 2 在字母 'E' 上 -> 移動距離 = 從字母 'K' 到字母 'E' 的距離 = 1
總距離 = 3ui

示例 2:spa

輸入:word = "HAPPY"
輸出:6
解釋:
使用兩根手指輸入 "HAPPY" 的最佳方案之一是:
手指 1 在字母 'H' 上 -> 移動距離 = 0
手指 1 在字母 'A' 上 -> 移動距離 = 從字母 'H' 到字母 'A' 的距離 = 2
手指 2 在字母 'P' 上 -> 移動距離 = 0
手指 2 在字母 'P' 上 -> 移動距離 = 從字母 'P' 到字母 'P' 的距離 = 0
手指 1 在字母 'Y' 上 -> 移動距離 = 從字母 'A' 到字母 'Y' 的距離 = 4
總距離 = 6code

示例 3:blog

輸入:word = "NEW"
輸出:3leetcode

示例 4:

輸入:word = "YEAR"
輸出:7

提示:

  • 2 <= word.length <= 300
  • 每一個 word[i] 都是一個大寫英文字母。

解題思路

我本身沒作出來,學習了比賽排行榜上第一頁的 suibianfahui 的代碼。這個代碼是我理解之後本身寫的。原來和原代碼相同。

準備

定義一個字母位置表,再定義一個函數 find_distance 查找任意兩個字母間距離

動規

mapx[f1, f2] = setp

mapx 是一個字典,

  f1 表明當前狀態第一個手指的位置,f2 是第二個手指的位置, None 表明這個手指還沒用過

  setp 是如今一共移動了多少距離。

初始狀態

mapx[單詞第一個字母,None] = 0    表明我用第一個手打了第一個字母,第二個手沒動,一共移動 0 步

狀態轉移方程

從第二個字母開始遍歷單詞,

對每個字母要檢查**上一步**全部的狀態(由於只須要上一步,因此不用 dp 數組,每次都覆蓋上一次的結果就能夠了)

對每一個狀態,嘗試用第一個手指打當前字母和用第二個手指打當前字母

結果

最後返回 map 中最小值就能夠了。

歡迎來[個人博客](https://codeplot.top/),看我刷的其餘題目:[刷題記錄](https://codeplot.top/categori...

代碼

class Solution:
    def minimumDistance(self, word: str) -> int:
        if len(word) == 2: # 若是隻有兩個字母,不須要移動
            return 0
        # 字母位置表
        pos = {}
        ch = ord('A')
        for i in range(5):
            for j in range(6):
                pos[chr(ch)] = (i, j)
                if ch == ord('Z'): break
                ch += 1
        #print(pos)
        # {'A': (0, 0), 'B': (0, 1), 'C': (0, 2), 'D': (0, 3), 'E': (0, 4), 'F': (0, 5), 'G': (1, 0), 'H': (1, 1), 'I': (1, 2), 'J': (1, 3), 'K': (1, 4), 'L': (1, 5), 'M': (2, 0), 'N': (2, 1), 'O': (2, 2), 'P': (2, 3), 'Q': (2, 4), 'R': (2, 5), 'S': (3, 0), 'T': (3, 1), 'U': (3, 2), 'V': (3, 3), 'W': (3, 4), 'X': (3, 5), 'Y': (4, 0), 'Z': (4, 1)}
        def find_distance(a, b): # 求 a, b 兩個字母距離
            if a == None: 
                return 0
            return abs(pos[a][0] - pos[b][0]) + abs(pos[a][1] - pos[b][1])
        
        mapx = {}
        mapx[(word[0], None)] = 0 # map[(a, b)] = setp 表明 第一個手指目前在 a 上, 第二個手指在 b 上, 步數爲 setp
                                  # None 表明這個手指還沒用過
        for cur in word[1:]:
            next_map = {}
            for finger1, finger2 in mapx:
                f1_dis = find_distance(finger1, cur) # 手指 1 到當前字母的距離
                f2_dis = find_distance(finger2, cur) # 手指 2 到當前字母的距離
                new_state1 = (cur, finger2) # 第一個手指按當前字母(固然第二個手指的狀態不變)
                new_state2 = (finger1, cur) # 第二個手指按當前字母
                for new_state, dis in ((new_state1, f1_dis), (new_state2, f2_dis)):
                    if new_state in next_map:
                        next_map[new_state] = min(mapx[(finger1, finger2)] + dis, next_map[new_state])
                    else:
                        next_map[new_state] = mapx[(finger1, finger2)] + dis
            mapx = next_map
        return min(mapx.values())
相關文章
相關標籤/搜索