LC 650. 2 Keys Keyboard

Sarthak Sehgal · April 11, 2020

Using DP

Most of the solutions of this problem which exist on LeetCode Discuss do not prove the recurrence property they are using (as you’ll understand below). Below is an elaborate discussion inspired by the this post. The discussion does not contain a mathematically intensive proof which is required to solve the problem more optimally. Please look at the post mentioned earlier for a proof using mathematical induction.

Solution Image 1

With the recurrence formula derived above, we can easily implement a DP solution:

// Language: Java
public static int minSteps(int n) {
    int[] dp = new int[n + 1];

    for (int k = 2; k <= n; k++) {
        dp[k] = Integer.MAX_VALUE;

        for (int i = 1; i < k; i++) {
            if (k % i != 0) continue;
            dp[k] = Math.min(dp[k], dp[i] + k / i);
        }
    }

    return dp[n];
}

Further, assuming T(k) = T(k_m) + k/k_m as mentioned above, we can further optimize the solution:

// Language: Java
public int minSteps(int n) {
    int[] dp = new int[n + 1];

    for (int k = 2, i = 0; k <= n; k++) {
        for (i = k >> 1; i >= 1 && k % i != 0; i--);

				dp[k] = dp[i] + k / i;
    }

    return dp[n];
}

Without using DP

If you observe the above solution, we only need the greatest divisor for n and then the greatest divisor for that number and so on. So we might be wasting a lot of space using a whole dp[] array.

Solution Image 2

Let’s see a non-DP solution:

int minSteps(int n) {
		int res = 0, k_m;
		for (int k=n; k>1; k=k_m) {
				for (k_m=k/2; k%k_m!=0; k_m--);
				res += k/k_m;
		}

		return res;
}

Twitter, Facebook