Problem 1974

Abstract / Summary

A typewriter moves by shifting to a character then pressing it so find the least time to type a word this way.

Note

The full problem description, including helpful examples, can be found on LeetCode.

Python 1974.py

class Solution:
    def minTimeToType(self, word: str) -> int:
        result = 0

        def distance(a, b):
            a = ord(a)
            b = ord(b)
            diff = abs(a - b)
            return min(diff, 26 - diff)

        prev = "a"
        for c in word:
            result += 1 + distance(c, prev)
            prev    = c

        return result
16 lines | 377 bytes | submitted January 26, 2024 | GitHub   tab size 4 | low complexity

Difficulty

This problem is ranked as
easy medium hard

and has an acceptance rate of about 79% (80k+ submissions).

Typical patterns to solve this problem:
  • Greedy
  • String
I solved 663 easy, 1250 medium and 309 hard problems

AI Disclaimer

Every single line of code was written by me, 100% from scratch, between August 2023 and August 2024.
However, two years later I set up this website and used various AI tools to generate most of the walkthrough / explanations below.

See this dedicated page for more details.
LeetCode profile | GitHub repo

Code Walkthrough

Overview

The provided implementation defines a class with a single method that calculates the minimum number of actions required to type a given word on a circular alphabet dial. The algorithm treats the dial as a ring of 26 lowercase English letters, starting from the letter ‘a’. For each character in the input string, it adds the cost of moving the dial to that character and the cost of pressing the key. The total accumulated cost is returned as the result.

Core Logic

At the heart of the method is a loop that walks through the characters of the input word. A running total called result is incremented by the sum of a constant press cost and a distance cost between the current character and the previously selected character. The previous character is tracked in a variable that is updated after each iteration.

result = 0
prev = "a"
for c in word:
    result += 1 + distance(c, prev)
    prev = c
return result

The constant 1 represents the press action, while the distance function supplies the minimal rotation steps needed to align the dial.

Distance Computation

The helper function distance receives two characters, converts them to their Unicode code points using ord, and computes the absolute difference. Because the dial is circular, the function returns the smaller of the direct difference and the wrap-around distance, which is obtained by subtracting the direct difference from the total number of letters (26).

def distance(a, b):
    a = ord(a)
    b = ord(b)
    diff = abs(a - b)
    return min(diff, 26 - diff)

By performing the conversion to integer code points once per call and using a simple arithmetic expression, the function efficiently determines the optimal rotation steps.

Iteration Over Input

The loop processes each character sequentially, ensuring that the state of the dial (the prev variable) reflects the last typed character. This sequential dependency mirrors the real-world operation of a rotary input device, where each movement builds on the previous position. The algorithm does not require any auxiliary data structures, keeping the memory footprint minimal.

Edge Cases

The implementation gracefully handles an empty input string. In that scenario, the loop body never executes, leaving result at its initial value of zero, which correctly indicates that no actions are needed. When the word consists of a single character, the distance is measured from the starting position ‘a’ to that character, and the press cost is added, yielding the correct total for a one-letter word. Because the distance calculation uses modular arithmetic via min(diff, 26 - diff), it correctly accounts for cases where moving backward around the dial is shorter than moving forward, such as transitioning from ‘z’ to ‘b’.

Performance Considerations

The algorithm processes each character exactly once, resulting in a linear traversal of the input. The use of local variables (result, prev) and the in-line definition of the distance helper avoid repeated attribute lookups or global namespace accesses, which contributes to faster execution. Converting characters to their ordinal values inside the distance function eliminates the need for repeated string indexing or slicing. The arithmetic operations involved are constant-time, and the absence of additional containers ensures that the memory usage stays proportional to the input size without extra overhead. Overall, the design achieves an efficient balance between clarity and speed for the problem it solves.

written by openai gpt

ELI5 - Simplified Explanation

Imagine a big circular wheel with all the letters of the alphabet written on it, just like how a toy dial works. The goal is to type out a word by moving your finger from one letter to the next.

The pointer starts at the letter a. To type a new letter, the finger must move along the wheel to reach the target. Sometimes moving to the right is the fastest way, and sometimes taking the shortcut by going the other way around the circle is faster. The code figures out which way is the shortest distance between the current letter and the next letter needed.

After moving to the right letter, the finger needs one extra moment to press a button to type it. This happens over and over for every single letter in the word. Every time a letter is typed, that letter becomes the new starting point for the next jump. All those movements and typing moments are added up to find the total time spent.

written by google gemini

Code Quality

Several LLMs ranked my code quality on a scale from 1 (very poor) to 10 (outstanding):
n = 27 | median = 8 | μ = 8.11 | σ = 0.92

Complexity Analysis

Time: linear
As a rule of thumb, the maximum input size for one second execution time is
  • factorial: up to 10 elements
  • exponential: up to 20 elements
  • polynomial: a few thousand elements
  • loglinear: up to 100,000 elements
  • linear: a few million elements
  • logarithmic: a billion elements
  • constant: practically unlimited
generated automatically

Other Solutions

I wrote a basic crawler to find other solutions to that problem.
Obviously, I did that after I solved the problem myself.

In general, AlgoMonster and WalkCCC solutions are high-quality and always worth a look.
I haven't checked most of the other solutions, but they might be helpful as well.

And of course, the LeetCode forum is always a good place (or even the best) to look for alternative approaches.

(click on a column header to sort the table)
author
author solutions
www AlgoMonster C++ Python Java TS
WalkCCC C++ Python Java
leetcode.ca C++ Python Java Go TS
Progiez C++ Python Java
github black-shadows C++
charles-wangkai Java
DimitrisJim JS
fartem Ruby
fsq C++
JoshCrozier JS
lkwq007 Python
suxrobGM C#
trung-hn Python
varunu28 Java
AlgoMonster C++, Python, Java, TypeScript
WalkCCC C++, Python, Java
leetcode.ca C++, Go, Java, Python, TypeScript
Progiez C++, Java, Python
black-shadows C++, C++
charles-wangkai Java
DimitrisJim JavaScript
fartem Ruby
fsq C++
JoshCrozier JavaScript
lkwq007 Python
suxrobGM C#
trung-hn Python
varunu28 Java
25 links | 14 authors | 8 languages

Videos

7 videos   did my crawler come up with invalid videos ? drop me a line.

Similar Problems

1 similar problem

Solved On The Same Day

5 solutions   January 26, 2024

Extra

There are a few extra pages giving you some insights into my setup:
  • Tech Stack - my development environment and tools
  • AI - how AI helped me create this website (NOT solving the problems)
  • Progress - progression over time
  • Quality - code quality