|
| 1 | +# 🔥 Union-Find 🔥 || Simple Fast and Easy || with Explanation 😈 |
| 2 | + |
| 3 | +The code provided aims to solve a problem of finding the length of the longest subarray with the maximum number of 1s, with the allowance of flipping at most one 0 to a 1. |
| 4 | + |
| 5 | +Let's go through the code step by step and explain its functionality: |
| 6 | + |
| 7 | +## DisjointSet Class |
| 8 | + |
| 9 | +- The `DisjointSet` class represents the disjoint-set data structure. |
| 10 | +- It has two instance variables: `parent` and `size`. |
| 11 | +- The `parent` list maintains the parent of each element, and the `size` list stores the size of each set. |
| 12 | +- The constructor `DisjointSet(int n)` initializes the `size` and `parent` lists with size `n+1` and sets each element's parent as itself. |
| 13 | +- The `findParent(int node)` method implements the find operation of the disjoint-set data structure. It uses path compression optimization to flatten the tree structure and returns the parent of the given `node`. |
| 14 | +- The `unionBySize(int u, int v)` method performs the union operation of the disjoint-set data structure. It finds the parents of `u` and `v`, and if they are different, it merges the smaller set into the larger set and updates the size accordingly. |
| 15 | + |
| 16 | +## Solution Class |
| 17 | + |
| 18 | +- The `Solution` class contains the `longestSubarray` method that takes a list of integers `nums` as input and returns the length of the longest subarray. |
| 19 | +- It initializes the variable `s` as the sum of all elements in `nums`. |
| 20 | +- If `s` is equal to the length of `nums`, it means all elements are 1, so it returns `s - 1` (since we can flip at most one 0 to a 1). |
| 21 | +- If `s` is equal to 1 or 0, it means all elements are 0 or all elements are already 1, respectively, so it returns `s`. |
| 22 | +- It creates an instance of the `DisjointSet` class called `ds` with the length of `nums`. |
| 23 | +- It iterates through the `nums` list from index 0 to `n-1` and performs union operations for adjacent 1s in the `ds` disjoint set. |
| 24 | +- It then iterates through the `nums` list from index 1 to `n-1` and checks for 0s to calculate the length of the longest subarray. |
| 25 | +- Inside this loop, if the current element is 0, it calculates the sum of sizes of adjacent sets that contain 1s. |
| 26 | +- It updates the `ans` variable with the maximum length of the subarray obtained so far. |
| 27 | +- Finally, it compares `ans` with the size of the root set (representing the count of 1s without any 0 flips) and returns the maximum value between them. |
| 28 | + |
| 29 | +### Time Complexity Analysis |
| 30 | + |
| 31 | +The time complexity of the code is O(n), where n is the length of the input list `nums`. This complexity arises due to the two iterations over the `nums` list. Both iterations have linear time complexity. |
| 32 | + |
| 33 | +### Space Complexity Analysis |
| 34 | + |
| 35 | +The space complexity of the code is O(n). This is because the `DisjointSet` class uses two lists, `parent` and `size`, each with a length of `n+1`. Additionally, a few auxiliary variables are used, but their space requirements are negligible compared to the `DisjointSet` arrays. |
| 36 | + |
| 37 | +In conclusion, the code utilizes the Union-Find (Disjoint-Set) algorithm to solve the problem efficiently. It has a time complexity of O(n) and a space complexity of O(n). |
| 38 | + |
| 39 | +```dart |
| 40 | +class DisjointSet { |
| 41 | + late List<int> parent; |
| 42 | + late List<int> size; |
| 43 | +
|
| 44 | + DisjointSet(int n) { |
| 45 | + size = List<int>.filled(n + 1, 1); |
| 46 | + parent = List<int>.filled(n + 1, 0); |
| 47 | +
|
| 48 | + for (int i = 0; i <= n; ++i) parent[i] = i; |
| 49 | + } |
| 50 | +
|
| 51 | + int findParent(int node) { |
| 52 | + if (parent[node] == node) return node; |
| 53 | + return parent[node] = findParent(parent[node]); |
| 54 | + } |
| 55 | +
|
| 56 | + void unionBySize(int u, int v) { |
| 57 | + int pU = findParent(u); |
| 58 | + int pV = findParent(v); |
| 59 | +
|
| 60 | + if (pU == pV) return; |
| 61 | +
|
| 62 | + if (size[pU] < size[pV]) { |
| 63 | + parent[pU] = pV; |
| 64 | + size[pV] += size[pU]; |
| 65 | + } else { |
| 66 | + parent[pV] = pU; |
| 67 | + size[pU] += size[pV]; |
| 68 | + } |
| 69 | + } |
| 70 | +} |
| 71 | +
|
| 72 | +class Solution { |
| 73 | + int longestSubarray(List<int> nums) { |
| 74 | + final int n = nums.length; |
| 75 | + int s = 0; |
| 76 | +
|
| 77 | + for (final int x in nums) s += x; |
| 78 | + if (s == n) return s - 1; |
| 79 | + if (s == 1 || s == 0) return s; |
| 80 | +
|
| 81 | + final DisjointSet ds = DisjointSet(n); |
| 82 | +
|
| 83 | + for (int i = 0; i < n - 1; ++i) { |
| 84 | + if (nums[i] == 1) { |
| 85 | + if (nums[i + 1] == 1) { |
| 86 | + if (ds.findParent(i) != ds.findParent(i + 1)) { |
| 87 | + ds.unionBySize(i, i + 1); |
| 88 | + } |
| 89 | + } |
| 90 | + } |
| 91 | + } |
| 92 | +
|
| 93 | + int ans = 0; |
| 94 | + for (int i = 1; i < n - 1; ++i) { |
| 95 | + if (nums[i] == 0) { |
| 96 | + int tSum = 0; |
| 97 | + if (nums[i - 1] == 1) { |
| 98 | + tSum += ds.size[ds.parent[i - 1]]; |
| 99 | + } |
| 100 | + if (nums[i + 1] == 1) { |
| 101 | + tSum += ds.size[ds.parent[i + 1]]; |
| 102 | + } |
| 103 | + ans = tSum > ans ? tSum : ans; |
| 104 | + } |
| 105 | + } |
| 106 | +
|
| 107 | + ans = ans > ds.size[0] ? ans : ds.size[0]; |
| 108 | + return ans; |
| 109 | + } |
| 110 | +} |
| 111 | +``` |
0 commit comments