|
| 1 | +package com.fishercoder.solutions; |
| 2 | + |
| 3 | +/** |
| 4 | + * 488. Zuma Game |
| 5 | + * |
| 6 | + * Think about Zuma Game. You have a row of balls on the table, colored red(R), yellow(Y), blue(B), green(G), and white(W). |
| 7 | + * You also have several balls in your hand. |
| 8 | +
|
| 9 | + Each time, you may choose a ball in your hand, and insert it into the row (including the leftmost place and rightmost place). |
| 10 | + Then, if there is a group of 3 or more balls in the same color touching, remove these balls. Keep doing this until no more balls can be removed. |
| 11 | +
|
| 12 | + Find the minimal balls you have to insert to remove all the balls on the table. If you cannot remove all the balls, output -1. |
| 13 | +
|
| 14 | + Examples: |
| 15 | +
|
| 16 | + Input: "WRRBBW", "RB" |
| 17 | + Output: -1 |
| 18 | + Explanation: WRRBBW -> WRR[R]BBW -> WBBW -> WBB[B]W -> WW |
| 19 | +
|
| 20 | + Input: "WWRRBBWW", "WRBRW" |
| 21 | + Output: 2 |
| 22 | + Explanation: WWRRBBWW -> WWRR[R]BBWW -> WWBBWW -> WWBB[B]WW -> WWWW -> empty |
| 23 | +
|
| 24 | + Input:"G", "GGGGG" |
| 25 | + Output: 2 |
| 26 | + Explanation: G -> G[G] -> GG[G] -> empty |
| 27 | +
|
| 28 | + Input: "RBYYBBRRB", "YRBGB" |
| 29 | + Output: 3 |
| 30 | + Explanation: RBYYBBRRB -> RBYY[Y]BBRRB -> RBBBRRB -> RRRB -> B -> B[B] -> BB[B] -> empty |
| 31 | +
|
| 32 | + Note: |
| 33 | +
|
| 34 | + You may assume that the initial row of balls on the table won’t have any 3 or more consecutive balls with the same color. |
| 35 | + The number of balls on the table won't exceed 20, and the string represents these balls is called "board" in the input. |
| 36 | + The number of balls in your hand won't exceed 5, and the string represents these balls is called "hand" in the input. |
| 37 | + Both input strings will be non-empty and only contain characters 'R','Y','B','G','W'. |
| 38 | + */ |
| 39 | +public class _488 { |
| 40 | + |
| 41 | + /**credit: https://discuss.leetcode.com/topic/79820/short-java-solution-beats-98 |
| 42 | + * Two layer of recursion, pretty cool!*/ |
| 43 | + |
| 44 | + int MAXCOUNT = 6; // the max balls you need will not exceed 6 since "The number of balls in your hand won't exceed 5" |
| 45 | + |
| 46 | + public int findMinStep(String board, String hand) { |
| 47 | + int[] handCount = new int[26]; |
| 48 | + for (int i = 0; i < hand.length(); ++i) { |
| 49 | + ++handCount[hand.charAt(i) - 'A']; |
| 50 | + } |
| 51 | + int result = dfs(board + "#", handCount); // append a "#" to avoid special process while j==board.length, make the code shorter. |
| 52 | + return result == MAXCOUNT ? -1 : result; |
| 53 | + } |
| 54 | + private int dfs(String s, int[] handCount) { |
| 55 | + s = removeConsecutive(s); |
| 56 | + if (s.equals("#")) return 0; |
| 57 | + int result = MAXCOUNT; |
| 58 | + int need = 0; |
| 59 | + for (int i = 0, j = 0 ; j < s.length(); ++j) { |
| 60 | + if (s.charAt(j) == s.charAt(i)) continue; |
| 61 | + need = 3 - (j - i); //balls need to remove current consecutive balls. |
| 62 | + if (handCount[s.charAt(i) - 'A'] >= need) { |
| 63 | + handCount[s.charAt(i) - 'A'] -= need; |
| 64 | + result = Math.min(result, need + dfs(s.substring(0, i) + s.substring(j), handCount)); |
| 65 | + handCount[s.charAt(i) - 'A'] += need; |
| 66 | + } |
| 67 | + i = j; |
| 68 | + } |
| 69 | + return result; |
| 70 | + } |
| 71 | + |
| 72 | + //remove consecutive balls longer than 3 |
| 73 | + private String removeConsecutive(String board) { |
| 74 | + for (int i = 0, j = 0; j < board.length(); ++j) { |
| 75 | + if (board.charAt(j) == board.charAt(i)) continue; |
| 76 | + if (j - i >= 3) return removeConsecutive(board.substring(0, i) + board.substring(j)); |
| 77 | + else i = j; |
| 78 | + } |
| 79 | + return board; |
| 80 | + } |
| 81 | +} |
0 commit comments