每日一刷经验分享:力扣1200-最小绝对差

187 阅读3分钟

最小绝对差

题意

给你个整数数组 arr,其中每个元素都 不相同。

请你找到所有具有最小绝对差的元素对,并且按升序的顺序返回。

示例 1:

输入:arr = [4,2,1,3] 输出:[[1,2],[2,3],[3,4]] 示例 2:

输入:arr = [1,3,6,10,15] 输出:[[1,3]] 示例 3:

输入:arr = [3,8,-10,23,19,-4,-14,27] 输出:[[-14,-10],[19,23],[23,27]]  

提示:

2 <= arr.length <= 10^5 -10^6 <= arr[i] <= 10^6

相关类型: 数组排序

温馨提示:

  1. Find the minimum absolute difference between two elements in the array.
  2. The minimum absolute difference must be a difference between two consecutive elements in the sorted array.

AC代码

👀java版:

class Solution {
    public List<List<Integer>> minimumAbsDifference(int[] arr) {
        Arrays.sort(arr);
        int min1 = Integer.MAX_VALUE;
        int len = arr.length;
        for(int i=1;i<len;i++){
            min1 = Math.min(min1,arr[i]-arr[i-1]);
        }
        List<List<Integer>> list = new ArrayList<>();
        for(int i=1;i<len;i++){
            if(arr[i]-arr[i-1]==min1) {
                List<Integer>list1 = new ArrayList<Integer>();
                list1.add(arr[i-1]);
                list1.add(arr[i]);
                list.add(list1);
            }
        }
        return list;
    }
}

👀C++版:

class Solution {
public:
    vector<vector<int>> minimumAbsDifference(vector<int>& arr) {
        vector<vector<int>> res;
        int diff = 1e9;
        sort(arr.begin(), arr.end());
        for (int i = 1; i < arr.size(); i++) {
            diff = min(diff, arr[i] - arr[i - 1]);
        }
        for (int i = 1; i < arr.size(); i++) {
            if (arr[i] - arr[i - 1] == diff) res.push_back({arr[i - 1], arr[i]});
        }
        return res;
    }
};

分析

解题思路 排序

  1. 使用Arrays.sort(arr)排序之后,相对于每个i来说,最小的绝对值差的元素对只可能是自己的下一个元素.
  2. 这样,通过一次遍历获得最小的绝对值差的具体数字记录在min1变量中去.
  3. 再遍历一次,把差值等于步骤2获得的最小差值min1的作为答案备选收集.

题解过程分析

  1. Arrays.sort(arr); 对整个数组进行排序,便于后续的使用遍历。
  2. 定义min1,用于记录最小值,在第一次遍历的时候用于记录最小值。
  3. min1 = Math.min(min1,arr[i]-arr[i-1]);遍历查询最小值。
  4. 第二遍for循环
  • if(arr[i]-arr[i-1]==min1) { //当第二次遍历等于min1的时候
  • ——Listlist1 = new ArrayList(); //定义内部list
  • ——list1.add(arr[i-1]); //添加字符对的前一个
  • ——list1.add(arr[i]); //添加字符对的后一个
  • ——list.add(list1); //把内部list添加到外部list中
  • }
  1. 返回最后list数组。

图解过程分析

image.png

image.png

image.png

image.png

探索新方法

方法二:排序

  1. 我们将数组排序,逐个遍历并比较绝对最小差:
  2. 与最小绝对差相等,加入答案。
  3. 比最小绝对差小,清空答案并更新最小绝对差,然后加入新答案。
  4. 比最小绝对差大,直接跳过

🎐贴个代码

    public List<List<Integer>> minimumAbsDifference(int[] arr) {
        //排序
        Arrays.sort(arr);
        int min = Integer.MAX_VALUE;
        List<List<Integer>> ans = new ArrayList<>();
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] - arr[i - 1] < min) {
                //比最小绝对差小
                ans.clear();
                min = arr[i] - arr[i - 1];
            } else if (arr[i] - arr[i - 1] > min) {
                //比最小绝对差大
                continue;
            }
            //添加答案
            List<Integer> list = new ArrayList<>();
            list.add(arr[i - 1]);
            list.add(arr[i]);
            ans.add(list);
        }
        return ans;
    }

👀python3:

class Solution:
    def minimumAbsDifference(self, arr: List[int]) -> List[List[int]]:
        m, ans = inf, []
        for a, b in pairwise(sorted(arr)):
            if (cur := b - a) < m:
                m, ans = cur, [[a, b]]
            elif cur == m:
                ans.append([a, b])
        return ans

👀Go:

func minimumAbsDifference(arr []int) (ans [][]int) {
    sort.Ints(arr)
    for i, min := 0, math.MaxInt32; i < len(arr) - 1; i++ {
        if diff := arr[i + 1] - arr[i]; diff < min {
            min = diff
            ans = [][]int{[]int{arr[i], arr[i + 1]}}
        } else if diff == min {
            ans = append(ans, []int{arr[i], arr[i + 1]})
        }
    }
    return
}

复杂度分析

复杂度分析如下:

  • 时间复杂度:O(nlogn)
  • 空间复杂度:O(logn)
  • 如果对您有帮助,记得关注 + 点赞 + 收藏呦!!!
  • 每天都会更新每日一题题解,大家加油!!!

总结

除了自己的思路去解决这道题之外,网路上常见的的就是这两种方法,一种是先遍历一遍得出最小值,之后再遍历一遍查找与最小值相等的有序对,第二种就是就遍历一遍,如果有比最小值小的就把list中的数据清空,第一种的具体的复杂度为O(2n),第二种具体的复杂度是O(nlogn)。

一般这种题的思考方向就是先排序,然后再做后续的处理。

总体上来讲,这个题是相对简单的,也算是每日一刷中的一个上手就会做的一个题,但是通过越是像这种看着比较简单的题,我们往往会忽略边界条件,像是数组长度为0,当然这个题中是给出了不为0,知识我们以后在面试或者日常刷题练习的过程中要相对注意的一点,像是这种特别的情况我们常常需要在代码的开始阶段进行一些特判🤞。

image.png

上边的耗时情况,对于本题中的代码,分析之后应该是由于两边的遍历加上最初的排序造成的时间消耗相比于其他人比较大,所以我们也可以是用方法二中相应的策略,就是在排序完成后只进行一次遍历,在遇到最小值的时候把之前的删除即可,这也不失为一种好的解决方案。 image.png 这个耗费内存基本上没什么消耗,就是用了一个变量min1,应该是java相对于其他语言相对耗费内存较多的原因的问题,这个List要在队中申请的内存相比于其他语言占用内存较多。

我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