首页 > 试题广场 >

二分查找

[编程题]二分查找
  • 热度指数:4461 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
请实现有重复数字的有序数组的二分查找。
输出在数组中第一个大于等于查找值的位置,如果数组中不存在这样的数,则输出数组长度加1。

输入描述:
第一行两个正整数n,v(1<=n<=100000,1<=v<=100000),分别表示数组长度与查找值。

第二行n个正整数a1,a2,...,an(1<=a1<=a2<=...<=an<=n)表示有序数组。


输出描述:
输出在数组中第一个大于等于查找值的位置,如果数组中不存在这样的数,则输出数组长度加一。
示例1

输入

5 4
1 2 4 4 5

输出

3
示例2

输入

5 4
1 2 3 3 5

输出

5
示例3

输入

5 4
1 2 2 3 3

输出

6
#include<iostream>
#include<algorithm>
#include<string>
#include <vector>
using namespace std;
int binaryserch(vector<int>&v,int key){
    int low,high,mid;
    low=0;
    high=v.size()-1;
    while(low<=high){
        mid=(low+high)/2;
        if(v[mid]>=key){
            int j = mid;
            while(j>=0 && v[j]>=key){
                j--;
            }
            return j+1+1;
        }
        //else if(v[mid]>key){
        //     high = mid-1;            
        
        //}
        else{//v[mid] < key
            low = mid+1;
        }
    }
    return v.size()+1;
}
int main(){
    int n,key;
    vector<int>v;
    cin>>n>>key;
    int i;
    for(i=0;i<n;i++){
        int t;
        cin>>t;
        v.push_back(t);
    }
    cout<<binaryserch(v,key);
    
}

发表于 2020-08-03 10:52:15 回复(0)

#####算法思路:

由于题目要求输出第一个大于等于查找值的位置,因此需要对二分查找的结果进行判断。当查找到数组中某个位置的值等于查找值时,需要继续向前查找,直到找到第一个大于等于查找值的位置;当未查找到查找值时,需要输出下标+1,即为数组长度加1。

#####具体实现:

定义左右指针left和right,初始值分别为0和n-1,表示在整个数组范围内进行查找。

  在循环中,每次计算中间位置mid,如果中间位置的值等于查找值,需要向前查找,直到找到第一个大于等于查找值的位置;如果中间位置的值小于查找值,需要将左指针left更新为mid+1,继续在右半部分查找;如果中间位置的值大于查找值,需要将右指针right更新为mid-1,继续在左半部分查找。

如果循环结束时仍未查找到查找值,则输出right+1,即为数组长度加1。
时间复杂度:

由于每次将查找范围缩小一半,因此时间复杂度为O(logn)。

#include <iostream>
#include <vector>
using namespace std;

int binarySearch(vector<int> &nums,int target)
{
 int left=0;
   int right=nums.size()-1;
    while(left<=right)
    {
        int middle=left+(right-left)/2;
      
       if(target<=nums[middle])
        {
            right=middle-1;
        }
        else
        {
            left=middle+1;
        }
    }

return   left<nums.size()?left+1:nums.size()+1;
}

int main()
 {

    int len,target;
    scanf("%d",&len);
    scanf("%d",&target);

    vector<int> nums(len);
   
    for(int i=0;i<len;i++)
    {scanf("%d",&nums[i]);

    }


  cout<<binarySearch(nums,target)<<endl;

return 0;
  
}


在该代码中,首先使用scanf输入n和v,然后使用for循环和scanf输入整个数组nums。在二分查找函数binarySearch中,根据题目要求,使用左闭右开区间进行二分查找。如果nums[middle]大于等于target,则将右指针right更新为middle-1;否则将左指针left更新为middle+1。最后,返回left+1或n+1,即为所求的结果。

Q: return left < nums.size() ? left + 1 : nums.size() + 1;  这里为什么是left+1

A:在该代码中,二分查找的目标是在数组中查找第一个大于等于查找值的位置,因此当找到一个位置,该位置的值大于等于查找值时,需要返回该位置的下标加1。这是因为题目要求的是位置而不是下标,下标是从0开始的,因此需要将下标加1才能得到对应的位置。如果left到达了数组的末尾,即left == nums.size(),则说明数组中没有大于等于查找值的数,需要返回nums.size()+1。因此,最后的返回结果可以使用三目运算符进行判断和选择。

编辑于 2023-03-19 02:58:03 回复(0)
#include <stdio.h>

int find_location(int *array, int length, int val)
{
    int low = 0;
    int high = length;
    int tmp;
    int mid;
    while (low < high)
    {
        mid = (low + high) / 2;
        if (val > array[mid])
            low = mid + 1;
        else if (val <= array[mid])
            high = mid;
    }
    return low + 1;
}

int main(int argc, char **agrv)
{
    int num, findnum;
    int array[100000];
    int result;
    scanf("%d", &num);
    scanf("%d", &findnum);
    for (int i = 0; i < num; i ++)
    {
        scanf("%d", &array[i]);
    }
    result = find_location(array, num, findnum);
    printf("%d", result);
}


发表于 2023-03-03 19:16:08 回复(0)
n,v=map(int,input().split())
a=list(map(int,input().split()))

left,right=0,n-1
if not a:
    print(1)
Flag=True
while left<=right:
    mid=(left+right)>>1
    if a[mid]>=v:
        right=mid-1
    else: 
        left=mid+1
    
