Solution: Most Stones Removed with Same Row or Column
Let's solve the Most Stones Removed with Same Row or Column problem using the Union Find pattern.
Statement
Given an array of stones in a two-dimensional plane, where each stone is represented by a pair of x
and y
coordinates, find the maximum number of stones
we can remove with the following condition:
A stone can be removed if it shares either the same row or the same column with another stone that has not been removed so far.
Stones are provided as an array, stones
, of length , where represents the stone. Return the maximum possible number of stones
that can be removed.
Constraints:
-
stones.length
Solution
So far, you’ve probably brainstormed some approaches and have an idea of how to solve this problem. Let’s explore some of these approaches and figure out which one to follow based on considerations such as time and any implementation constraints.
Naive approach
The naive approach to solve this problem would be to iterate over the stones and try to remove each stone one by one. For each stone, we’ll check if it shares a row or column with another stone, and if it does, we remove the stone and increment a counter. In this approach, the order of removing the stones matters, so we will have to check all the combinations to reach the maximum number of stones we can remove.
We’ll get the solution, but the cost of achieving this is very high since the time complexity of this approach is . This is because we have to check for each stone against every other stone. Let’s try to devise an optimized solution for this problem.
Optimized solution using union find
To avoid the cost of processing one stone at a time, we can work with a group of stones instead. For this, we combine all the stones that share the same row or column into a single group. Then, in any of these groups, if we try to remove all the stones except for one, it won’t violate the problem’s condition because each row and column still retains at least one stone. This implies that the number of distinct groups corresponds to the number of stones that can’t be removed from the grid. Then, it would be safe to say that the maximum number of stones that can be removed equals the total number of stones minus the number of groups formed. These groups are connected components if we use the Union Find pattern to achieve this.
Using the Union method, we iterate through each stone and merge stones that share the same row or column into single connected components. After processing all the stones, we get the count of distinct connected components. Finally, we subtract this count from the total number of stones, indicating the maximum number that can be removed without violating the problem’s constraint.
The algorithm works as follows:
In the
UnionFind
class, we initialize the following:Two dictionaries,
parents
andranks
, to store the relevant information.union(x, y)
:This method takes
x
andy
coordinates of a stone and assigns each coordinate as a parent of itself in theparents
dictionary. It makes sure that the parent of the coordinate is updated only if it doesn't have an existing parent.Next, it merges the coordinates based on their rank values such that it attaches the lower rank coordinate to the higher rank coordinate. Otherwise, if both of the coordinates have the same rank, we choose either of the coordinates as the parent and attach the other coordinate to it.
While merging, if the current child coordinate is already merged with another coordinate, we recursively find their root parent using the
find()
method. We set the current parent coordinate as the parent of the root.To attach any coordinate,
c
, as a child to a parent coordinate,p
, we update theparents
dictionary and setparents[c] = p.
We also increment the rank of the parent coordinate,p
, by 1 in theranks
dictionary.
find(coordinate)
:This method takes a
coordinate
of a stone and returns its parent. It returns itself if the given coordinate is a parent of itself. Otherwise, it finds the parent of its parent recursively and returns it.
Iterate over the stones, and perform union by calling the
union()
function on all of the stones. This will form the groups and add them to theparents
dictionary. Sincex
andy
can have the same values, e.g., [0,0] or [1,1], an offset value is added to the coordinatey
to avoid any possible clash in theparents
andranks
dictionaries.To get the number of groups, we find the root parent of each element of the
parents
dictionary using thefind()
method.In the end, we return the difference between the number of stones and the number of
groups
made.
Let’s look at the following illustration to get a better understanding of the solution:
Let’s try to implement the algorithm as discussed above:
import java.util.*;class RemoveStones {public static int removeStones(int[][] stones) {int offset = 100000;UnionFind stone = new UnionFind();for (int[] s : stones) {int x = s[0];int y = s[1];stone.union(x, y + offset);}Set<Integer> groups = new HashSet<>();Map<Integer, Integer> parents = stone.getParents();for (Map.Entry<Integer, Integer> entry : parents.entrySet()) {groups.add(stone.find(entry.getKey()));}return stones.length - groups.size();}// Driver codepublic static void main(String[] args) {int[][][] stones = {{{0, 0}, {0, 1}, {1, 2}, {2, 2}, {3, 3}},{{0, 0}, {2, 2}, {3, 3}},{{0, 1}, {2, 1}, {3, 0}},{{1, 0}, {2, 1}, {2, 3}, {3, 1}, {3, 3}},{{1, 2}, {2, 0}, {2, 2}, {3, 3}}};for (int i = 0; i < stones.length; i++) {System.out.println((i + 1) + ".\tMaximum stones which can be removed from " +Arrays.deepToString(stones[i]) + " are: " + removeStones(stones[i]));System.out.println(String.join("", Collections.nCopies(100, "-")));}}}
Solution summary
To recap, the solution to this problem can be divided into the following three parts:
-
Iterate over all the stones, and use the
union()
function to check if they share a row or column with other stones. Merge the stones into one group if they share a row or column. -
Use the
find()
function to get the number ofgroups
to which the stones belong. -
Return the difference between the number of
stones
and the number ofgroups
made.
Time complexity
The time complexity of this solution is , where is the number of coordinates given in input, and is the time taken for performing union by rank and path compression. is almost constant time and grows very slowly with the input size.
Therefore, the overall time complexity becomes .
Space complexity
The space complexity is , where is the number of coordinates.
Level up your interview prep. Join Educative to access 70+ hands-on prep courses.