Skip to content

Commit

Permalink
Merge branch '7oSkaaa:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
AhmedGamal2212 committed Apr 30, 2023
2 parents 67b61e0 + 2cff214 commit e7d0a17
Show file tree
Hide file tree
Showing 4 changed files with 306 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Author: Mahmoud Aboelsoud

class Solution {
public:
// Disjoint Set Union (DSU) data structure

vector<int> parent, set_size;

int find_set(int v){
if(v == parent[v]) return v;

return parent[v] = find_set(parent[v]);
}

void union_sets(int a, int b){
a = find_set(a);
b = find_set(b);
if(a != b){
if(set_size[a] < set_size[b])
swap(a, b);
parent[b] = a;
set_size[a] += set_size[b];
}
}

bool same_set(int a, int b){
a = find_set(a);
b = find_set(b);

return a == b;
}

// in this problem we need to know how many similar groups are there
// we can do that by brute force and check each pair of strings if they are similar or not
// and if they are similar we can merge them in the same group which will help us to know the number of groups at the end


int numSimilarGroups(vector<string>& strs) {
// n: number of strings
int n = strs.size();
// parent: parent of each string
parent.assign(n, 0);
// set_size: size of each set
set_size.assign(n, 1);

// initially each string is in its own set (group) and its parent is itself
for(int i = 0; i < n; i++)
parent[i] = i;


// we can check each pair of strings if they are similar or not and merge them in the same group if they are similar
for(int i = 0; i < n; i++){
for(int j = i + 1; j < n; j++){
// if they are not in the same group then we check if they are similar or not
if(!same_set(i, j)){
// cnt: number of different characters between the two strings
int cnt = 0;
// loop over the two strings and count the number of different characters and add a condition to break the loop if the number of different characters is more than 2
// because if the number of different characters is more than 2 then the two strings are not similar and we don't need to check the rest of the characters
for(int k = 0; k < strs[i].size() && cnt <= 2; k++)
cnt += (strs[i][k] != strs[j][k]);

// if the number of different characters is 0 or 2 then the two strings are similar and we merge them in the same group
if(cnt == 0 || cnt == 2) union_sets(i, j);
}
}
}

// st: set of parents of all strings
set<int> st;

// loop over all strings and insert their parents in the set
for(int i = 0; i < n ; i++)
st.insert(find_set(i));

// return the size of the set which is the number of groups
return st.size();
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Author: Osama Ayman
// Time: O(n*n*m)
// Space: O(n*n)
class Solution {
public int numSimilarGroups(String[] strs) {
// adjacency map to represent the graph
Map<Integer, List<Integer>> adj = new HashMap<>();
int n = strs.length;
// adding edges if they are similar
for(int i=0; i<n; i++){
for(int j=i+1; j<n; j++){
if(isSimilar(strs[i], strs[j])){
// adding undirected edge (bi-directional)
adj.computeIfAbsent(i, k -> new ArrayList<>()).add(j);
adj.computeIfAbsent(j, k -> new ArrayList<>()).add(i);
}
}
}
int connectedComponents = 0;
Set<Integer> vis = new HashSet<>();
for(int i=0; i<n; i++){
if(!vis.contains(i)){
connectedComponents++;
dfs(i, adj, vis);
}
}
return connectedComponents;
}
private void dfs(int node, Map<Integer, List<Integer>> adj, Set<Integer> vis){
if(vis.contains(node) || !adj.containsKey(node)) return;
vis.add(node);
for(int neigh: adj.get(node)){
dfs(neigh, adj, vis);
}
}
private boolean isSimilar(String s1, String s2){
char c1='.',c2='.';

for(int i=0; i<s1.length(); i++){
// if they are equal, continue
if(s1.charAt(i) == s2.charAt(i)) continue;
// if they are not equal and c1 is not set, set c1 and c2
if(c1=='.'){
c1=s1.charAt(i);
c2=s2.charAt(i);
}
// if they are equal and c1 and c2 are set, but they are not equal to the
//char of the other string, return false
else if(!(s1.charAt(i) == c2 && s2.charAt(i) == c1) ){
return false;
}


}
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Author: Ahmed Hossam

// Define a generic disjoint-set union data structure with an optional base node
// parameter for 1-based indexing, and a template parameter for data type T.
template <typename T = int, int Base = 1>
struct DSU {
// The parent vector stores the parent of each node, and the Gsize vector
// stores the size of each disjoint set.
vector<T> parent, Gsize;

// Constructor initializes the parent and Gsize vectors for all nodes.
DSU(int MaxNodes) {
parent = Gsize = vector<T>(MaxNodes + 5);
for (int i = Base; i <= MaxNodes; i++)
parent[i] = i, Gsize[i] = 1;
}

// Recursive function to find the leader of the disjoint set that the node
// belongs to, and updates the parent of all visited nodes to the leader.
T find_leader(int node) {
return parent[node] = (parent[node] == node ? node : find_leader(parent[node]));
}

// Returns true if the two nodes belong to the same disjoint set.
bool is_same_sets(int u, int v) {
return find_leader(u) == find_leader(v);
}

// Merges the disjoint sets containing the two nodes u and v.
void union_sets(int u, int v) {
int leader_u = find_leader(u), leader_v = find_leader(v);
if (leader_u == leader_v) return;
if (Gsize[leader_u] < Gsize[leader_v]) swap(leader_u, leader_v);
Gsize[leader_u] += Gsize[leader_v], parent[leader_v] = leader_u;
}

// Returns the size of the disjoint set that the node belongs to.
int get_size(int u) {
return Gsize[find_leader(u)];
}
};

class Solution {
public:
int maxNumEdgesToRemove(int n, vector<vector<int>>& edges) {
// Variable to store the number of edges removed.
int removed_edges = 0;
// Create two disjoint-set union objects, one for Alice and one for Bob.
DSU<int> alice(n), bob(n);
// Sort edges in decreasing order of type so that type 3 edges are
// processed last.
sort(edges.rbegin(), edges.rend());
// Loop through each edge in the sorted list.
for (auto& edge : edges) {
int t = edge[0], u = edge[1], v = edge[2];
// Process the edge based on its type.
if (t == 1) {
if (alice.is_same_sets(u, v)) removed_edges++;
else alice.union_sets(u, v);
} else if (t == 2) {
if (bob.is_same_sets(u, v)) removed_edges++;
else bob.union_sets(u, v);
} else {
if (alice.is_same_sets(u, v) && bob.is_same_sets(u, v)) removed_edges++;
else alice.union_sets(u, v), bob.union_sets(u, v);
}
}
// Check if all nodes belong to the same disjoint set for both Alice and
// Bob. If not, return -1 as it is impossible to remove enough edges to
// create a spanning tree for both players.
if (alice.get_size(1) != n || bob.get_size(1) != n)
return -1;
// Return the number of edges removed.
return removed_edges;
}
};
94 changes: 94 additions & 0 deletions 04- April/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
1. **[Add Digits](#26--add-digits)**
1. **[Bulb Switcher](#27--bulb-switcher)**
1. **[Similar String Groups](#28--similar-string-groups)**
1. **[Remove Max Number of Edges to Keep Graph Fully Traversable](#30--remove-max-number-of-edges-to-keep-graph-fully-traversable)**

<hr>
<br><br>
Expand Down Expand Up @@ -1631,4 +1632,97 @@ public:

};
```
<hr>
<br><br>
## 30) [Remove Max Number of Edges to Keep Graph Fully Traversable](https://leetcode.com/problems/remove-max-number-of-edges-to-keep-graph-fully-traversable/)
### Difficulty
![](https://img.shields.io/badge/Hard-red?style=for-the-badge)
### Related Topic
`Union Find` `Graph`
### Code
```cpp
// Define a generic disjoint-set union data structure with an optional base node
// parameter for 1-based indexing, and a template parameter for data type T.
template <typename T = int, int Base = 1>
struct DSU {
// The parent vector stores the parent of each node, and the Gsize vector
// stores the size of each disjoint set.
vector<T> parent, Gsize;
// Constructor initializes the parent and Gsize vectors for all nodes.
DSU(int MaxNodes) {
parent = Gsize = vector<T>(MaxNodes + 5);
for (int i = Base; i <= MaxNodes; i++)
parent[i] = i, Gsize[i] = 1;
}
// Recursive function to find the leader of the disjoint set that the node
// belongs to, and updates the parent of all visited nodes to the leader.
T find_leader(int node) {
return parent[node] = (parent[node] == node ? node : find_leader(parent[node]));
}
// Returns true if the two nodes belong to the same disjoint set.
bool is_same_sets(int u, int v) {
return find_leader(u) == find_leader(v);
}
// Merges the disjoint sets containing the two nodes u and v.
void union_sets(int u, int v) {
int leader_u = find_leader(u), leader_v = find_leader(v);
if (leader_u == leader_v) return;
if (Gsize[leader_u] < Gsize[leader_v]) swap(leader_u, leader_v);
Gsize[leader_u] += Gsize[leader_v], parent[leader_v] = leader_u;
}
// Returns the size of the disjoint set that the node belongs to.
int get_size(int u) {
return Gsize[find_leader(u)];
}
};
class Solution {
public:
int maxNumEdgesToRemove(int n, vector<vector<int>>& edges) {
// Variable to store the number of edges removed.
int removed_edges = 0;
// Create two disjoint-set union objects, one for Alice and one for Bob.
DSU<int> alice(n), bob(n);
// Sort edges in decreasing order of type so that type 3 edges are
// processed last.
sort(edges.rbegin(), edges.rend());
// Loop through each edge in the sorted list.
for (auto& edge : edges) {
int t = edge[0], u = edge[1], v = edge[2];
// Process the edge based on its type.
if (t == 1) {
if (alice.is_same_sets(u, v)) removed_edges++;
else alice.union_sets(u, v);
} else if (t == 2) {
if (bob.is_same_sets(u, v)) removed_edges++;
else bob.union_sets(u, v);
} else {
if (alice.is_same_sets(u, v) && bob.is_same_sets(u, v)) removed_edges++;
else alice.union_sets(u, v), bob.union_sets(u, v);
}
}
// Check if all nodes belong to the same disjoint set for both Alice and
// Bob. If not, return -1 as it is impossible to remove enough edges to
// create a spanning tree for both players.
if (alice.get_size(1) != n || bob.get_size(1) != n)
return -1;
// Return the number of edges removed.
return removed_edges;
}
};
```

0 comments on commit e7d0a17

Please sign in to comment.