if left<n and a[left]>=v:
    print(left+1)
else:       
    print(len(a)+1)

发表于 2020-08-29 12:47:15 回复(0)
#include<iostream>
#include <vector>

using namespace std;

int binarySearch(std::vector<int> &vec, int target)
{
	int low = 0;
	int high = vec.size();//[low,high)区间搜索
	int mid = 0;
	while (low < high)
	{
		mid = (low + high) / 2;
		if (vec[mid] == target)
		{
			high = mid;//收紧右区间
		}
		else if (vec[mid] < target)
		{
			low = mid + 1;
		}
		else
		{
			high = mid;
		}
	}
	return low+1;
}

int main()
{

	int len = 0;
	int target = 0;

	std::cin >> len;
	std::cin >> target;

	int ele;
	std::vector<int> vec;
	while (std::cin >> ele)
	{
		vec.push_back(ele);
		if (vec.size() == len)
			break;
	}

	std::cout << binarySearch(vec, target);
}

编辑于 2020-04-08 23:51:31 回复(1)
代码有啥问题呢?
#include <iostream>
#include <vector>

int binarySearch(std::vector<int> &vec,int target)
{
	int low = 0;
	int high = vec.size()-1;
    int mid=0;
	while (low <=high)
	{
        mid = (low + high) / 2;
		if (vec[mid] == target)
		{
            
            while(vec[mid-1]==target) //保证取到的是第一个target
            {
                mid--;
            }
            
			return mid + 1;
		}
		else if(vec[mid]<target)
		{ 
			low = mid + 1;
		}
		else
		{
			high = mid - 1;
		}
	}
	return vec.size() + 1;





}

int main()
{

	int len=0;
	int target = 0;

	std::cin >> len;
	std::cin >> target;

	int ele; 
	std::vector<int> vec;
	while (std::cin >> ele)
	{
		vec.push_back(ele);
		if (vec.size() == len)
			break;
	}
	
	std::cout<<binarySearch(vec, target);
}



您的代码已保存
答案错误:您提交的程序没有通过所有的测试用例
case通过率为66.67%
用例:
100 1
2 3 4 4 4 7 7 8 10 10 11 12 13 14 15 15 17 18 19 23 24 24 24 24 25 26 26 26 27 27 28 29 29 30 33 36 38 38 40 40 41 43 43 43 44 46 46 47 51 52 52 53 54 56 57 57 57 58 58 61 61 61 62 64 64 66 66 67 67 67 70 72 74 74 74 75 75 78 78 78 79 79 80 83 83 83 83 84 84 86 88 89 89 90 91 91 92 93 93 96
对应输出应该为:
1
你的输出为:
101

编辑于 2020-03-18 18:39:56 回复(1)
import java.util.Scanner;

/*
 * Project_name:二分查找
5 3
1 2 3 3 5
 */

public class Main{
	
	public static void main(String args[]) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		int v=sc.nextInt();
		int[] ch=new int[n];
		for(int i=0;i<n;i++) {
			ch[i]=sc.nextInt();
		}
//		System.out.println(v);
		System.out.println(BineSearch(v,ch)+1);
	}

	private static int BineSearch(int v,int[] ch) {
		// TODO Auto-generated method stub
		int low=0;
		int high=ch.length-1;
		while(low<=high) {
			int mid=(low+high)/2;
			if(v<=ch[mid])
				high= mid-1;
			else if(v>ch[mid])
				low=mid+1;
		}
//		System.out.println(low);
		if(low<ch.length&&ch[low]>=v) {
			return low;
		}else {
			return ch.length;
		}
		
	}
}

发表于 2019-11-06 17:48:02 回复(0)
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in); // 输入
        while (input.hasNextInt()) {
            int length = input.nextInt();  // 输入数组长度
            int value = input.nextInt();  // 输入查询值
            int array[] = new int[length];
            for (int i = 0; i < length; i++) {
                array[i] = input.nextInt();  // 输入数组元素值
            }
            int low = 0;  // 设置边界左端位置
            int high = length - 1;  // 设置边界右端位置
            while (low <= high) {
                if (array[(low + high) / 2] < value) {  // 若此段中间位置值小于查询值
                    low = (low + high) / 2 + 1;  // 说明查询值位于此段右半段
                }
                if (array[(low + high) / 2] >= value) {  // 若此段中间位置值大于等于查询值
                    high = (low + high) / 2 - 1;  // 说明查询值位于此段右半段
                }
            }
            if (low == length || high == -1) {
                if (high == length - 1 && array[high] >= value) {
                    System.out.println(high + 1);
                }
                else if (low == 0 && array[low] >= value) {
                    System.out.println(low + 1);
                }
                else {  // 说明查询值并不位于此数组中
                    System.out.println(length + 1);
                }
            }
            else {
                if (array[low] >= value && array[high] >= value) {
                    System.out.println(high + 1);
                }
                if (array[low] >= value && array[high] < value) {
                    System.out.println(low + 1);
                }
            }
        }
    }
}

发表于 2019-09-03 17:20:41 回复(0)
import sys
if __name__ == '__main__':
    n, k = list(map(int, input().strip().split()))
    res = sys.stdin.readline().split()
    flag=0
    for i in range(len(res)):
        if k <= int(res[i]):
            print(i + 1)
            flag=1
            break
    if flag==0:
        print(n + 1)

发表于 2019-09-03 11:12:16 回复(0)