Want Help Cracking FAANG?

(Then click this)

×
Back to Question Bank

651. 4 Keys Keyboard - Leetcode Solution

Problem Description

The 4 Keys Keyboard problem asks: Imagine you have a special keyboard with only four keys:

  • A: Prints one 'A' on the screen.
  • Ctrl-A: Selects all the text on the screen.
  • Ctrl-C: Copies the selected text to a buffer (clipboard).
  • Ctrl-V: Pastes the buffer's content onto the screen, appending it to existing text.
Given a number n (the total number of allowed key presses), return the maximum number of 'A's you can print on the screen using exactly n key presses. You must decide the optimal sequence of these four operations to maximize the output.

Constraints:

  • 1 ≤ n ≤ 50
  • Each key press counts as one move.
  • You cannot paste anything until you have copied something.

Thought Process

At first glance, it might seem optimal to just press 'A' repeatedly, but with the copy-paste operations, there might be a more efficient way to multiply the number of 'A's. The challenge is to figure out when to use the copy-paste sequence to maximize the output. We need to balance between simply typing 'A' and using the more powerful copy-paste operations.

A brute-force approach would be to try every possible sequence of operations, but this quickly becomes infeasible as n grows. Instead, we look for patterns or subproblems we can solve efficiently, such as:

  • What is the best way to use the last few operations?
  • Is there a way to build the solution using the results of smaller problems?
This leads us toward a dynamic programming approach, where we build up solutions for smaller values of n and use them to solve larger ones.

Solution Approach

We'll use dynamic programming to solve this problem efficiently. The idea is to keep track of the maximum number of 'A's that can be produced with a given number of key presses.

  • Let dp[i] represent the maximum number of 'A's that can be printed with i key presses.
  • For each i from 1 to n:
    • By default, you can always press 'A', so dp[i] = dp[i-1] + 1.
    • For more efficiency, consider sequences where you:
      1. Build up some number of 'A's (say at step j).
      2. Then, at step j, perform Ctrl-A, Ctrl-C (2 steps), and then multiple Ctrl-V (each paste is one step).
      3. For each possible j (where j < i-2), calculate:
        • Number of pastes: i - j - 2 (since 2 steps for select and copy).
        • Total 'A's: dp[j] * (number of pastes + 1) (the original plus all pastes).
      4. Update dp[i] if this gives a higher value.

This approach ensures we always have the best possible number of 'A's for each number of key presses, using previously computed results for efficiency. We use an array for dp because it allows constant-time access and updates.

Example Walkthrough

Let's walk through an example with n = 7:

  • Option 1: Just type 'A' 7 times
    Output: 7 'A's.
  • Option 2: Use copy-paste
    • Type 'A' 3 times (dp[3] = 3).
    • Step 4: Ctrl-A
    • Step 5: Ctrl-C
    • Steps 6 & 7: Ctrl-V twice (each adds 3 'A's).
    • Total: 3 (original) + 3 + 3 = 9 'A's.
  • Option 3: Try different split points
    • Type 'A' 2 times (dp[2] = 2).
    • Step 3: Ctrl-A
    • Step 4: Ctrl-C
    • Steps 5-7: Ctrl-V three times (each adds 2 'A's).
    • Total: 2 (original) + 2 + 2 + 2 = 8 'A's.
  • So, the best is 9 'A's for n = 7.

The DP array would look like this for n=7:
[0, 1, 2, 3, 4, 5, 6, 9]

Time and Space Complexity

  • Brute-force: Exponential time, as you would try all possible operation sequences. Not feasible for n up to 50.
  • Dynamic Programming:
    • For each i from 1 to n, we check all j from 1 to i - 3 (since we need at least 3 steps for select, copy, and one paste). So, it's O(n^2) time.
    • Space is O(n) for the dp array.

This is efficient for the given constraints.

Summary

The 4 Keys Keyboard problem is a classic dynamic programming challenge. The key insight is that the optimal strategy often involves building up a sequence of 'A's, then using select-copy-paste to multiply your progress. By using a DP array, we efficiently compute the best result for every number of key presses, always considering if a copy-paste sequence can beat simply typing 'A'. This approach is both elegant and efficient for the problem's constraints.

Code Implementation

class Solution:
    def maxA(self, n: int) -> int:
        dp = [0] * (n + 1)
        for i in range(1, n + 1):
            # Press 'A'
            dp[i] = dp[i - 1] + 1
            # Try all possible copy-paste sequences
            for j in range(1, i - 2):
                # At step j: select all, copy, then paste (i - j - 2) times
                dp[i] = max(dp[i], dp[j] * (i - j - 1))
        return dp[n]
      
class Solution {
public:
    int maxA(int n) {
        vector<int> dp(n + 1, 0);
        for (int i = 1; i <= n; ++i) {
            dp[i] = dp[i - 1] + 1;
            for (int j = 1; j < i - 2; ++j) {
                dp[i] = max(dp[i], dp[j] * (i - j - 1));
            }
        }
        return dp[n];
    }
};
      
class Solution {
    public int maxA(int n) {
        int[] dp = new int[n + 1];
        for (int i = 1; i <= n; i++) {
            dp[i] = dp[i - 1] + 1;
            for (int j = 1; j < i - 2; j++) {
                dp[i] = Math.max(dp[i], dp[j] * (i - j - 1));
            }
        }
        return dp[n];
    }
}
      
var maxA = function(n) {
    let dp = new Array(n + 1).fill(0);
    for (let i = 1; i <= n; i++) {
        dp[i] = dp[i - 1] + 1;
        for (let j = 1; j < i - 2; j++) {
            dp[i] = Math.max(dp[i], dp[j] * (i - j - 1));
        }
    }
    return dp[n];
};