【算法】-- 【求数对之差的最大值、求绝对值最小的数、求两个元素的最小距离、求指定数字在数组中第一次出现的位置、对数组的两个子有序段进行合并】

01 如何求数对之差的最大值

方法一:蛮力法
首先遍历数组,找到所有可能的差值,其次从所有差值中找出最大值。

public static int getMax(int[] a){
        int n=a.length;
        int max=Integer.MIN_VALUE;
        for (int i=0;i<n;i++){
            for (int j=i+1;j<n;j++){
                if (a[i]-a[j]>max)
                    max=a[i]-a[j];
            }
        }
        return max;
    }


    public static void main(String[] args) {
        int a[]={1,2,3,4,0,6,7,8,9};
        System.out.println(getMax(a));
    }

方法二:二分法
把数组分为两个子数组,那么最大的差值只能有3种可能:
1.最大的差值对应的被减数和减数都在左子数组中,假设最大的差值为leftMax
2.被减数和减数都在右子数组中,假设最大差值为rightMax
3.被减数是右子数组中最小值,假设差值为minMax。

  public static int getMax1(int a[]){
        if (a==null)
            return Integer.MAX_VALUE;
        int len=a.length;
        if (len<1)
            return Integer.MIN_VALUE;
        AtomicInteger max = new AtomicInteger(0);
        AtomicInteger min = new AtomicInteger(0);
        return getMaxDiff(a,0,len-1,max,min);
    }

    private static int getMaxDiff(int[] a, int begin, int end, AtomicInteger max, AtomicInteger min) {
        if (begin==end){
            max.set(a[begin]);
            min.set(a[begin]);
            return Integer.MIN_VALUE;
        }
        int middle=begin+(end-begin)/2;
        //数组前半部分的最小值与最大值
        AtomicInteger lMax = new AtomicInteger(0);
        AtomicInteger lMin = new AtomicInteger(0);
        //数组前半部分的最大差值(第一种情况)
        int leftMax=getMaxDiff(a,begin,middle,lMax,lMin);
        //数组前半部分的最小值与最大值
        AtomicInteger rMax=new AtomicInteger(0);
        AtomicInteger rMin =new AtomicInteger(0);

        //数组后半部分的最大差值(第二种情况)
        int rightMax=getMaxDiff(a,middle+1,end,rMax,rMin);
        //对应第三种情况
        int minMax=lMax.get()-rMin.get();
        //求数组的最大值和最小值
        if (lMax.get()>rMax.get())
            max.set(lMax.get());
        else
            max.set(rMax.get());
        if (lMin.get()<rMin.get())
            min.set(lMin.get());
        else
            min.set(rMin.get());
        //求最大的差值
        int allMax =(leftMax>rightMax)?leftMax:rightMax;
        allMax=(allMax>minMax)?allMax:minMax;
        return allMax;
    }


    public static void main(String[] args) {
        int a[]={1,2,3,4,0,6,7,8,9};
        System.out.println(getMax1(a));
    }

方法三:动态规划

  public static int max(int m,int n){
        return (m>n)?m:n;
    }
    public static int getMax2(int a[]){
        if (a==null)
            return Integer.MAX_VALUE;
        int len=a.length;
        if (len<=1)
            return Integer.MIN_VALUE;
        int[] diff=new int[len];
        int[] max=new int[len];
        diff[0]=Integer.MIN_VALUE;
        max[0]=a[0];
        for (int i=1;i<len;i++){
            diff[i]=max(diff[i-1],max[i-1]-a[i]);
            max[i]=max(max[i-1],a[i]);
        }
        return diff[len-1];
    }



    public static void main(String[] args) {
        int a[]={1,2,3,4,0,6,7,8,9};
    
        System.out.println(getMax2(a));
    }

动态规划优化

    public static int getMax3(int a[]){
        if (a==null)
            return Integer.MIN_VALUE;
        int len=a.length;
        if (len<=1)
            return Integer.MIN_VALUE;
        int diff=0;
        int max=0;
        for (int i=1;i<len;i++){
            diff=max(diff,max-a[i]);
            max=max(max,a[i]);
        }
        return diff;
    }


    public static void main(String[] args) {
        int a[]={1,2,3,4,0,6,7,8,9};
    
        System.out.println(getMax3(a));
    }

02 如何求绝对值最小的数

问题描述:有一个升序排列的数组,数组中可能有正数、负数、0,求数组中元素的绝对值最小的数。例如:数组{-10,-5,-2,7,15,20}
二分法:

 public static int getMinAbsoluteValue(int []a){
        if (a==null)
            return Integer.MIN_VALUE;
        int len =a.length;

        if (len<1)
            return Integer.MIN_VALUE;

        //数组中没有负数
        if (a[0]>0)
            return a[0];
        //数组中没有正数
        if (a[len-1]<0)
            return a[len-1];

        int mid=0;
        int begin=0;
        int end=len-1;
        int absMin=0;
        //数组中既有正数又有负数
        while (true){
            mid=begin+(end-begin)/2;
            //如果值等于0,那么就是绝对值最小的数
            if (a[mid]==0)
                return 0;
            //如果值大于0,那么正负数的分界点在左半部分
            else if (a[mid]>0){
                //继续在数组的左半部分查找
                if (a[mid-1]>0){
                    end=mid-1;
                }else if (a[mid-1]==0)
                    return 0;
                //找到正负的分界点
                else
                    break;
            }//如果值小于0,那么正负数的分界点在右半部分
            else{
                //在数组的右半边查找
                if (a[mid+1]<0)
                    begin=mid+1;
                else if (a[mid+1]==0)
                    return 0;
                else
                    break;
            }
        }
        //已获得正负分界点,找出最小绝对值
        if (a[mid]>0){
            if (a[mid]<Math.abs(a[mid-1]))
                absMin=a[mid];
            else
                absMin=a[mid-1];
        }else{
            if (Math.abs(a[mid])>a[mid+1])
                absMin=a[mid+1];
            else
                absMin=a[mid];
        }
        return absMin;
    }

    public static void main(String[] args) {
        int a1[]={-5,-4,-3,-2,-1,3,6,9};
        int a2[]={2,3,4,7,9};
        int a3[]={-15,-12,-10,-8,-6,-3};
        System.out.println(getMinAbsoluteValue(a1));
        System.out.println(getMinAbsoluteValue(a2));
        System.out.println(getMinAbsoluteValue(a3));

    }

