算法--微软面试题:求一个整数数组元素间最小差值

Q题目

有一个整数数组,请求出两两之差绝对值最小的值,记住,只要得出最小值即可,不需要求出是哪两个数.


A解法

方案一:最愚笨的办法——暴力穷举

利用数组中所有数据两两相减的对比来求出这个最小差值。
缺点:效率低,浪费资源

代码如下:

package 微软数组最小差值;

import java.util.ArrayList;
import java.util.Collections;

/**
 * 有一个整数数组,请求出两两之差绝对值最小的值,记住,只要得出最小值即可,不需要求出是哪两个数
 * @author Administrator
 *
 */
public class Test1 {
    public static void main(String[] args) {
//      int[] arr={-2,2,5,8,11};
        int[] arr={-2,10,5,87,11,2};
        int min=getMinSubtract(arr);
        System.out.println("==min==="+min);

    }

    //1.暴力穷举法,求出所有数的差
    public static int getMinSubtract(int[] arr){
        int minus=0;
        //1.若用数组处理,先计算数组长度arr.length的阶乘,因为比较麻烦,这里就不用数组了
        //2.集合处理:存储两数的差值
        ArrayList<Integer> list=new ArrayList<>();
        for(int i=0;i<arr.length-1;i++){
            for(int j=i+1;j<arr.length;j++){
                minus=Math.abs(arr[i]-arr[j]);
                list.add(minus);
            }
        }
        System.out.println("所有差值为:"+list);
        int min=Collections.min(list);
        return min;
    }


}

方案二:先排序,再求相邻两个数的差值

优点:效率高

代码如下:

package 微软数组最小差值;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

public class Test2 {
    public static void main(String[] args) {
        int[] arr={-2,10,5,87,11,2};
        int min=getMinSubtract02(arr);
        System.out.println("==min==="+min);
    }

    //2.排序后,再求最小值
    public static int getMinSubtract02(int[] arr){
        Arrays.sort(arr);
        System.out.println("排序后的数组:"+Arrays.toString(arr));

        //这里同样采用集合,不用数组
        ArrayList<Integer> list=new ArrayList<>();
        int start=arr[0];
        for (int i = 1; i < arr.length; i++) {
            int minus=arr[i]-start;//因为数组时按从小到大排序的,所以不用去绝对值
            list.add(minus);
            start=arr[i];
        }

        System.out.println("所有差值为:"+list);
        int min=Collections.min(list);
        return min;
    }
}

方案三:设立辅助数组(不排序,直接求相邻两个数的差值)

思路分析:

设立辅助数组。以下是设立辅助数组的基本思路

设辅助数组为Bn.原来题目中给定的数组是An,则Bn等于:

  B1 = A1 - A2;

  B2 = A2 - A3;

  B3 = A3 - A4;

  ……

  Bn-1 = An-1 - An.

注意,Bn的长度是n-1,正好比An要小一个。聪明的同学看到这个辅助数组,立马就能猜到原因了,因为这样做的话,我们能够把这道看似无从下手求出最优解的问题转化为求Bn的绝对值最小的最长连续子序列和,因为Bn的连续子序列和便是An任意两数之差(注意,由于题目要求的是绝对值最小,所以求出A1-A2等效于得出A2-A1),例如:

  A2 - A5 = B2 + B3 + B4 = A2 - A3 + A3 - A4 + A4 - A5 = A2 - A5

  实际上,任何Ai - Aj(i<j) = sigma(k=i -> k=j-1)(k)。
  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 分治算法可以用来一个整数数组中的第k大元素。具体步骤如下: 1. 将数组分成两个子数组,左边的子数组包含小于等于中值的元素,右边的子数组包含大于中值的元素。 2. 如果左边的子数组的长度大于等于k,则在左边的子数组中继续查找第k大元素。 3. 如果左边的子数组的长度小于k,则在右边的子数组中查找第k - 左边子数组长度 - 1大元素。 4. 重复以上步骤,直到找到第k大元素。 这个算法的时复杂度为O(nlogn),其中n为数组的长度。 ### 回答2: 分治算法是一种经典的算法思想,通过将一个问题分解成若干个小问题,并分别解决,最后合并结果得到整个问题的解决方案。对于整数数组中的第k大元素的问题,我们可以运用分治算法进行解。 具体的方法如下: 1. 随机选择数组中的一个数作为枢轴值(pivot),将数组中小于枢轴值的数放在它左边,大于它的数放在它右边。 2. 计算出枢轴值在数组中的位置 p (第 p 大元素)。 a. 如果 p == k,则找到了第 k 大元素,返回它的值。 b. 如果 p > k,则在枢轴值的左边继续查找第 k 大元素。 c. 如果 p < k,则在枢轴值的右边继续查找第 k-p 大元素。 3. 当在步骤2中找到了第 k 大元素时,返回它的值。 4. 当在步骤2中未能找到第 k 大元素时,重复执行步骤1-3。 由于每一次都将数组分成了两个部分,所以每一次查找的时复杂度为 O(n),因此总时复杂度为 O(n log n)。 需要注意的是,为了防止出现最坏情况,需随机选择枢轴值,或者通过一定的方法选择每次划分的方向(例如:选择中位数作为枢轴值),防止过多的元素分到一边,导致时复杂度退化。 总之,利用分治算法整数数组中第 k 大元素是一种高效的方法,其时复杂度为 O(n log n),是解决这一问题的常用方法。 ### 回答3: 分治算法将问题分成小的子问题,然后将这些子问题的解合并成原问题的解。一个整数数组中的第k大元素就可以使用分治算法解。 首先选择一个pivot元素,将数组分成两部分,一部分比pivot元素小,一部分比pivot元素大。如果这个pivot元素是第k大的元素,那么问题就得到了解决。 如果pivot元素不是第k大的元素,那么问题就被拆分成了两个子问题,分别对这两个子问题进行递归操作即可。只需要递归子数组中可能存在第k大元素的那一部分。 快速选择算法采用的就是这种思路,可以快速地找到第k大元素。反复进行快速选择操作,直到找到第k大的元素为止。 快速选择算法的时复杂度为O(n),其中n为数组的长度。由于每次操作只需要递归一个子问题,所以算法的空复杂度为O(log n)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值