From 3a21b7cf8fc77db8dc5eaaffd982600589c48cc0 Mon Sep 17 00:00:00 2001 From: 7oSkaaa Date: Fri, 28 Apr 2023 01:06:58 +0000 Subject: [PATCH 1/7] Add new daily problem --- .github/data/problems.json | 4 ++++ 04- April/28- Similar String Groups/.gitkeep | 0 2 files changed, 4 insertions(+) create mode 100644 04- April/28- Similar String Groups/.gitkeep diff --git a/.github/data/problems.json b/.github/data/problems.json index a867e1ce9..ada23e045 100644 --- a/.github/data/problems.json +++ b/.github/data/problems.json @@ -473,6 +473,10 @@ { "day": "27", "title": "Bulb Switcher" + }, + { + "day": "28", + "title": "Similar String Groups" } ] } \ No newline at end of file diff --git a/04- April/28- Similar String Groups/.gitkeep b/04- April/28- Similar String Groups/.gitkeep new file mode 100644 index 000000000..e69de29bb From bf206bfb9bc023708acfdfa29304424ab2e6ade0 Mon Sep 17 00:00:00 2001 From: aboelsoud Date: Fri, 28 Apr 2023 13:52:23 +0300 Subject: [PATCH 2/7] add the 28'th day problem solution --- ...ilar String Groups (Mahmoud Aboelsoud).cpp | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 04- April/28- Similar String Groups/28- Similar String Groups (Mahmoud Aboelsoud).cpp diff --git a/04- April/28- Similar String Groups/28- Similar String Groups (Mahmoud Aboelsoud).cpp b/04- April/28- Similar String Groups/28- Similar String Groups (Mahmoud Aboelsoud).cpp new file mode 100644 index 000000000..21682ccc0 --- /dev/null +++ b/04- April/28- Similar String Groups/28- Similar String Groups (Mahmoud Aboelsoud).cpp @@ -0,0 +1,79 @@ +// Author: Mahmoud Aboelsoud + +class Solution { +public: + // Disjoint Set Union (DSU) data structure + + vector 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& 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 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(); + } +}; From 3c67ca43cfd4f3e8b838cc6eb35f9b7bd70eb262 Mon Sep 17 00:00:00 2001 From: Osama Ayman Date: Fri, 28 Apr 2023 15:17:01 +0200 Subject: [PATCH 3/7] Added my sol to 28 April --- ...- Similar String Groups (Osama Ayman).java | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 04- April/28- Similar String Groups/28- Similar String Groups (Osama Ayman).java diff --git a/04- April/28- Similar String Groups/28- Similar String Groups (Osama Ayman).java b/04- April/28- Similar String Groups/28- Similar String Groups (Osama Ayman).java new file mode 100644 index 000000000..1c673abca --- /dev/null +++ b/04- April/28- Similar String Groups/28- Similar String Groups (Osama Ayman).java @@ -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> adj = new HashMap<>(); + int n = strs.length; + // adding edges if they are similar + for(int i=0; i new ArrayList<>()).add(j); + adj.computeIfAbsent(j, k -> new ArrayList<>()).add(i); + } + } + } + int connectedComponents = 0; + Set vis = new HashSet<>(); + for(int i=0; i> adj, Set 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 Date: Sat, 29 Apr 2023 00:32:46 +0000 Subject: [PATCH 4/7] Add new daily problem --- .github/data/problems.json | 4 ++++ .../.gitkeep | 0 2 files changed, 4 insertions(+) create mode 100644 04- April/29- Checking Existence of Edge Length Limited Paths/.gitkeep diff --git a/.github/data/problems.json b/.github/data/problems.json index ada23e045..acff9a3db 100644 --- a/.github/data/problems.json +++ b/.github/data/problems.json @@ -477,6 +477,10 @@ { "day": "28", "title": "Similar String Groups" + }, + { + "day": "29", + "title": "Checking Existence of Edge Length Limited Paths" } ] } \ No newline at end of file diff --git a/04- April/29- Checking Existence of Edge Length Limited Paths/.gitkeep b/04- April/29- Checking Existence of Edge Length Limited Paths/.gitkeep new file mode 100644 index 000000000..e69de29bb From 9e0c01ac36009647e7efea46c93dea467c386f71 Mon Sep 17 00:00:00 2001 From: 7oSkaaa Date: Sun, 30 Apr 2023 00:00:12 +0000 Subject: [PATCH 5/7] Add new daily problem --- .github/data/problems.json | 4 ++++ .../.gitkeep | 0 2 files changed, 4 insertions(+) create mode 100644 04- April/30- Remove Max Number of Edges to Keep Graph Fully Traversable/.gitkeep diff --git a/.github/data/problems.json b/.github/data/problems.json index acff9a3db..95f087c63 100644 --- a/.github/data/problems.json +++ b/.github/data/problems.json @@ -481,6 +481,10 @@ { "day": "29", "title": "Checking Existence of Edge Length Limited Paths" + }, + { + "day": "30", + "title": "Remove Max Number of Edges to Keep Graph Fully Traversable" } ] } \ No newline at end of file diff --git a/04- April/30- Remove Max Number of Edges to Keep Graph Fully Traversable/.gitkeep b/04- April/30- Remove Max Number of Edges to Keep Graph Fully Traversable/.gitkeep new file mode 100644 index 000000000..e69de29bb From 3dde15a42e6142d0f01d01eca4b8afa3b4547e10 Mon Sep 17 00:00:00 2001 From: Ahmed Hossam <63050133+7oSkaaa@users.noreply.github.com> Date: Sun, 30 Apr 2023 02:52:53 +0200 Subject: [PATCH 6/7] Create 30- Remove Max Number of Edges to Keep Graph Fully Traversable (Ahmed Hossam).cpp --- ...Graph Fully Traversable (Ahmed Hossam).cpp | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 04- April/30- Remove Max Number of Edges to Keep Graph Fully Traversable/30- Remove Max Number of Edges to Keep Graph Fully Traversable (Ahmed Hossam).cpp diff --git a/04- April/30- Remove Max Number of Edges to Keep Graph Fully Traversable/30- Remove Max Number of Edges to Keep Graph Fully Traversable (Ahmed Hossam).cpp b/04- April/30- Remove Max Number of Edges to Keep Graph Fully Traversable/30- Remove Max Number of Edges to Keep Graph Fully Traversable (Ahmed Hossam).cpp new file mode 100644 index 000000000..0ab163797 --- /dev/null +++ b/04- April/30- Remove Max Number of Edges to Keep Graph Fully Traversable/30- Remove Max Number of Edges to Keep Graph Fully Traversable (Ahmed Hossam).cpp @@ -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 +struct DSU { + // The parent vector stores the parent of each node, and the Gsize vector + // stores the size of each disjoint set. + vector parent, Gsize; + + // Constructor initializes the parent and Gsize vectors for all nodes. + DSU(int MaxNodes) { + parent = Gsize = vector(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>& 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 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; + } +}; From 2cff21483da0311e51b3a535ff13de8b7c800e84 Mon Sep 17 00:00:00 2001 From: 7oSkaaa Date: Sun, 30 Apr 2023 00:53:32 +0000 Subject: [PATCH 7/7] Add new daily problem to README --- 04- April/README.md | 94 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/04- April/README.md b/04- April/README.md index 10fcc20f1..0e2635750 100644 --- a/04- April/README.md +++ b/04- April/README.md @@ -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)**


@@ -1631,4 +1632,97 @@ public: }; ``` + +
+

+ +## 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 +struct DSU { + // The parent vector stores the parent of each node, and the Gsize vector + // stores the size of each disjoint set. + vector parent, Gsize; + + // Constructor initializes the parent and Gsize vectors for all nodes. + DSU(int MaxNodes) { + parent = Gsize = vector(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>& 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 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; + } +}; +``` \ No newline at end of file