算法实践:查找最接近的元素(最近不能相等)

查找最接近的元素(最近不能相等)

描述

查找最接近的元素

输入

第一行包含一个整数n,为非降序列长度。1 <= n <= 100000。

第二行包含n个整数,为非降序列各元素。所有元素的大小均在0-1,000,000之间。

第三行包含一个整数m,为要询问的给定值个数。1 <= m <= 10000。

接下来m行,每行一个整数,为要询问最接近元素的给定值。所有给定值的大小均在0-1,000,000之间。

(注意:最接近但是不能相等。输入保证有解)

输出

m行,每行一个整数,为最接近相应给定值的元素值,保持输入顺序。

若有多个值满足条件,输出最小的一个。

样例

3
2 5 8
2
10
5
8
2

难度

解法

要求找到与target最接近,但是不能相等的数,意味着要严格思考检查目标的左右边界最接近的值的位置。

lowerBound函数:在包含n个元素的、从小到大排序的int数组nums里查找比给定整数target小的,下标最大的元素。找到则返回其下标,找不到则返回-1------二分查找

upperBound函数:在包含n个元素的、从小到大排序的int数组nums里查找比给定整数target大的,下标最小的元素。找到则返回其下标,找不到则返回-1------二分查找

先判断target如果比第一个小,比最后一个大的情况,然后是分别有左右边界的情况,接着返回有左右边界中最接近的那个数。

代码

package com.company;
import java.util.*;
public class Main {
//    查找target小的,下标最大的元素
    public static int lowerBound(long nums[],int n,long target){
        int left = 0 , right = n;
        int result = -1; //没找到
        while(left<right){
            int mid = (left + right)/2;
            if(nums[mid]>=target) right=mid;  //[left,mid)
            else{
                result = mid;   //nums[mid]<target
                left = mid+1;
            }
        }
        if(result==-1&&nums[0]<target)
            result = 0;
        return result;
    }
//    查找target小的,下标最小的元素
    public static int upperBound(long nums[],int n,long target){
        int left = 0 , right = n;
        int result = -1; //没找到
        while(left<right){
            int mid = (left + right)/2;
            if(nums[mid]<=target) left=mid+1;
            else{
                result = mid;   //nums[mid]<target
                right = mid;
            }
        }
        if(result==-1&&nums[n-1]>target)  //判断右边界
            result = n-1;
        return result;
    }
    public static void main(String[] args) {
	    int n,m,left,right;
	    long target,foundNumber;
	    Scanner input = new Scanner(System.in);
	    n = input.nextInt();
	    long[] numbers = new long[n];
	    for(int i=0;i<n;i++)
	        numbers[i] = input.nextLong();
	    m = input.nextInt();
	    while(m>0){
	        m--;
	        target = input.nextLong();
	        if(target<numbers[0]){
	            System.out.println(numbers[0]);
	            continue;
            }
            if(target>numbers[n-1]){
                System.out.println(numbers[n-1]);
                continue;
            }
            left = lowerBound(numbers,n,target);
            right = upperBound(numbers,n,target);
            if(left==-1){
                System.out.println(numbers[right]);
                continue;
            }
            if(right==-1){
                System.out.println(numbers[left]);
                continue;
            }
            foundNumber = target-numbers[left]>numbers[right]-target?numbers[right]:numbers[left];
            System.out.println(foundNumber);
	    }
    }
}

发布了129 篇原创文章 · 获赞 148 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/matafeiyanll/article/details/104859990