递增数组找和x值最接近值的第一个下标

算法题:递增数组找和x值最接近值的下标

说明:

  • 最接近指差的绝对值最小
  • 元素可重复
  • 相同接近时取最小下标
  • 时间复杂度要求O(logn)

   例子:

  1, 2, 2, 3, 5, 6, 6, 9, 19

  x: 4                 index: 3

  x: 8                 index: 7

  x: 2                 index: 1

  x: 7                 index: 5

  x: 0                 index: 0

  x: 100             index: 8 

方法一:

public class Main {
    public static void main(String[] args) {
        int[] arr={1,2,2,3,5,6,6,9,19};
        int[] res={4,8,2,7,0,100};

        int index;
        for(int x:res){
            index=find(arr, x);
            System.out.println("index:"+index);
        }
    }
    private static int find(int[] arr, int target){
        int n=arr.length;
        if(target<=arr[0])
            return 0;
        if(target>arr[n-1])
            return n-1;

        int low=0, high=n-1;
        int mid=0;
        while(low<high){
            mid=low+(high-low)/2;
            if(arr[mid]>=target){
                if(mid>0&&arr[mid-1]<target){
                    high=Math.abs(target-arr[mid-1])<=Math.abs(target-arr[mid])?mid-1:mid;
                    continue;
                }
                high=mid;
            }else{  //目标值比中间值大
                if(mid<n-1&&arr[mid+1]>target){
                    low=Math.abs(target-arr[mid])<=Math.abs(target-arr[mid+1])?mid:mid+1;
                    continue;
                }
                low=mid+1;
            }

        }
        while(low>0&&arr[low]==arr[low-1])
            low--;
        return low;
    }
}

方法二:把目标值的值改成数组中最接近它的值,可以取到最左边的下标,时间复杂度严格为O(logn)

public class Main {
    public static void main(String[] args) {
        int[] arr={1,2,2,3,5,6,6,9,19};
        int[] res={4,8,2,7,0,100};

        int index;
        for(int x: res){
            index=find(arr, x);
            System.out.println("index:"+index);
        }
    }

    private static int find(int[] arr, int target){
        int n=arr.length;
        if(target<=arr[0])
            return 0;
        int temp=target;
        int low=0, high=n-1;
        int mid=0;
        while(low<high){
            mid=low+(high-low)/2;
            if(arr[mid]==temp){
                high=mid;
            }else if(arr[mid]>temp){
                if(mid>0&&arr[mid-1]<temp){
                    if((temp-arr[mid-1])>(arr[mid]-temp))
                        return mid;
                    else temp=arr[mid-1];  //改变目标值的值,取最左边的下标
                }
                else if(mid>0&&arr[mid-1]>=temp) high=mid-1;
            }else{  //目标值比中间值大
                if(mid<n-1&&arr[mid+1]>temp){
                    if((temp-arr[mid])>(arr[mid+1]-temp))
                        return mid+1;
                    else temp=arr[mid];   //改变目标值的值,取最左边的下标
                }
                else if(mid<n-1&&arr[mid+1]<=temp)  low=mid+1;
            }

        }
        return low;
    }
}

 

posted @ 2021-04-18 14:56  东风劲,少年梦  阅读(160)  评论(0)    收藏  举报