Skip to content

Commit b60b914

Browse files
committed
[Function add]
1. Add leetcode solutions with tag graph.
1 parent c465d51 commit b60b914

5 files changed

+361
-1
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,7 @@
618618
* [576. Out of Boundary Paths](https://github.com/Seanforfun/Algorithm-and-Leetcode/blob/master/leetcode/576.%20Out%20of%20Boundary%20Paths.md)
619619
* [935. Knight Dialer](https://github.com/Seanforfun/Algorithm-and-Leetcode/blob/master/leetcode/935.%20Knight%20Dialer.md)
620620

621-
#### Graph
621+
### Graph
622622
* [133. Clone Graph](https://github.com/Seanforfun/Algorithm-and-Leetcode/blob/master/leetcode/133.%20Clone%20Graph.md)
623623
* [138. Copy List with Random Pointer](https://github.com/Seanforfun/Algorithm-and-Leetcode/blob/master/leetcode/138.%20Copy%20List%20with%20Random%20Pointer.md)
624624
* [200. Number of Islands](https://github.com/Seanforfun/Algorithm-and-Leetcode/blob/master/leetcode/200.%20Number%20of%20Islands.md)

leetcode/721. Accounts Merge.md

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
## 721. Accounts Merge
2+
3+
### Question:
4+
Given a list accounts, each element accounts[i] is a list of strings, where the first element accounts[i][0] is a name, and the rest of the elements are emails representing emails of the account.
5+
6+
Now, we would like to merge these accounts. Two accounts definitely belong to the same person if there is some email that is common to both accounts. Note that even if two accounts have the same name, they may belong to different people as people could have the same name. A person can have any number of accounts initially, but all of their accounts definitely have the same name.
7+
8+
After merging the accounts, return the accounts in the following format: the first element of each account is the name, and the rest of the elements are emails in sorted order. The accounts themselves can be returned in any order.
9+
10+
```
11+
Example 1:
12+
13+
Input:
14+
accounts = [["John", "johnsmith@mail.com", "john00@mail.com"], ["John", "johnnybravo@mail.com"], ["John", "johnsmith@mail.com", "john_newyork@mail.com"], ["Mary", "mary@mail.com"]]
15+
Output: [["John", 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com'], ["John", "johnnybravo@mail.com"], ["Mary", "mary@mail.com"]]
16+
Explanation:
17+
The first and third John's are the same person as they have the common email "johnsmith@mail.com".
18+
The second John and Mary are different people as none of their email addresses are used by other accounts.
19+
We could return these lists in any order, for example the answer [['Mary', 'mary@mail.com'], ['John', 'johnnybravo@mail.com'],
20+
['John', 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com']] would still be accepted.
21+
```
22+
23+
Note:
24+
* The length of accounts will be in the range [1, 1000].
25+
* The length of accounts[i] will be in the range [1, 10].
26+
* The length of accounts[i][j] will be in the range [1, 30].
27+
28+
29+
### Solution:
30+
* Method 1: Union find set beats 94%
31+
```Java
32+
class Solution {
33+
public List<List<String>> accountsMerge(List<List<String>> accounts) {
34+
Map<String, String> owner = new HashMap<>(); // key: e-mail value: name -> records which user it belongs to.
35+
Map<String, String> parent = new HashMap<>(); // key: email value: email
36+
Map<String, TreeSet<String>> uf = new HashMap<>();
37+
// Step 1: Initialization
38+
for(List<String> account : accounts){
39+
for(int i = 1; i < account.size(); i++){
40+
parent.put(account.get(i), account.get(i)); // each e-mails was initialized to point to themselves.
41+
owner.put(account.get(i), account.get(0)); // set onwer of each e-mail.
42+
}
43+
}
44+
// Step 2: Merge each lines
45+
for(List<String> account : accounts){
46+
String root = find(account.get(1), parent); // find the root e-mail for the first email and this one will be the root for this account.
47+
for(int i = 2; i < account.size(); i++){
48+
parent.put(find(account.get(i), parent), root); // find root for rest e-mails and merge them to the root.
49+
}
50+
}
51+
// Step 3: Add to uf.(Actually merge different lines)
52+
for(List<String> account : accounts){
53+
String root = find(account.get(1), parent); //// find the root e-mail for the first email.
54+
if(!uf.containsKey(root)) uf.put(root, new TreeSet<String>());
55+
for(int i = 1; i < account.size(); i++)
56+
uf.get(root).add(account.get(i)); // Add all emails in this account to uf.
57+
}
58+
// Step 4: Create result List.
59+
List<List<String>> result = new ArrayList<>();
60+
for(String key : uf.keySet()){
61+
List<String> temp = new ArrayList<>();
62+
temp.add(owner.get(uf.get(key).first())); // first add the username.
63+
temp.addAll(uf.get(key)); // Add all emails to the list.
64+
result.add(temp);
65+
}
66+
return result;
67+
}
68+
private String find(String s, Map<String, String> map){
69+
if(!map.get(s).equals(s)){
70+
map.put(s, find(map.get(s), map));
71+
}
72+
return map.get(s);
73+
}
74+
}
75+
```
76+
77+
### Reference
78+
1. [[Java/C++] Union Find](https://leetcode.com/problems/accounts-merge/discuss/109157/JavaC++-Union-Find)

leetcode/886. Possible Bipartition.md

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
## 886. Possible Bipartition
2+
3+
### Question:
4+
Given a set of N people (numbered 1, 2, ..., N), we would like to split everyone into two groups of any size.
5+
6+
Each person may dislike some other people, and they should not go into the same group.
7+
8+
Formally, if dislikes[i] = [a, b], it means it is not allowed to put the people numbered a and b into the same group.
9+
10+
Return true if and only if it is possible to split everyone into two groups in this way.
11+
12+
```
13+
Example 1:
14+
15+
Input: N = 4, dislikes = [[1,2],[1,3],[2,4]]
16+
Output: true
17+
Explanation: group1 [1,4], group2 [2,3]
18+
19+
Example 2:
20+
21+
Input: N = 3, dislikes = [[1,2],[1,3],[2,3]]
22+
Output: false
23+
24+
Example 3:
25+
26+
Input: N = 5, dislikes = [[1,2],[2,3],[3,4],[4,5],[1,5]]
27+
Output: false
28+
```
29+
30+
Note:
31+
* 1 <= N <= 2000
32+
* 0 <= dislikes.length <= 10000
33+
* 1 <= dislikes[i][j] <= N
34+
* dislikes[i][0] < dislikes[i][1]
35+
* There does not exist i != j for which dislikes[i] == dislikes[j].
36+
37+
### Solution:
38+
![Imgur](https://i.imgur.com/8aPdzPj.png)
39+
* Method 1: dfs + bopartite
40+
* we use the dfs to color the graph.
41+
* Current node is 1, and we need to color their neighbours to -1, and keep coloring.
42+
* If one node's color is filled and different from current color, this question cannot be solved.
43+
```Java
44+
class Solution {
45+
private Map<Integer, List<Integer>> graph;
46+
private int[] visited;
47+
public boolean possibleBipartition(int N, int[][] dislikes) {
48+
if(N == 0 || dislikes.length == 0) return true;
49+
graph = new HashMap<>();
50+
for(int[] dislike : dislikes){
51+
List<Integer> temp = graph.containsKey(dislike[0]) ? graph.get(dislike[0]): new ArrayList<>();
52+
temp.add(dislike[1]);
53+
graph.put(dislike[0], temp);
54+
temp = graph.containsKey(dislike[1]) ? graph.get(dislike[1]): new ArrayList<>();
55+
temp.add(dislike[0]);
56+
graph.put(dislike[1], temp);
57+
}
58+
visited = new int[N + 1];
59+
for(int i = 0; i < N; i++){
60+
if(visited[i] == 0){
61+
if(!dfs(i, 1)) return false;
62+
}
63+
}
64+
return true;
65+
}
66+
private boolean dfs(int node, int color){
67+
if(visited[node] != 0 && visited[node] != color) return false;
68+
if(visited[node] == color) return true;
69+
visited[node] = color;
70+
List<Integer> neighbours = graph.get(node);
71+
if(neighbours == null) return true;
72+
for(Integer neighbour : neighbours){
73+
if(!dfs(neighbour, -color)) return false;
74+
}
75+
return true;
76+
}
77+
}
78+
```
79+
80+
* Method 2: bfs
81+
* For all initialized node, we set it to 1 and add to queue.
82+
* for all neighbours, we check their neighbours color, if any one of them equals current one, return false.
83+
* Otherwise, we set it to -currentColor and save it to the queue.
84+
* Finally return true;
85+
```Java
86+
class Solution {
87+
public boolean possibleBipartition(int N, int[][] dislikes) {
88+
Map<Integer, List<Integer>> graph = new HashMap<>();
89+
for(int[] dislike : dislikes){
90+
List<Integer> temp = graph.containsKey(dislike[0]) ? graph.get(dislike[0]): new ArrayList<>();
91+
temp.add(dislike[1]);
92+
graph.put(dislike[0], temp);
93+
temp = graph.containsKey(dislike[1]) ? graph.get(dislike[1]): new ArrayList<>();
94+
temp.add(dislike[0]);
95+
graph.put(dislike[1], temp);
96+
}
97+
Queue<Integer> queue = new LinkedList<>();
98+
int[] visited = new int[N + 1];
99+
for(int i = 0; i < N; i++){
100+
if(visited[i] == 0){
101+
visited[i] = 1;
102+
queue.offer(i);
103+
while(!queue.isEmpty()){
104+
int cur = queue.poll();
105+
List<Integer> temp = graph.get(cur);
106+
if(temp == null) continue;
107+
for(Integer next : temp){
108+
if(visited[next] == visited[cur]) return false;
109+
if(visited[next] == 0){
110+
visited[next] = -visited[cur];
111+
queue.offer(next);
112+
}
113+
}
114+
}
115+
}
116+
}
117+
return true;
118+
}
119+
}
120+
```
121+
122+
### Reference
123+
1. [花花酱 LeetCode 886. Possible Bipartition](https://zxi.mytechroad.com/blog/graph/leetcode-886-possible-bipartition/)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
## 952. Largest Component Size by Common Factor
2+
3+
### Question:
4+
Given a non-empty array of unique positive integers A, consider the following graph:
5+
* There are A.length nodes, labelled A[0] to A[A.length - 1];
6+
* There is an edge between A[i] and A[j] if and only if A[i] and A[j] share a common factor greater than 1.
7+
8+
Return the size of the largest connected component in the graph.
9+
10+
```
11+
Example 1:
12+
13+
Input: [4,6,15,35]
14+
Output: 4
15+
16+
Example 2:
17+
18+
Input: [20,50,9,63]
19+
Output: 2
20+
21+
Example 3:
22+
23+
Input: [2,3,6,7,4,12,21,39]
24+
Output: 8
25+
```
26+
27+
Note:
28+
* 1 <= A.length <= 20000
29+
* 1 <= A[i] <= 100000
30+
31+
### Solution:
32+
* Method 1: Union find set
33+
```Java
34+
class Solution {
35+
private int[] uf;
36+
public int largestComponentSize(int[] A) {
37+
if(A == null || A.length == 0) return 0;
38+
int max = A[0];
39+
for(int i = 1; i < A.length; i++) max = Math.max(max, A[i]);
40+
this.uf = new int[max + 1];
41+
for(int i = 0; i < uf.length; i++) this.uf[i] = i;
42+
// For every number, find their factor and add to uf.
43+
for(int i = 0; i < A.length; i++){
44+
for(int j = 2; j <= (int)Math.sqrt(A[i]); j++){
45+
if(A[i] % j == 0){
46+
union(A[i], j);
47+
union(A[i], A[i] / j);
48+
}
49+
}
50+
}
51+
Map<Integer, Integer> map = new HashMap<>();
52+
int res = 1;
53+
for(int i = 0; i < A.length; i++){
54+
int root = find(A[i]);
55+
int cur = map.containsKey(root) ? map.get(root): 0;
56+
map.put(root, ++cur);
57+
res = Math.max(res, cur);
58+
}
59+
return res;
60+
}
61+
private void union(int i, int j){
62+
int p = find(i);
63+
int q = find(j);
64+
uf[p] = q;
65+
}
66+
private int find(int j){
67+
if(uf[j] != j){
68+
uf[j] = find(uf[j]);
69+
}
70+
return uf[j];
71+
}
72+
}
73+
```
74+
75+
### Reference
76+
1. [花花酱 LeetCode 952. Largest Component Size by Common Factor](https://zxi.mytechroad.com/blog/graph/leetcode-952-largest-component-size-by-common-factor/)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
## 990. Satisfiability of Equality Equations
2+
3+
### Question:
4+
Given an array equations of strings that represent relationships between variables, each string equations[i] has length 4 and takes one of two different forms: "a==b" or "a!=b". Here, a and b are lowercase letters (not necessarily different) that represent one-letter variable names.
5+
6+
Return true if and only if it is possible to assign integers to variable names so as to satisfy all the given equations.
7+
8+
```
9+
Example 1:
10+
11+
Input: ["a==b","b!=a"]
12+
Output: false
13+
Explanation: If we assign say, a = 1 and b = 1, then the first equation is satisfied, but not the second. There is no way to assign the variables to satisfy both equations.
14+
15+
Example 2:
16+
17+
Input: ["b==a","a==b"]
18+
Output: true
19+
Explanation: We could assign a = 1 and b = 1 to satisfy both equations.
20+
21+
Example 3:
22+
23+
Input: ["a==b","b==c","a==c"]
24+
Output: true
25+
26+
Example 4:
27+
28+
Input: ["a==b","b!=c","c==a"]
29+
Output: false
30+
31+
Example 5:
32+
33+
Input: ["c==c","b==d","x!=z"]
34+
Output: true
35+
```
36+
37+
Note:
38+
* 1 <= equations.length <= 500
39+
* equations[i].length == 4
40+
* equations[i][0] and equations[i][3] are lowercase letters
41+
* equations[i][1] is either '=' or '!'
42+
* equations[i][2] is '='
43+
44+
45+
### Solution:
46+
* Method 1: Union find set beats 100%
47+
```Java
48+
class Solution {
49+
private static final char EQ = '=';
50+
private static final char NOT_EQ = '!';
51+
private char[] uf;
52+
public boolean equationsPossible(String[] equations) {
53+
this.uf = new char[26];
54+
for(int i = 0; i < 26; i++) uf[i] = (char)(i + 'a');
55+
for(int i = 0; i < equations.length; i++){
56+
String eq = equations[i];
57+
if(eq.charAt(1) == EQ){ // Add to union find set
58+
union(eq.charAt(0), eq.charAt(3));
59+
}
60+
}
61+
for(int i = 0; i < equations.length; i++){
62+
String eq = equations[i];
63+
if(eq.charAt(1) == NOT_EQ){
64+
char a = find(eq.charAt(0));
65+
char b = find(eq.charAt(3));
66+
if(a == b) return false;
67+
}
68+
}
69+
return true;
70+
}
71+
private char find(char c){
72+
if(c != uf[c - 'a']){
73+
uf[c - 'a'] = find(uf[c - 'a']);
74+
}
75+
return uf[c - 'a'];
76+
}
77+
private void union(char a, char b){
78+
char p = find(a);
79+
char q = find(b);
80+
uf[p - 'a'] = q;
81+
}
82+
}
83+
```

0 commit comments

Comments
 (0)