1320. Minimum Distance to Type a Word Using Two Fingers
Problem Description
You have a keyboard layout where English uppercase letters are arranged in a grid pattern. The keyboard has 26 letters arranged with 6 letters per row (except the last row which has 2 letters). The letters are positioned as follows:
- Row 0: A B C D E F (positions 0-5)
- Row 1: G H I J K L (positions 6-11)
- Row 2: M N O P Q R (positions 12-17)
- Row 3: S T U V W X (positions 18-23)
- Row 4: Y Z (positions 24-25)
Each letter has coordinates (row, column)
. For example:
- Letter 'A' is at coordinate
(0, 0)
- Letter 'B' is at coordinate
(0, 1)
- Letter 'P' is at coordinate
(2, 3)
- Letter 'Z' is at coordinate
(4, 1)
You need to type a given string word
using two fingers. The distance between any two coordinates (x₁, y₁)
and (x₂, y₂)
is calculated using Manhattan distance: |x₁ - x₂| + |y₁ - y₂|
.
Key rules:
- You can use two fingers to type the word
- The initial positions of your fingers are free (don't count toward the total distance)
- Your fingers don't have to start at the first letter or first two letters
- Each letter in the word must be typed in order
- Only one finger moves to type each letter
The goal is to find the minimum total distance traveled by your fingers to type the entire word.
For example, if you need to type "CAKE":
- You could position one finger initially at 'C' and another at 'A' (no cost for initial positioning)
- Then move fingers optimally to type 'K' and 'E'
- The total distance would be the sum of all movements made after the initial positioning
Return the minimum total distance required to type the given word using two fingers.
Intuition
The key insight is that at any point while typing, we need to know where both fingers are positioned to make optimal decisions about which finger to use for the next letter. This naturally leads to a dynamic programming approach where we track the positions of both fingers after typing each character.
Think about it this way: when we need to type the next letter, we have two choices - use finger 1 or use finger 2. The optimal choice depends on:
- Where each finger currently is
- How far each finger would need to move
- Where the remaining letters are (which affects future moves)
Since we can't predict all future moves easily, we can use dynamic programming to explore all possibilities and keep track of the minimum cost for each possible configuration.
The state representation becomes clear: f[i][j][k]
represents "after typing the i-th character, what's the minimum distance if finger 1 is at position j and finger 2 is at position k?"
For the base case, when typing the first letter, one finger moves to that letter (with 0 cost since initial positions are free) while the other finger can be anywhere. This gives us all possible starting configurations.
For subsequent letters, we need to consider:
- If we use finger 1 to type the current letter, finger 1 moves from its previous position to the new letter's position, while finger 2 stays put
- If we use finger 2 to type the current letter, finger 2 moves while finger 1 stays put
The tricky part is that we need to track which finger was at the previous letter's position. If finger 1 was at position a
(previous letter) and we move it to position b
(current letter), then we add dist(a, b)
to our cost. But if finger 2 was at position a
, then we need to consider all possible previous positions of finger 1 to find the minimum cost path.
By building up the solution letter by letter and considering all possible finger configurations, we ensure we find the globally optimal solution rather than getting stuck in a locally optimal but globally suboptimal choice.
Learn more about Dynamic Programming patterns.
Solution Approach
The solution uses dynamic programming with a 3D state array to track all possible finger positions after typing each character.
State Definition:
f[i][j][k]
represents the minimum distance after typingword[i]
, with finger 1 at positionj
and finger 2 at positionk
- Positions
j
andk
range from 0 to 25 (representing letters A to Z) - Initialize all states to infinity
Distance Calculation:
The dist(a, b)
function calculates Manhattan distance between two letter positions:
- Convert position to row/column:
row = position // 6
,column = position % 6
- Distance =
|row1 - row2| + |col1 - col2|
Base Case (First Letter):
When typing word[0]
, we have two scenarios:
- Finger 1 at
word[0]
, finger 2 anywhere:f[0][word[0]][k] = 0
for allk ∈ [0, 25]
- Finger 2 at
word[0]
, finger 1 anywhere:f[0][k][word[0]] = 0
for allk ∈ [0, 25]
The cost is 0 because initial finger positions are free.
Transition (Subsequent Letters):
For each letter word[i]
(where i ≥ 1
):
- Let
a = word[i-1]
(previous letter position) - Let
b = word[i]
(current letter position)
We consider two main cases:
Case 1: Use finger 1 to type current letter (finger 1 moves to position b
):
- For each possible position
j
of finger 2:- If finger 1 was at position
a
previously:f[i][b][j] = min(f[i][b][j], f[i-1][a][j] + dist(a, b))
- If finger 2 is at position
a
(i.e.,j = a
), then finger 2 typed the previous letter. We enumerate all possible previous positionsk
of finger 1:f[i][b][j] = min(f[i][b][j], f[i-1][k][a] + dist(k, b))
- If finger 1 was at position
Case 2: Use finger 2 to type current letter (finger 2 moves to position b
):
- For each possible position
j
of finger 1:- If finger 2 was at position
a
previously:f[i][j][b] = min(f[i][j][b], f[i-1][j][a] + dist(a, b))
- If finger 1 is at position
a
(i.e.,j = a
), then finger 1 typed the previous letter. We enumerate all possible previous positionsk
of finger 2:f[i][j][b] = min(f[i][j][b], f[i-1][a][k] + dist(k, b))
- If finger 2 was at position
Final Answer:
After processing all letters, the last letter must be at position word[n-1]
. We find the minimum among:
- All states where finger 1 is at the last letter:
min(f[n-1][word[n-1]][j])
for allj
- All states where finger 2 is at the last letter:
min(f[n-1][j][word[n-1]])
for allj
The algorithm systematically explores all possible finger configurations and movement sequences, ensuring we find the globally optimal solution with time complexity O(n × 26²)
and space complexity O(n × 26²)
.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through typing the word "HI" to illustrate the solution approach.
First, let's identify the letter positions:
- 'H' is at position 7 (row 1, column 1)
- 'I' is at position 8 (row 1, column 2)
Step 1: Initialize the DP array
- Create
f[2][26][26]
initialized to infinity f[i][j][k]
= minimum distance after typing character i, with finger 1 at position j and finger 2 at position k
Step 2: Base case - typing 'H' (word[0]) Since initial finger positions are free, we set:
- Finger 1 at 'H', finger 2 anywhere:
f[0][7][k] = 0
for all k ∈ [0, 25] - Finger 2 at 'H', finger 1 anywhere:
f[0][j][7] = 0
for all j ∈ [0, 25]
This gives us 52 possible starting configurations, all with cost 0.
Step 3: Transition - typing 'I' (word[1]) Previous letter: a = 7 ('H') Current letter: b = 8 ('I') Distance from 'H' to 'I': dist(7, 8) = |1-1| + |1-2| = 1
Now we consider all valid previous states and calculate new states:
Case 1: Use finger 1 to type 'I' (finger 1 moves to position 8)
- From state
f[0][7][k] = 0
(finger 1 was at 'H'):f[1][8][k] = min(∞, 0 + 1) = 1
for all k ≠ 7
- When k = 7 (both fingers were at 'H'), we need to check all possible previous positions of finger 1:
- From state
f[0][j][7] = 0
:f[1][8][7] = min(∞, 0 + dist(j, 8))
- The minimum occurs when j = 7:
f[1][8][7] = 0 + dist(7, 8) = 1
- From state
Case 2: Use finger 2 to type 'I' (finger 2 moves to position 8)
- From state
f[0][j][7] = 0
(finger 2 was at 'H'):f[1][j][8] = min(∞, 0 + 1) = 1
for all j ≠ 7
- When j = 7 (both fingers were at 'H'), we need to check all possible previous positions of finger 2:
- From state
f[0][7][k] = 0
:f[1][7][8] = min(∞, 0 + dist(k, 8))
- The minimum occurs when k = 7:
f[1][7][8] = 0 + dist(7, 8) = 1
- From state
Step 4: Find the minimum distance The last letter 'I' is at position 8. We check:
- States where finger 1 is at 'I':
min(f[1][8][k])
for all k = min(1) = 1 - States where finger 2 is at 'I':
min(f[1][j][8])
for all j = min(1) = 1
Result: The minimum distance to type "HI" is 1.
This makes intuitive sense: we position both fingers initially at 'H' (free), then move one finger from 'H' to 'I' (distance = 1).
Solution Implementation
1class Solution:
2 def minimumDistance(self, word: str) -> int:
3 """
4 Calculate minimum distance to type a word using two fingers on a keyboard.
5 The keyboard layout is A-Z arranged in a 6x5 grid (last row has 2 letters).
6 """
7
8 def calculate_distance(char1: int, char2: int) -> int:
9 """
10 Calculate Manhattan distance between two characters on the keyboard.
11
12 Args:
13 char1: First character index (0-25 for A-Z)
14 char2: Second character index (0-25 for A-Z)
15
16 Returns:
17 Manhattan distance between the two positions
18 """
19 row1, col1 = divmod(char1, 6)
20 row2, col2 = divmod(char2, 6)
21 return abs(row1 - row2) + abs(col1 - col2)
22
23 word_length = len(word)
24
25 # dp[i][left_finger][right_finger] represents minimum distance after typing
26 # word[0:i+1] with left finger at position left_finger and right finger at right_finger
27 dp = [[[float('inf')] * 26 for _ in range(26)] for _ in range(word_length)]
28
29 # Initialize first character - can be typed by either finger with 0 cost
30 first_char_index = ord(word[0]) - ord('A')
31 for finger_pos in range(26):
32 dp[0][first_char_index][finger_pos] = 0 # Left finger typed first char
33 dp[0][finger_pos][first_char_index] = 0 # Right finger typed first char
34
35 # Process each subsequent character
36 for i in range(1, word_length):
37 prev_char_index = ord(word[i - 1]) - ord('A')
38 curr_char_index = ord(word[i]) - ord('A')
39 distance_between_chars = calculate_distance(prev_char_index, curr_char_index)
40
41 for other_finger in range(26):
42 # Case 1: Same finger that typed previous character types current character
43 # Left finger was at prev_char, moves to curr_char
44 dp[i][curr_char_index][other_finger] = min(
45 dp[i][curr_char_index][other_finger],
46 dp[i - 1][prev_char_index][other_finger] + distance_between_chars
47 )
48 # Right finger was at prev_char, moves to curr_char
49 dp[i][other_finger][curr_char_index] = min(
50 dp[i][other_finger][curr_char_index],
51 dp[i - 1][other_finger][prev_char_index] + distance_between_chars
52 )
53
54 # Case 2: The other finger (not at prev_char) types current character
55 if other_finger == prev_char_index:
56 for previous_position in range(26):
57 distance_to_current = calculate_distance(previous_position, curr_char_index)
58 # Left finger moves from previous_position to curr_char
59 dp[i][curr_char_index][other_finger] = min(
60 dp[i][curr_char_index][other_finger],
61 dp[i - 1][previous_position][prev_char_index] + distance_to_current
62 )
63 # Right finger moves from previous_position to curr_char
64 dp[i][other_finger][curr_char_index] = min(
65 dp[i][other_finger][curr_char_index],
66 dp[i - 1][prev_char_index][previous_position] + distance_to_current
67 )
68
69 # Find minimum distance among all valid final states
70 last_char_index = ord(word[-1]) - ord('A')
71
72 # Minimum when left finger is at last character
73 min_left_finger = min(dp[word_length - 1][last_char_index])
74
75 # Minimum when right finger is at last character
76 min_right_finger = min(dp[word_length - 1][j][last_char_index] for j in range(26))
77
78 return int(min(min_left_finger, min_right_finger))
79
1class Solution {
2 public int minimumDistance(String word) {
3 int n = word.length();
4 final int INF = 1 << 30;
5
6 // dp[i][j][k] represents the minimum distance to type first i+1 characters
7 // with left finger on character j and right finger on character k
8 int[][][] dp = new int[n][26][26];
9
10 // Initialize all states with infinity
11 for (int[][] row : dp) {
12 for (int[] cell : row) {
13 Arrays.fill(cell, INF);
14 }
15 }
16
17 // Base case: first character can be typed by either finger with 0 cost
18 // The other finger can be at any position
19 int firstChar = word.charAt(0) - 'A';
20 for (int j = 0; j < 26; ++j) {
21 dp[0][firstChar][j] = 0; // Left finger types first char, right at position j
22 dp[0][j][firstChar] = 0; // Right finger types first char, left at position j
23 }
24
25 // Fill dp table for remaining characters
26 for (int i = 1; i < n; ++i) {
27 int prevChar = word.charAt(i - 1) - 'A';
28 int currChar = word.charAt(i) - 'A';
29 int distance = dist(prevChar, currChar);
30
31 for (int j = 0; j < 26; ++j) {
32 // Case 1: Move the finger that was on previous character to current character
33 // Left finger was on prevChar, move it to currChar
34 dp[i][currChar][j] = Math.min(dp[i][currChar][j], dp[i - 1][prevChar][j] + distance);
35 // Right finger was on prevChar, move it to currChar
36 dp[i][j][currChar] = Math.min(dp[i][j][currChar], dp[i - 1][j][prevChar] + distance);
37
38 // Case 2: Use the other finger (that wasn't on prevChar) to type currChar
39 if (j == prevChar) {
40 for (int k = 0; k < 26; ++k) {
41 int moveDistance = dist(k, currChar);
42 // Left finger was at k, move it to currChar (right stays at prevChar=j)
43 dp[i][currChar][j] = Math.min(dp[i][currChar][j], dp[i - 1][k][prevChar] + moveDistance);
44 // Right finger was at k, move it to currChar (left stays at prevChar=j)
45 dp[i][j][currChar] = Math.min(dp[i][j][currChar], dp[i - 1][prevChar][k] + moveDistance);
46 }
47 }
48 }
49 }
50
51 // Find minimum distance among all valid final states
52 // One finger must be on the last character
53 int result = INF;
54 int lastChar = word.charAt(n - 1) - 'A';
55 for (int j = 0; j < 26; ++j) {
56 result = Math.min(result, dp[n - 1][j][lastChar]); // Right finger on last char
57 result = Math.min(result, dp[n - 1][lastChar][j]); // Left finger on last char
58 }
59
60 return result;
61 }
62
63 /**
64 * Calculate Manhattan distance between two keys on a 6x5 keyboard layout
65 * Keys are numbered 0-25 (A-Z) in row-major order
66 */
67 private int dist(int a, int b) {
68 int row1 = a / 6, col1 = a % 6;
69 int row2 = b / 6, col2 = b % 6;
70 return Math.abs(row1 - row2) + Math.abs(col1 - col2);
71 }
72}
73
1class Solution {
2public:
3 int minimumDistance(string word) {
4 int wordLength = word.size();
5 const int INF = 1 << 30; // Large value representing infinity
6
7 // dp[i][leftFinger][rightFinger] = minimum distance to type first i+1 characters
8 // with left finger on position leftFinger and right finger on position rightFinger
9 vector<vector<vector<int>>> dp(wordLength,
10 vector<vector<int>>(26,
11 vector<int>(26, INF)));
12
13 // Initialize first character - can be typed with either finger at no cost
14 // The other finger can be at any position
15 for (int otherFinger = 0; otherFinger < 26; ++otherFinger) {
16 dp[0][word[0] - 'A'][otherFinger] = 0; // First char typed with left finger
17 dp[0][otherFinger][word[0] - 'A'] = 0; // First char typed with right finger
18 }
19
20 // Process each subsequent character
21 for (int i = 1; i < wordLength; ++i) {
22 int prevChar = word[i - 1] - 'A'; // Previous character position
23 int currChar = word[i] - 'A'; // Current character to type
24 int moveDist = dist(prevChar, currChar); // Distance between consecutive chars
25
26 // Try all possible finger configurations
27 for (int otherFinger = 0; otherFinger < 26; ++otherFinger) {
28 // Case 1: Same finger that typed previous char types current char
29 // Left finger moves from prevChar to currChar, right stays at otherFinger
30 dp[i][currChar][otherFinger] = min(dp[i][currChar][otherFinger],
31 dp[i - 1][prevChar][otherFinger] + moveDist);
32
33 // Right finger moves from prevChar to currChar, left stays at otherFinger
34 dp[i][otherFinger][currChar] = min(dp[i][otherFinger][currChar],
35 dp[i - 1][otherFinger][prevChar] + moveDist);
36
37 // Case 2: The other finger (not at prevChar) types current char
38 if (otherFinger == prevChar) {
39 // The finger at otherFinger position was the one that typed previous char
40 // So we use the other finger to type current char
41 for (int prevOtherFinger = 0; prevOtherFinger < 26; ++prevOtherFinger) {
42 int otherFingerDist = dist(prevOtherFinger, currChar);
43
44 // Left finger was at prevOtherFinger, moves to currChar
45 dp[i][currChar][otherFinger] = min(dp[i][currChar][otherFinger],
46 dp[i - 1][prevOtherFinger][prevChar] + otherFingerDist);
47
48 // Right finger was at prevOtherFinger, moves to currChar
49 dp[i][otherFinger][currChar] = min(dp[i][otherFinger][currChar],
50 dp[i - 1][prevChar][prevOtherFinger] + otherFingerDist);
51 }
52 }
53 }
54 }
55
56 // Find minimum distance among all valid final configurations
57 // One finger must be at the last character position
58 int minDistance = INF;
59 int lastChar = word[wordLength - 1] - 'A';
60
61 for (int otherFinger = 0; otherFinger < 26; ++otherFinger) {
62 minDistance = min(minDistance, dp[wordLength - 1][lastChar][otherFinger]);
63 minDistance = min(minDistance, dp[wordLength - 1][otherFinger][lastChar]);
64 }
65
66 return minDistance;
67 }
68
69 // Calculate Manhattan distance between two keys on a 6x5 keyboard layout
70 // Keys are arranged as: A=0, B=1, ..., Z=25
71 // Keyboard layout: 6 columns per row
72 int dist(int keyA, int keyB) {
73 int rowA = keyA / 6, colA = keyA % 6;
74 int rowB = keyB / 6, colB = keyB % 6;
75 return abs(rowA - rowB) + abs(colA - colB);
76 }
77};
78
1/**
2 * Calculates minimum distance to type a word using two fingers on a keyboard
3 * @param word - The word to type (uppercase letters only)
4 * @returns Minimum total distance fingers need to travel
5 */
6function minimumDistance(word: string): number {
7 const wordLength = word.length;
8 const INF = 1 << 30; // Large value representing infinity
9
10 // dp[i][leftFinger][rightFinger] = minimum distance to type first i+1 characters
11 // with left finger on position leftFinger and right finger on position rightFinger
12 const dp: number[][][] = Array(wordLength)
13 .fill(null)
14 .map(() => Array(26)
15 .fill(null)
16 .map(() => Array(26).fill(INF)));
17
18 // Initialize first character - can be typed with either finger at no cost
19 // The other finger can be at any position
20 for (let otherFinger = 0; otherFinger < 26; otherFinger++) {
21 dp[0][word.charCodeAt(0) - 65][otherFinger] = 0; // First char typed with left finger
22 dp[0][otherFinger][word.charCodeAt(0) - 65] = 0; // First char typed with right finger
23 }
24
25 // Process each subsequent character
26 for (let i = 1; i < wordLength; i++) {
27 const prevChar = word.charCodeAt(i - 1) - 65; // Previous character position (A=0, B=1, etc.)
28 const currChar = word.charCodeAt(i) - 65; // Current character to type
29 const moveDist = dist(prevChar, currChar); // Distance between consecutive chars
30
31 // Try all possible finger configurations
32 for (let otherFinger = 0; otherFinger < 26; otherFinger++) {
33 // Case 1: Same finger that typed previous char types current char
34 // Left finger moves from prevChar to currChar, right stays at otherFinger
35 dp[i][currChar][otherFinger] = Math.min(
36 dp[i][currChar][otherFinger],
37 dp[i - 1][prevChar][otherFinger] + moveDist
38 );
39
40 // Right finger moves from prevChar to currChar, left stays at otherFinger
41 dp[i][otherFinger][currChar] = Math.min(
42 dp[i][otherFinger][currChar],
43 dp[i - 1][otherFinger][prevChar] + moveDist
44 );
45
46 // Case 2: The other finger (not at prevChar) types current char
47 if (otherFinger === prevChar) {
48 // The finger at otherFinger position was the one that typed previous char
49 // So we use the other finger to type current char
50 for (let prevOtherFinger = 0; prevOtherFinger < 26; prevOtherFinger++) {
51 const otherFingerDist = dist(prevOtherFinger, currChar);
52
53 // Left finger was at prevOtherFinger, moves to currChar
54 dp[i][currChar][otherFinger] = Math.min(
55 dp[i][currChar][otherFinger],
56 dp[i - 1][prevOtherFinger][prevChar] + otherFingerDist
57 );
58
59 // Right finger was at prevOtherFinger, moves to currChar
60 dp[i][otherFinger][currChar] = Math.min(
61 dp[i][otherFinger][currChar],
62 dp[i - 1][prevChar][prevOtherFinger] + otherFingerDist
63 );
64 }
65 }
66 }
67 }
68
69 // Find minimum distance among all valid final configurations
70 // One finger must be at the last character position
71 let minDistance = INF;
72 const lastChar = word.charCodeAt(wordLength - 1) - 65;
73
74 for (let otherFinger = 0; otherFinger < 26; otherFinger++) {
75 minDistance = Math.min(minDistance, dp[wordLength - 1][lastChar][otherFinger]);
76 minDistance = Math.min(minDistance, dp[wordLength - 1][otherFinger][lastChar]);
77 }
78
79 return minDistance;
80}
81
82/**
83 * Calculate Manhattan distance between two keys on a 6x5 keyboard layout
84 * Keys are arranged as: A=0, B=1, ..., Z=25
85 * Keyboard layout: 6 columns per row
86 * @param keyA - First key position (0-25)
87 * @param keyB - Second key position (0-25)
88 * @returns Manhattan distance between the two keys
89 */
90function dist(keyA: number, keyB: number): number {
91 const rowA = Math.floor(keyA / 6);
92 const colA = keyA % 6;
93 const rowB = Math.floor(keyB / 6);
94 const colB = keyB % 6;
95 return Math.abs(rowA - rowB) + Math.abs(colA - colB);
96}
97
Time and Space Complexity
The time complexity is O(n × |Σ|²)
, where n
is the length of the string word
and |Σ| = 26
represents the size of the alphabet.
The analysis breaks down as follows:
- The outer loop runs
n
times (for each character in the word) - For each iteration
i
, we iterate through all 26 possible positions for fingerj
, contributingO(|Σ|)
operations - Within the special case when
j == a
, we have another loop through all 26 positionsk
, adding anotherO(|Σ|)
factor - Overall, this gives us
O(n × |Σ| × |Σ|) = O(n × |Σ|²)
The space complexity is O(n × |Σ|²)
due to the 3-dimensional DP array f
with dimensions [n][26][26]
, which stores the minimum distance for each position i
in the word with the two fingers at positions [left_finger][right_finger]
.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Incorrect Assumption About Initial Finger Positions
Pitfall: Many solutions incorrectly assume that fingers must start at the first one or two letters of the word, leading to suboptimal solutions.
Example: For the word "HAPPY", you might assume:
- Finger 1 starts at 'H', Finger 2 starts at 'A'
- Or both fingers start at 'H'
Why it's wrong: The problem states that initial finger positions are free (cost = 0). Fingers can start anywhere on the keyboard, not necessarily at the beginning letters.
Correct Approach: Initialize the DP state for the first letter with both possibilities:
- One finger at the first letter, other finger anywhere (cost = 0)
- This allows the algorithm to find the optimal starting position for the idle finger
2. Mishandling the Transition Between Letters
Pitfall: Failing to correctly track which finger typed the previous letter when calculating transitions.
Problematic Code Example:
# WRONG: Only considering the case where the same finger continues typing dp[i][curr][other] = dp[i-1][prev][other] + dist(prev, curr)
Why it's wrong: This doesn't account for the case where the other finger (currently at position other
) might have typed the previous letter.
Correct Implementation:
# Must check if other_finger is at prev_char position
if other_finger == prev_char_index:
# The other finger typed previous letter, so we need to consider
# all possible previous positions of the current moving finger
for previous_position in range(26):
distance = calculate_distance(previous_position, curr_char_index)
dp[i][curr_char_index][other_finger] = min(
dp[i][curr_char_index][other_finger],
dp[i-1][previous_position][prev_char_index] + distance
)
3. Space Optimization Trap
Pitfall: Attempting to optimize space by using only 2D DP array instead of 3D.
Problematic Approach:
# WRONG: Trying to use dp[finger1_pos][finger2_pos] without tracking progress
dp = [[float('inf')] * 26 for _ in range(26)]
Why it fails: Without tracking which character we're currently typing (the i
dimension), we lose critical information about the sequence and can't correctly compute transitions.
Solution: Maintain the full 3D state or use rolling array optimization:
# Option 1: Full 3D array (shown in solution)
dp = [[[float('inf')] * 26 for _ in range(26)] for _ in range(word_length)]
# Option 2: Rolling array optimization (if space is critical)
prev_dp = [[float('inf')] * 26 for _ in range(26)]
curr_dp = [[float('inf')] * 26 for _ in range(26)]
# Swap prev_dp and curr_dp after each iteration
4. Incorrect Distance Calculation
Pitfall: Using Euclidean distance or incorrect grid mapping.
Wrong Example:
# WRONG: Using Euclidean distance
import math
distance = math.sqrt((row1 - row2)**2 + (col1 - col2)**2)
# WRONG: Incorrect grid layout (assuming 5 columns)
row, col = divmod(char_index, 5)
Correct Approach:
# Manhattan distance with 6 columns per row
row, col = divmod(char_index, 6)
distance = abs(row1 - row2) + abs(col1 - col2)
5. Edge Case: Single Character Word
Pitfall: Not handling words with length 1 correctly.
Issue: The algorithm might fail or return incorrect results for single-character words.
Solution: The current implementation handles this correctly by:
- Initializing both finger positions for the first (and only) character
- Returning 0 as the minimum distance (no movement needed after initial positioning)
Test Case:
assert minimumDistance("A") == 0 assert minimumDistance("Z") == 0
The three-steps of Depth First Search are:
- Identify states;
- Draw the state-space tree;
- DFS on the state-space tree.
Recommended Readings
What is Dynamic Programming Prerequisite DFS problems dfs_intro Backtracking problems backtracking Memoization problems memoization_intro Pruning problems backtracking_pruning Dynamic programming is an algorithmic optimization technique that breaks down a complicated problem into smaller overlapping sub problems in a recursive manner and uses solutions to the sub problems to construct a solution
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Don’t Miss This!