|
1 | 1 | package g0401_0500.s0488_zuma_game;
|
2 | 2 |
|
3 | 3 | // #Hard #String #Dynamic_Programming #Breadth_First_Search #Memoization
|
4 |
| -// #2022_04_15_Time_2077_ms_(7.41%)_Space_42.5_MB_(77.78%) |
| 4 | +// #2022_07_13_Time_1989_ms_(32.79%)_Space_56.5_MB_(81.97%) |
5 | 5 |
|
6 |
| -import java.util.ArrayList; |
7 |
| -import java.util.HashSet; |
8 |
| -import java.util.List; |
9 |
| -import java.util.Set; |
| 6 | +import java.util.HashMap; |
| 7 | +import java.util.Stack; |
10 | 8 |
|
11 |
| -@SuppressWarnings("java:S135") |
12 | 9 | public class Solution {
|
13 |
| - public int findMinStep(String board, String hand) { |
14 |
| - List<Character> boardList = new ArrayList<>(); |
15 |
| - for (char c : board.toCharArray()) { |
16 |
| - boardList.add(c); |
17 |
| - } |
18 |
| - List<Character> handList = new ArrayList<>(); |
19 |
| - for (char c : hand.toCharArray()) { |
20 |
| - handList.add(c); |
21 |
| - } |
22 |
| - return findMinStep(boardList, handList); |
23 |
| - } |
| 10 | + private HashMap<String, Integer> map = new HashMap<>(); |
24 | 11 |
|
25 |
| - private int findMinStep(List<Character> boardList, List<Character> handList) { |
26 |
| - if (boardList.isEmpty()) { |
27 |
| - return 0; |
28 |
| - } |
29 |
| - if (handList.isEmpty()) { |
30 |
| - return -1; |
31 |
| - } |
32 |
| - if (!isValid(boardList, handList)) { |
33 |
| - return -1; |
34 |
| - } |
35 |
| - int res = Integer.MAX_VALUE; |
36 |
| - for (int boardListIndex = 0; boardListIndex <= boardList.size(); boardListIndex++) { |
37 |
| - Set<Character> duplicate = new HashSet<>(); |
38 |
| - for (int handListIndex = 0; handListIndex < handList.size(); handListIndex++) { |
39 |
| - if (boardListIndex > 0 |
40 |
| - && boardList.get(boardListIndex - 1).equals(handList.get(handListIndex))) { |
41 |
| - continue; |
42 |
| - } |
43 |
| - if (duplicate.contains(handList.get(handListIndex))) { |
44 |
| - continue; |
| 12 | + private String removeConsecutiveThreeOrMoreBalls(String board) { |
| 13 | + Stack<Character> st = new Stack<>(); |
| 14 | + int n = board.length(); |
| 15 | + for (int i = 0; i < n; i++) { |
| 16 | + char ch = board.charAt(i); |
| 17 | + st.push(ch); |
| 18 | + if (st.size() >= 3 && (i == n - 1 || ch != board.charAt(i + 1))) { |
| 19 | + char a = st.pop(); |
| 20 | + char b = st.pop(); |
| 21 | + char c = st.pop(); |
| 22 | + if (a == b && b == c) { |
| 23 | + while (!st.isEmpty() && st.peek() == a) { |
| 24 | + st.pop(); |
| 25 | + } |
45 | 26 | } else {
|
46 |
| - duplicate.add(handList.get(handListIndex)); |
47 |
| - } |
48 |
| - boolean goodCase1 = |
49 |
| - (boardListIndex < boardList.size() |
50 |
| - && boardList |
51 |
| - .get(boardListIndex) |
52 |
| - .equals(handList.get(handListIndex))); |
53 |
| - boolean goodCase2 = |
54 |
| - (boardListIndex > 0 |
55 |
| - && boardListIndex < boardList.size() |
56 |
| - && boardList |
57 |
| - .get(boardListIndex - 1) |
58 |
| - .equals(boardList.get(boardListIndex)) |
59 |
| - && !boardList |
60 |
| - .get(boardListIndex - 1) |
61 |
| - .equals(handList.get(handListIndex))); |
62 |
| - if (!goodCase1 && !goodCase2) { |
63 |
| - continue; |
64 |
| - } |
65 |
| - List<Character> boardListClone = new ArrayList<>(boardList); |
66 |
| - List<Character> handListClone = new ArrayList<>(handList); |
67 |
| - boardListClone.add(boardListIndex, handListClone.remove(handListIndex)); |
68 |
| - cleanup(boardListClone); |
69 |
| - int preRes = findMinStep(boardListClone, handListClone); |
70 |
| - if (preRes != -1 && preRes < res) { |
71 |
| - res = preRes; |
| 27 | + st.push(c); |
| 28 | + st.push(b); |
| 29 | + st.push(a); |
72 | 30 | }
|
73 | 31 | }
|
74 | 32 | }
|
75 |
| - |
76 |
| - if (res == Integer.MAX_VALUE) { |
77 |
| - return -1; |
| 33 | + StringBuilder res = new StringBuilder(); |
| 34 | + while (!st.isEmpty()) { |
| 35 | + res.append(st.pop()); |
78 | 36 | }
|
79 |
| - return res + 1; |
| 37 | + return res.reverse().toString(); |
80 | 38 | }
|
81 | 39 |
|
82 |
| - public void cleanup(List<Character> boardList) { |
83 |
| - boolean isCleanup = false; |
84 |
| - while (!isCleanup) { |
85 |
| - isCleanup = true; |
86 |
| - for (int i = 0; i < boardList.size() - 2; i++) { |
87 |
| - int repeatLen = 1; |
88 |
| - for (int j = i + 1; j < boardList.size(); j++) { |
89 |
| - if (boardList.get(j).equals(boardList.get(j - 1))) { |
90 |
| - repeatLen++; |
91 |
| - } else { |
92 |
| - break; |
93 |
| - } |
94 |
| - } |
95 |
| - if (repeatLen >= 3) { |
96 |
| - isCleanup = false; |
97 |
| - for (; repeatLen > 0; repeatLen--) { |
98 |
| - boardList.remove(i); |
99 |
| - } |
100 |
| - } |
101 |
| - } |
102 |
| - } |
| 40 | + private String ss(String s, int i, int j) { |
| 41 | + return s.substring(i, j); |
103 | 42 | }
|
104 | 43 |
|
105 |
| - public boolean isValid(List<Character> boardList, List<Character> handList) { |
106 |
| - int boardR = 0; |
107 |
| - int boardY = 0; |
108 |
| - int boardB = 0; |
109 |
| - int boardG = 0; |
110 |
| - int boardW = 0; |
111 |
| - int handR = 0; |
112 |
| - int handY = 0; |
113 |
| - int handB = 0; |
114 |
| - int handG = 0; |
115 |
| - int handW = 0; |
116 |
| - for (char c : boardList) { |
117 |
| - if (c == 'R') { |
118 |
| - boardR++; |
119 |
| - } |
120 |
| - if (c == 'Y') { |
121 |
| - boardY++; |
122 |
| - } |
123 |
| - if (c == 'B') { |
124 |
| - boardB++; |
125 |
| - } |
126 |
| - if (c == 'G') { |
127 |
| - boardG++; |
128 |
| - } |
129 |
| - if (c == 'W') { |
130 |
| - boardW++; |
131 |
| - } |
132 |
| - } |
133 |
| - for (char c : handList) { |
134 |
| - if (c == 'R') { |
135 |
| - handR++; |
136 |
| - } |
137 |
| - if (c == 'Y') { |
138 |
| - handY++; |
139 |
| - } |
140 |
| - if (c == 'B') { |
141 |
| - handB++; |
142 |
| - } |
143 |
| - if (c == 'G') { |
144 |
| - handG++; |
145 |
| - } |
146 |
| - if (c == 'W') { |
147 |
| - handW++; |
148 |
| - } |
149 |
| - } |
150 |
| - if (boardR < 3 && boardR > 0 && boardR + handR < 3) { |
151 |
| - return false; |
| 44 | + private int solve(String board, String hand) { |
| 45 | + String key = board + "#" + hand; |
| 46 | + if (map.containsKey(key)) { |
| 47 | + return map.get(key); |
152 | 48 | }
|
153 |
| - if (boardY < 3 && boardY > 0 && boardY + handY < 3) { |
154 |
| - return false; |
| 49 | + board = removeConsecutiveThreeOrMoreBalls(board); |
| 50 | + int ans = 100, n = board.length(), m = hand.length(); |
| 51 | + if (n == 0 || m == 0) { |
| 52 | + map.put(key, n == 0 ? 0 : 100); |
| 53 | + return n == 0 ? 0 : 100; |
155 | 54 | }
|
156 |
| - if (boardB < 3 && boardB > 0 && boardB + handB < 3) { |
157 |
| - return false; |
158 |
| - } |
159 |
| - if (boardG < 3 && boardG > 0 && boardG + handG < 3) { |
160 |
| - return false; |
| 55 | + for (int i = 0; i < hand.length(); i++) { |
| 56 | + for (int j = 0; j < n; j++) { |
| 57 | + if (board.charAt(j) == hand.charAt(i) |
| 58 | + || (j < n - 1 && board.charAt(j) == board.charAt(j + 1))) { |
| 59 | + ans = |
| 60 | + Math.min( |
| 61 | + ans, |
| 62 | + 1 |
| 63 | + + solve( |
| 64 | + ss(board, 0, j + 1) |
| 65 | + + hand.charAt(i) |
| 66 | + + ss(board, j + 1, n), |
| 67 | + ss(hand, 0, i) + ss(hand, i + 1, m))); |
| 68 | + } |
| 69 | + } |
161 | 70 | }
|
162 |
| - return boardW >= 3 || boardW <= 0 || boardW + handW >= 3; |
| 71 | + map.put(key, ans); |
| 72 | + return ans; |
| 73 | + } |
| 74 | + |
| 75 | + public int findMinStep(String board, String hand) { |
| 76 | + int ans = solve(board, hand); |
| 77 | + return ans >= 100 ? -1 : ans; |
163 | 78 | }
|
164 | 79 | }
|
0 commit comments