-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathInfiniteLoopAroundTheDinnerTable.java
More file actions
171 lines (148 loc) · 7.51 KB
/
InfiniteLoopAroundTheDinnerTable.java
File metadata and controls
171 lines (148 loc) · 7.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/*
After the event, our company will take the students out for dinner.
The restaurant has a large round table that can fit the whole party.
We want to know if we can arrange the students so that the names of all students around the table form an “infinite loop.”
For each pair of neighboring students s1 and s2, the last letter of s1’s name must be identical to the first letter of s2’s name.
For example, “ALICE” and “ERIC” can sit together, but “ALICE” and “BOB” cannot.
Given an array of names, determine if it is possible to arrange the students at the round table in this way.
Input: an array of names. Each name contains capital letters only.
Output: true or false.
Example
Input: String[] = {“ALICE”, “CHARLES”, “ERIC”, “SOPHIA”}
Output: true
Analysis:
*/
import java.util.*;
public class InfiniteLoopAroundTheDinnerTable {
// Solution 1, dfs swap-swap, preferred, TC: O(n!) max, can be real small, SC: O(n)
public boolean isInfinite(String[] names) {
System.out.printf("%s : ", Arrays.toString(names));
if (names == null || names.length == 0) return false;
return dfs(1, names);
}
private boolean dfs(int idx, String[] names) {
if (idx == names.length)
return valid(names, idx - 1, 0);
for (int i = idx; i < names.length; i++) {
if (!valid(names, idx - 1, i)) continue;
if (i != idx) swap(names, i, idx);
if (dfs(idx + 1, names)) return true;
if (i != idx) swap(names, i, idx);
}
return false;
}
private void swap(String[] names, int i, int j) {
String tmp = names[i];
names[i] = names[j];
names[j] = tmp;
}
public boolean valid(String[] names, int i, int j) {
if (i < 0) return true;
return names[i].charAt(names[i].length() - 1) == names[j].charAt(0);
}
// Solution 2, dfs with set de-dup
public boolean isInfinite2(String[] names) {
System.out.printf("%s : ", Arrays.toString(names));
if (names == null || names.length == 0) return false;
Set<String> set = new HashSet<>();
String[] cur = new String[names.length];
return dfs2(0, cur, set, names);
}
private boolean dfs2(int idx, String[] cur, Set<String> set, String[] names) {
if (idx == cur.length)
return valid(cur, idx - 1, 0);
for (String s : names) {
if (!set.add(s)) continue;
cur[idx] = s;
if (!valid(cur, idx - 1, idx)) continue;
if (dfs2(idx + 1, cur, set, names)) return true;
set.remove(s);
}
return false;
}
// Solution 2 ends here
public void verifySolution2(String[] names) {
System.out.println(isInfinite(names) == isInfinite2(names));
}
public static void main(String[] args) {
InfiniteLoopAroundTheDinnerTable il = new InfiniteLoopAroundTheDinnerTable();
System.out.println(il.isInfinite(new String[]{"a", "bc", "c", "ddb", "cd", "da", "aad"}));
// System.out.println(il.isInfinite(l1));
// System.out.println(il.isInfinite(l2));
System.out.println(il.isInfinite(new String[]{"A"})); // true
System.out.println(il.isInfinite(new String[0])); // false
System.out.println(il.isInfinite(null)); // false
System.out.println(il.isInfinite(new String[]{"A", "B"})); // false
List<String> l1 = new ArrayList<>(Arrays.asList("ALICE", "CHARLES", "ERIC", "SOPHIA"));
List<String> l2 = new ArrayList<>(Arrays.asList("ALICE", "XRIC", "CHARLES", "SOPHIA"));
List<String> l3 = new ArrayList<>(Arrays.asList("AxB", "BxC", "CxD", "DxE", "ExF", "FxG", "GxA"));
System.out.println();
il.verifySolution2(new String[]{"A"}); // true
il.verifySolution2(new String[0]); // true
il.verifySolution2(null); // true
il.verifySolution2(new String[]{"A", "B"}); // true
il.verifySolution2(l1.toArray(new String[0]));
il.verifySolution2(l2.toArray(new String[0]));
System.out.println();
System.out.println(il.isInfinite(l1.toArray(new String[0]))); // true
System.out.println(il.isInfinite(l2.toArray(new String[0]))); // false
Collections.shuffle(l1);
System.out.println(il.isInfinite(l1.toArray(new String[0]))); // true
System.out.println();
il.verifySolution2(l1.toArray(new String[0]));
l1.set(0, "XXX");
System.out.println(il.isInfinite(l1.toArray(new String[0]))); // false
il.verifySolution2(l1.toArray(new String[0]));
il.verifySolution2(l3.toArray(new String[0]));
System.out.println();
System.out.println(il.isInfinite(l3.toArray(new String[0]))); // true
Collections.shuffle(l3);
il.verifySolution2(l3.toArray(new String[0]));
System.out.println(il.isInfinite(l3.toArray(new String[0]))); // true
Collections.shuffle(l3);
il.verifySolution2(l3.toArray(new String[0]));
System.out.println(il.isInfinite(l3.toArray(new String[0]))); // true
List<String> l5 = new ArrayList<>(Arrays.asList("AB", "BA", "A", "AC", "CA", "A", "A"));
il.verifySolution2(l5.toArray(new String[0]));
System.out.println(il.isInfinite(l5.toArray(new String[0])));
Collections.shuffle(l5);
il.verifySolution2(l5.toArray(new String[0]));
System.out.println(il.isInfinite(l5.toArray(new String[0])));
List<String> l4 = new ArrayList<>(Arrays.asList("AxB", "BxC", "CxD", "DxE", "ExF", "FxG", "GxH", "HxI", "IxJ", "JxK", "KxL", "LxM", "MxN", "NxO", "OxP", "PxQ", "QxR", "RxS", "SxT", "TxU", "UxV", "VxW", "WxX", "XxY", "YxZ", "ZxA"));
il.verifySolution2(l4.toArray(new String[0]));
System.out.println(il.isInfinite(l4.toArray(new String[0]))); // true
Collections.shuffle(l4);
il.verifySolution2(l4.toArray(new String[0]));
System.out.println(il.isInfinite(l4.toArray(new String[0]))); // true
Collections.shuffle(l4);
il.verifySolution2(l4.toArray(new String[0]));
System.out.println(il.isInfinite(l4.toArray(new String[0]))); // true
Collections.shuffle(l4);
il.verifySolution2(l4.toArray(new String[0]));
System.out.println(il.isInfinite(l4.toArray(new String[0]))); // true
Collections.shuffle(l4);
il.verifySolution2(l4.toArray(new String[0]));
System.out.println(il.isInfinite(l4.toArray(new String[0]))); // true
l4.set(0, "XXX");
l4.set(5, "YYY");
System.out.println(il.isInfinite(l4.toArray(new String[0]))); // false
il.verifySolution2(l4.toArray(new String[0]));
List<String> l6 = new ArrayList<>(Arrays.asList("AB", "BC", "CD", "DA"));
System.out.println(il.isInfinite(l6.toArray(new String[0])));
il.verifySolution2(l6.toArray(new String[0]));
Collections.shuffle(l6);
System.out.println(il.isInfinite(l6.toArray(new String[0])));
il.verifySolution2(l6.toArray(new String[0]));
}
}
/*
[ALICE, CHARLES, ERIC, SOPHIA] : true
[SOPHIA, CHARLES, ERIC, ALICE] : true
[XXX, ALICE, ERIC, CHARLES] : false
[AxB, BxC, CxD, DxE, ExF, FxG, GxA] : true
[DxE, FxG, GxA, AxB, BxC, CxD, ExF] : true
[BxC, DxE, GxA, ExF, CxD, FxG, AxB] : true
[AB, BA, A, AC, CA, A, A] : true
[BA, CA, A, A, A, AC, AB] : true
[AxB, BxC, CxD, DxE, ExF, FxG, GxH, HxI, IxJ, JxK, KxL, LxM, MxN, NxO, OxP, PxQ, QxR, RxS, SxT, TxU, UxV, VxW, WxX, XxY, YxZ, ZxA] : true
*/