力扣:移除最多的同行或同列石头

题目描述


n 块石头放置在二维平面中的一些整数坐标点上。每个坐标点上最多只能有一块石头。
如果一块石头的 同行或者同列 上有其他石头存在,那么就可以移除这块石头。
给你一个长度为 n 的数组 stones ,其中 stones [ i ] = [ xi , yi ] 表示第 i 块石头的位置,返回 可以移除的石子 的最大数量。
力扣:947. 移除最多的同行或同列石头

输入:stones = [ [ 0 , 0 ] , [ 0 , 1 ] , [ 1 ,0 ] , [ 1 , 2 ] , [ 2 , 1 ] , [ 2 , 2 ] ]
输出:5
解释:一种移除 5 块石头的方法如下所示:
1、 移除石头 [ 2 , 2 ] ,因为它和 [ 2 , 1 ] 同行。
2、移除石头 [ 2 , 1 ] ,因为它和 [ 0 , 1 ] 同列。
3、移除石头 [ 1 , 2 ] ,因为它和 [ 1 , 0 ] 同行。
4、移除石头 [ 1 , 0 ] ,因为它和 [ 0 , 0 ] 同列。
5、移除石头 [ 0 , 1 ] ,因为它和 [ 0 , 0 ] 同行。
石头 [ 0 , 0 ] 不能移除,因为它没有与另一块石头同行/列。

题目分析


并查集模板题应用

class Solution {
    int maxn = 20005; //根据坐标范围而定
    int[] father = new int[maxn];

    // 并查集初始化
    public void init(){
        Arrays.fill(father , -1);
    }

    // 并查集里寻根的过程
    public int find(int u){
        return father[u] == -1 ? u : find(father[u]);
    }

    // 将 v -> u 这条边加入并查集
    public void union(int u , int v){
        int rootu = find(u);
        int rootv = find(v);
        if(rootu != rootv){
            father[rootv] = rootu;
        }
    }

    // 判断 u 和 v 是否找到同一个根
    public boolean same(int u , int v){
        return find(u) == find(v);
    }

    public int removeStones(int[][] stones) {
        init();
        for(int[] stone : stones){
            union(stone[0] , stone[1] + 10000);
        }
        Map<Integer , Boolean>  umap = new HashMap<>();
        for(int[] stone : stones){
            umap.put(find(stone[0]) , true);
            umap.put(find(stone[1] + 10000) , true);
        }
        return stones.length - umap.size();
    }
}
力扣上的“盛最多水的容器”是一道经典的算法题,主要考察双指针技巧的应用。题目描述大致为:给定一个长度为 n 的非负整数数组 height,其中每个元素表示一条垂直线的高度。找出两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。 ### 解法思路 我们可以采用 **双指针** 方法来高效解决问题: 1. 初始化两个指针 `left` 和 `right` 分别指向数组的第一个位置和最后一个位置。 2. 计算当前两个指针所围成的面积 `(right - left) * min(height[left], height[right])` 并更新最大值。 3. 每次移动高度较小的那个指针(因为如果移动较大的那个指针,则无论如何都不会让水量增加),直到两指针相遇为止。 4. 最终得到的最大面积即为答案。 这种方法的时间复杂度为 O(n),比暴力解法更优。 --- #### 示例代码 (Python) ```python def maxArea(height): left, right = 0, len(height) - 1 max_area = 0 while left < right: # 当前面积计算 current_area = (right - left) * min(height[left], height[right]) max_area = max(max_area, current_area) # 移动较短的一侧指针 if height[left] < height[right]: left += 1 else: right -= 1 return max_area ``` --- ### 关键点解析 1. 双指针从两端开始逼近的原因在于我们试图寻找更大的宽度组合,并动态调整高度限制条件。 2. 如果只移动较高的那一端,由于宽度减少而无法提升高度,因此不会带来更好的结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值