Redundant Connection
Problem Statement
Is problem mein, tree ek undirected graph hai jo connected hota hai aur jismein koi cycles nahi hoti.
Aapko ek graph diya gaya hai jo initially n nodes se shuru hota hai and ek additional edge add ki hai. Yeh graph ab ek aisa tree hai jismein ek extra edge added hai jise aapko identify karna hai aur remove karna hai taki resulting graph ek valid tree ban jaye.
Input:
Edges array: Ek array
edges
diya gaya hai jiska lengthn
hai aur har elementedges[i] = [ai, bi]
represent karta hai nodesai
aurbi
ke beech edge ko.
Objective:
Aapko ek edge return karna hai jo remove karne par graph phir se ek valid tree ban jaye jismein n nodes hon.
Agar multiple possible answers hain, return the edge that occurs last in the input.
Examples:
Example 1:
Input:
edges = [[1,2],[1,3],[2,3]]
Output:[2,3]
Explanation: Yeh graph initially connected tree hai with edges [1,2] aur [1,3]. Adding edge [2,3] se ek cycle create ho jati hai. Remove karte hain edge [2,3] taki graph phir se valid tree ban jaye.
Example 2:
Input:
edges = [[1,2],[2,3],[3,4],[1,4],[1,5]]
Output:[1,4]
Explanation: Yeh graph initially ek tree hai. Adding edge [1,4] se ek cycle create ho jati hai. Remove karte hain edge [1,4] taki graph phir se valid tree ban jaye.
Constraints:
n == edges.length
3 <= n <= 1000
edges[i].length == 2
1 <= ai < bi <= edges.length
ai != bi
There are no repeated edges.
The given graph is connected.
Redundant Connection
Is problem mein, aapko ek graph diya gaya hai jo initially connected tree tha, aur jismein koi cycles nahi thi. Aapko ek "redundant connection" yaani aisi edge find karni hai jo add hone par pehli baar cycle create kar deti hai. Matlab, humein aisi edge identify karni hai jo graph mein ek cycle complete kar deti hai.
Intuition
Initialize with Tree: Graph ko initially ek tree me represent kiya hai. Tree connectedhota hai and usme koi cycles nahi hoti.
Add Edge to Detect Cycle: Aapko ek additional edge add karne par graph me cycle detect karni hai.
Detect First Cycle-Completing Edge:
Union-Find Algorithm: Yeh ek common algorithm hai jo cycles detect karne mein madad karta hai. Is algorithm mein hum parent aur rank arrays ka use karke union operation perform karte hain.
Union Operation: Har edge ko graph mein add karte waqt, union operation use karte hain to check if they belong to same component.
Cycle Detection: Jab humein koi aisi edge milti hai jo union operation ke baad bhi same component mein hai, woh humari redundant edge hoti hai jo cycle complete karti hai. Approach
Time Complexity (Samay Jatilta):
Edge-by-Edge Checking: Har edge ke liye, humein check karna hota hai ki do nodes ke beech koi path hai ya nahi, using iterative traversal.
Worst-Case Traversal: Sabse badi jatilta wala case (worst case) mein yeh traversal sabhi nodes ko visit kar sakta hai, jo
O(V)
(V = number of nodes) hoga.Repeat for Each Edge: Yeh traversal har edge ke liye repeat hota hai, jo
O(E)
(E = number of edges) mein hota hai.Overall Time Complexity: Isliye, overall time complexity
O(E + V)
hoti hai, jahan E edges aur V nodes hai.
Space Complexity (Sthaan Jatilta):
Adjacency List: Graph ko store karne ke liye adjacency list use hoti hai jo
O(V + E)
space leti hai.Stack & Visited Set: Traversal ke waqt, stack aur visited set ko maintain karna hota hai jo
O(V)
space leta hai, kyunki yeh sab nodes ko track karta hai.Total Space Complexity: Isliye, total space complexity
O(V + E)
hoti hai.
Solution
class Solution {
findRedundantConnection(edges) {
const graph = new Map(); // Graph ko represent karta hai as a map
const isConnected = (u, v) => { // Check karte hain ki do nodes connected hain ya nahi
const visited = new Set(); // Visited nodes ko track karta hai
const stack = []; // DFS ke liye stack use karte hain
stack.push(u); // Start karte hain node 'u' se
while (stack.length > 0) { // Jab tak stack khali nahi hota
const node = stack.pop(); // Stack se node nikalte hain
if (visited.has(node)) continue; // Agar node visited hai to continue karte hain
visited.add(node); // Node ko visited set mein add karte hain
if (node === v) return true; // Agar node 'v' hai to return true
(graph.get(node) || []).forEach(neighbor => { // Har neighbor ko stack mein push karte hain
stack.push(neighbor);
});
}
return false; // Agar path nahi milta to return false
};
for (const [u, v] of edges) { // Har edge ko process karte hain
if (graph.has(u) && graph.has(v) && isConnected(u, v)) {
return [u, v]; // Agar cycle detect hoti hai to yeh edge return karte hain
}
if (!graph.has(u)) graph.set(u, []); // Agar node 'u' graph mein nahi hai to new entry add karte hain
if (!graph.has(v)) graph.set(v, []); // Agar node 'v' graph mein nahi hai to new entry add karte hain
graph.get(u).push(v); // Edge ko graph mein add karte hain
graph.get(v).push(u); // Reverse edge ko bhi add karte hain (undirected graph)
}
return []; // Agar koi redundant edge nahi milti to empty array return karte hain
}
}
Graph Representation:
Graph initialize:
graph
ekMap
object ke रूप में define kiya gaya hai. Yeh graph ko represent karta hai jahan har node ke saath uske neighbors (connected nodes) stored hain.javascriptconst graph = new Map();
Connectivity Check Function (isConnected
):
isConnected
function: Yeh function check karta hai ki do nodesu
aurv
connected hain ya nahi. Yeh DFS algorithm use karta hai using astack
.javascriptconst isConnected = (u, v) => { const visited = new Set(); // Visited nodes ko track karte hain const stack = []; // DFS ke liye stack use karte hain stack.push(u); // Start karte hain node 'u' se
DFS Traversal: Jab tak stack khali nahi hota, har node ko visit karte hain, aur agar
visited
set mein node already hai, usko skip kar dete hain. Agar current nodev
hai, totrue
return karte hain, yeh indicate karta hai ki nodes connected hain.javascriptwhile (stack.length > 0) { const node = stack.pop(); if (visited.has(node)) continue; visited.add(node); if (node === v) return true;
Neighbors Check: Har node ke neighbors ko stack mein push karte hain. Agar koi valid path nahi milta, to
false
return karte hain.javascript(graph.get(node) || []).forEach(neighbor => { stack.push(neighbor); }); return false; };
Main Function (findRedundantConnection
):
Edge Processing:
for
loop use karke har edge ko process karte hain. Agar dono nodesgraph
mein exist karte hain aurisConnected
functiontrue
return karta hai, to yeh edge redundant hai jo cycle complete karte hain.javascriptfor (const [u, v] of edges) { if (graph.has(u) && graph.has(v) && isConnected(u, v)) { return [u, v]; // Cycle detect hone par yeh edge return karte hain }
Add Edge to Graph: Agar nodes
graph
mein nahi hain, to nayi edges ko add karte hainMap
mein as new entries. Yeh undirected graph ke liye hota hai isliye har connection ke liye reverse connection bhi add karte hain.javascriptif (!graph.has(u)) graph.set(u, []); if (!graph.has(v)) graph.set(v, []); graph.get(u).push(v); graph.get(v).push(u);
Return Result: Agar koi redundant edge detect nahi hoti, to empty array return karte hain.
javascriptreturn []; }
Solution
class Solution {
public:
vector findRedundantConnection(vector>& edges) {
// Graph ko represent karne ke liye unordered_map use karte hain
unordered_map> graph;
// Connectivity check karne ke liye lambda function use karte hain
auto isConnected = [&](int u, int v) {
unordered_set visited; // Visited nodes ko track karte hain
stack stack; // DFS ke liye stack use karte hain
stack.push(u); // Start karte hain node 'u' se
while (!stack.empty()) { // Jab tak stack khali nahi hota
int node = stack.top(); // Stack ke top pe node ko lete hain
stack.pop(); // Node ko stack se nikaal dete hain
if (visited.count(node)) continue; // Agar node already visited hai to continue karte hain
visited.insert(node); // Node ko visited set mein add karte hain
if (node == v) return true; // Agar current node 'v' hai to return true
for (int neighbor : graph[node]) { // Har neighbor ko stack mein push karte hain
stack.push(neighbor);
}
}
return false; // Agar koi path nahi milta to return false
};
for (const auto& edge : edges) { // Har edge ko process karte hain
int u = edge[0], v = edge[1];
if (graph.count(u) && graph.count(v) && isConnected(u, v)) {
return edge; // Agar cycle detect hoti hai to yeh edge return karte hain
}
graph[u].push_back(v); // Node 'u' ko 'v' ke saath connect karte hain
graph[v].push_back(u); // Node 'v' ko 'u' ke saath connect karte hain
}
return {}; // Agar koi redundant edge nahi milti to return empty array
}
};
Graph Representation:
Graph initialize: Graph ko represent karne ke liye
unordered_map
use kiya gaya hai. Har node ke neighbors ko store kiya gaya hai, jaha node ke saath unke connected nodes stored hain.cppunordered_map<int, vector<int>> graph;
Connectivity Check Function (
isConnected
):isConnected
function: Yeh check karta hai ki do nodesu
aurv
connected hain ya nahi. Iske liye DFS (Depth-First Search) algorithm use kiya gaya hai using astack
.cppauto isConnected = [&](int u, int v) { unordered_set<int> visited; // Visited nodes ko track karte hain stack<int> stack; // DFS ke liye stack use karte hain stack.push(u); // Start karte hain node 'u' se
DFS Traversal: Jab tak stack khali nahi hota, har node ko stack se nikal kar visit karte hain. Agar wo node
visited
set mein pehle hi hai to usko skip kar dete hain. Agar current nodev
hai, to yeh returntrue
karega, yeh indicate karta hai kiu
aurv
connected hain.cppwhile (!stack.empty()) { int node = stack.top(); // Stack ke top pe node ko lete hain stack.pop(); // Node ko stack se nikaal dete hain if (visited.count(node)) continue; // Agar node already visited hai to continue karte hain visited.insert(node); // Node ko visited set mein add karte hain if (node == v) return true; // Agar current node 'v' hai to return true
Neighbors Check: Har node ke neighbors ko stack mein push karte hain taki unhe bhi check kiya ja sake. Agar koi valid path nahi milta to
false
return karte hain.cppfor (int neighbor : graph[node]) { // Har node ke neighbors ko stack mein push karte hain stack.push(neighbor); } return false; };
Main Function (
findRedundantConnection
):Edge Processing: Sari edges ko process karte hain. Agar dono nodes
graph
mein exist karte hain aurisConnected
functiontrue
return karta hai, iska matlab hai ki yeh edge redundant hai aur cycle complete kar rahi hai.cppfor (const auto& edge : edges) { // Har edge ko process karte hain int u = edge[0], v = edge[1]; if (graph.count(u) && graph.count(v) && isConnected(u, v)) { return edge; // Agar cycle detect hoti hai to yeh edge return karte hain }
Add Edge to Graph: Agar nodes
graph
mein exist nahi karte to nayi edges kounordered_map
mein add karte hain. Yeh undirected graph ke liye hota hai, isliye har connection ke liye reverse connection bhi add karte hain.cppgraph[u].push_back(v); // Node 'u' ko 'v' ke saath connect karte hain graph[v].push_back(u); // Node 'v' ko 'u' ke saath connect karte hain
Return Result: Agar koi redundant edge detect nahi hoti to empty array return karte hain.
cppreturn {}; }