leetcode 624.数组列表中的最大距离

文章介绍了如何解决一个编程问题,给定一组有序数组,找出其中任意两个不同数组的最大距离,同时排除来自同一数组的元素。作者提供了三种不同的解法,涉及优先队列和变量更新策略来提高效率。
摘要由CSDN通过智能技术生成

在这里插入图片描述

思路:

O(n^2)的方法很好想,但太慢了

朴素想法: 既然每个数组已经有序,找到m个数组第一个元素中的最小值,再找到每个数组最后一个元素的最大值就行了

问题: 题目要求两个元素不能来自于同一个数组,所以考虑记录次小和次大,即便最小和最大是来自同一个的,根据次优值算就行了。
最小min1, 次小min2, 最大max1, 次大max2

若min1, max1不是来自同一个数组,结果就是|min1-max1|
若是来自同一个数组,结果就是max(|min1, max2|, |min2, max1|)

解法1:
建两个优先队列,每个队列长度为2
遍历过程中还需要记录两个队列头元素是否来自同一个数组,用fromSame记录

首先将第一个数组的最小,最大分别入队,fromSame设置为true

遍历剩余数组:最小,最大分别入队,fromSame更新机制为:
fromSame=true仅有以下两种情况:
1.该数组同时出现了更小和更大的,即都来自当前遍历的数组
2.fromSame已经为true,且当前遍历的数组,既没有更小的,也没有更大的,fromSame依然为true

否则,fromSame置为false

class Solution {
    public int maxDistance(List<List<Integer>> arrays) {
        PriorityQueue<Integer> minQ=new PriorityQueue<>(2, (a,b)->a-b);
        PriorityQueue<Integer> maxQ=new PriorityQueue<>(2, (a,b)->b-a);
        List<Integer> tmp = arrays.get(0);
        minQ.add(tmp.get(0));
        maxQ.add(tmp.get(tmp.size()-1));
        boolean fromSame=true;
        for(int i=1;i<arrays.size();i++){
            tmp=arrays.get(i);
            int minEle = tmp.get(0);
            int maxEle = tmp.get(tmp.size()-1);
            if(minEle<minQ.peek() && maxEle>maxQ.peek()){
                fromSame=true;
            }else if(fromSame && minEle>minQ.peek() && maxEle<maxQ.peek()){
                fromSame=true;
            }else{
                fromSame=false;
            }
            minQ.add(minEle);
            maxQ.add(maxEle);
        }
        if(!fromSame){
            return Math.abs(minQ.peek()-maxQ.peek());
        }
        int min1=minQ.poll();
        int min2=minQ.poll();
        int max1=maxQ.poll();
        int max2=maxQ.poll();
        return Math.max(
            Math.abs(min1-max2),
            Math.abs(min2-max1)
        );
    }
}

解法2:
直接开4个变量记录最大,最小,次大,次小,其余不变
省去队列插入的复杂度

class Solution {
    public int maxDistance(List<List<Integer>> arrays) {
        int min1,min2,max1,max2;
        List<Integer> tmp = arrays.get(0);
        min1=tmp.get(0);
        max1=tmp.get(tmp.size()-1);
        boolean fromSame=true;
        for(int i=1;i<arrays.size();i++){
            tmp=arrays.get(i);
            int minEle = tmp.get(0);
            int maxEle = tmp.get(tmp.size()-1);
            //更新fromSame
            if((minEle<min1 && maxEle>max1) || (fromSame && minEle>min1 && maxEle<max1)){
                fromSame=true;
            }else{
                fromSame=false;
            }

            //更新最大最小值
            if(minEle<=min1){
                min2=min1;
                min1=minEle;
            }else if(minEle<=min2){
                min2=minEle;
            }

            if(maxEle>=max1){
                max2=max1;
                max1=maxEle;
            }else if(maxEle>=max2){
                max2=maxEle;
            }
        }
        if(!fromSame){
            return Math.abs(max1-min1);
        }
        return Math.max(
            Math.abs(min1-max2),
            Math.abs(min2-max1)
        );
    }
}

解法3:
前两个都是在最后才确认最大和最小,所以需要记录次大,次小
实际上,可以遍历每个新数组时,更新最大,最小,抛开次大、次小

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值