03 如何求数组中两个元素的最小距离

问题描述:给定一个数组,数组中含有重复元素,给出两个数n1和n2,求这两个数字在数组中搜出现位置的最小距离。例如:数组{4,5,6,4,7,8,4,2,3,4,5,4,6,9}中,4和8的最小距离为1

定义一个变量min_dist记录n1和n2的最小距离,在以上两种情况下,每次求出n1和n2的距离后与min_dist相比,求最小值。时间复杂度O(n)

 private static int min(int a,int b){
        return (a>b)?b:a;
    }

    public static int getMinDistance(int a[],int n1,int n2){
        if (a==null)
            return Integer.MIN_VALUE;
        int len=a.length;
        int n1_index=-1;
        int n2_index=-1;
        int min_dist=Integer.MIN_VALUE+1;
        for (int i=0;i<len;i++){
            if (a[i]==n1){
                n1_index=i;
                if (n2_index>=0)
                    min_dist=min(Math.abs(min_dist),Math.abs(n1_index-n2_index));
            }
            if (a[i]==n2){
                n2_index=i;
                if (n1_index>=0)
                    min_dist=min(Math.abs(min_dist),Math.abs(n2_index-n1_index));
            }
        }
        return min_dist;
    }

    public static void main(String[] args) {
        int a[]={4,5,6,4,7,8,4,2,3,4,5,4,6,9};
        System.out.println(getMinDistance(a,4,8));
    }

04 如何求指定数字在数组中第一次出现的位置

问题描述:给定数组{4,5,6,5,4,3,2,1,2,3,4,5,6,7,8,9},这个数组中相邻元素之差都为1,给定数字9,它在数组中第一次出现的位置下标为13。

跳跃搜索法:

public static int getFindIndex(int a[],int t){
        if (a==null)
            return Integer.MIN_VALUE;
        int len=a.length;
        int i=0;
        while (i<len){
            if (a[i]==t)
                return i;
            else
                i+=Math.abs(t-a[i]);
        }
        return -1;
    }

    public static void main(String[] args) {
        int a[]={4,5,6,5,4,3,2,1,2,3,4,5,6,7,8,9};
        System.out.println(getFindIndex(a,7));
    }

05 如何对数组的两个子有序段进行合并

 public static void getFindRightPlaceForMid(int []a,int mid){
        int len=a.length;
        int tmp;
        for (int i=mid;i<len-1;i++){
            if (a[i+1]<a[i]){
                tmp=a[i];
                a[i]=a[i+1];
                a[i+1]=tmp;
            }
        }
    }

    public static void sort (int a[],int mid){
        int tmp;
        for (int i=0;i<mid;i++){
            if (a[mid]<a[i]){
                tmp=a[i];
                a[i]=a[mid];
                a[mid]=tmp;
                getFindRightPlaceForMid(a,mid);
            }
        }
    }

    public static void main(String[] args) {
        int a[]={1,3,5,7,9,2,4,6,8};
        int mid=5;
        sort(a,5);
        System.out.println(Arrays.toString(a));
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
对于给定的一组整a1, a2, a3, …, an,要使两个之和的绝对值最小,我们需要寻找两个的组合。 我们可以使用两个指针,一个在数组的开头,一个在数组的末尾。我们将这两个指针指向的相加,并将其与当前最小绝对值进行比较。如果和的绝对值更小,我们更新最小绝对值,并保存这两个。然后,我们根据和的正负情况将指针向内移动。 具体算法如下: 1. 将数组按升序排序。 2. 定义两个指针,一个指向数组的开头,另一个指向数组的末尾。 3. 初始化最小绝对值为无穷大。 4. 循环寻找两个之和,并更新最小绝对值以及保存这两个。 5. 根据和的正负情况移动指针。 6. 返回保存的两个。 以下是一个示例代码: def findMinSum(numbers): numbers.sort() # 将数组升序排序 left = 0 # 左指针 right = len(numbers) - 1 # 右指针 minAbsSum = float('inf') # 初始最小绝对值为无穷大 num1 = 0 # 第一个 num2 = 0 # 第二个 while left < right: currentSum = numbers[left] + numbers[right] # 当前之和 currentAbsSum = abs(currentSum) # 当前之和的绝对值 if currentAbsSum < minAbsSum: # 如果当前绝对值更小 minAbsSum = currentAbsSum # 更新最小绝对值 num1 = numbers[left] # 保存第一个 num2 = numbers[right] # 保存第二个 if currentSum < 0: # 如果和为负,说明之和偏小 left += 1 # 左指针向右移动一位 else: # 如果和为正,说明之和偏大 right -= 1 # 右指针向左移动一位 return num1, num2 这样,通过以上算法,我们可以找到一组之和的绝对值最小

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值