diff --git a/README.md b/README.md index 17b4312a6b..49a0a23938 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,7 @@ Your ideas/fixes/algorithms are more than welcome! |941|[Valid Mountain Array](https://leetcode.com/problems/valid-mountain-array/)|[Solution](../master/src/main/java/com/fishercoder/solutions/_941.java) | O(n) | O(1) | |Easy| |938|[Range Sum of BST](https://leetcode.com/problems/range-sum-of-bst/)|[Solution](../master/src/main/java/com/fishercoder/solutions/_938.java) | O(n) | O(n) | |Medium| BST, recursion, DFS |937|[Reorder Log Files](https://leetcode.com/problems/reorder-log-files/)|[Solution](../master/src/main/java/com/fishercoder/solutions/_937.java) | O(n) | O(n) | |Easy| +|935|[Knight Dialer](https://leetcode.com/problems/knight-dialer/)|[Solution](../master/src/main/java/com/fishercoder/solutions/_935.java) | O(n) | O(1) | |Medium| |933|[Number of Recent Calls](https://leetcode.com/problems/number-of-recent-calls/)|[Solution](../master/src/main/java/com/fishercoder/solutions/_933.java) | O(n) | O(n) | |Easy| |929|[Unique Email Addresses](https://leetcode.com/problems/unique-email-addresses/)|[Solution](../master/src/main/java/com/fishercoder/solutions/_929.java) | O(n) | O(n) | |Easy| |925|[Long Pressed Name](https://leetcode.com/problems/long-pressed-name/)|[Solution](../master/src/main/java/com/fishercoder/solutions/_925.java) | O(n) | O(1) | |Easy| diff --git a/src/main/java/com/fishercoder/solutions/_935.java b/src/main/java/com/fishercoder/solutions/_935.java new file mode 100644 index 0000000000..6a089a6803 --- /dev/null +++ b/src/main/java/com/fishercoder/solutions/_935.java @@ -0,0 +1,89 @@ +package com.fishercoder.solutions; + +/** + * A chess knight can move as indicated in the chess diagram below: + * + * https://assets.leetcode.com/uploads/2018/10/12/knight.png + * + * |---|---|---| + * | 1 | 2 | 3 | + * |---|---|---| + * | 4 | 5 | 6 | + * |---|---|---| + * | 7 | 8 | 9 | + * |---|---|---| + * | x | 0 | x | + * |---|---|---| + * + * This time, we place our chess knight on any numbered key of a phone pad (indicated above), and the knight makes N-1 hops. + * Each hop must be from one key to another numbered key. + * + * Each time it lands on a key (including the initial placement of the knight), it presses the number of that key, pressing N digits total. + * + * How many distinct numbers can you dial in this manner? + * + * Since the answer may be large, output the answer modulo 10^9 + 7. + * + * Note: + * * 1 <= N <= 5000 + */ + +public class _935 { + /* + * The intuition is to calculate the number of ways + * we can reach a key k after i hops, based on the number of ways we can reach keys x after i-1 hops + * s.t. the knight can move from x to k in one move + * For example, + * We can reach 6 in 3 ways after 1 hop (1 -> 6, 7 -> 6 or 0 -> 6) + * We can reach 8 in 2 ways after 1 hop (1 -> 8 or 3 -> 8) + * Thus, we can reach 1 in 5 ways after 2 hops: + * . 1. 1 -> 6 -> 1 + * . 2. 7 -> 6 -> 1 + * . 3. 0 -> 6 -> 1 + * 4. 1 -> 8 -> 1 + * 5. 3 -> 8 -> 1 + */ + public static class Solution1 { + private static final int MOD = 1000_000_007; + + // whereFromHere[i] is an array of keys that can be reached from the ith digit + private static final int[][] whereFromHere = { + {4, 6}, {6, 8}, {7, 9}, {4, 8}, // 0, 1, 2, 3 + {3, 9, 0}, {}, {1, 7, 0}, // 4, 5, 6 + {2, 6}, {1, 3}, {2, 4} // 7, 8, 9 + }; + + public int knightDialer(int N) { + // a[i] is the number of ways we can end up on the ith digit + // The initial array is for N = 1, i.e. for 0 hops. + long[] a = new long[]{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + + // Simulate N - 1 hops + for (int i = 0; i < N - 1; ++i) { + long[] tmp = new long[10]; + + // For each digit + for (int j = 0; j < 10; j++) { + // Which other digits can we reach? + for (int k : whereFromHere[j]) { + tmp[j] = (tmp[j] + a[k]) % MOD; + } + } + + // Sanity checks based on symmetry of the keypad + assert tmp[1] == tmp[3]; + assert tmp[4] == tmp[6]; + assert tmp[7] == tmp[9]; + + a = tmp; + } + + long ans = 0; + for (long k : a) { + ans = (ans + k) % MOD; + } + + return (int) ans; + } + } +} diff --git a/src/test/java/com/fishercoder/_935Test.java b/src/test/java/com/fishercoder/_935Test.java new file mode 100644 index 0000000000..0b9ff3f99a --- /dev/null +++ b/src/test/java/com/fishercoder/_935Test.java @@ -0,0 +1,29 @@ +package com.fishercoder; + +import com.fishercoder.solutions._935; +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class _935Test { + private static _935.Solution1 solution1; + + @BeforeClass + public static void setup() { solution1 = new _935.Solution1(); } + + @Test + public void test1() { + assertEquals(solution1.knightDialer(1), 10); + } + + @Test + public void test2() { + assertEquals(solution1.knightDialer(2), 20); + } + + @Test + public void test3() { + assertEquals(solution1.knightDialer(3), 46); + } +}
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: