首页 > 试题广场 >

二分查找-II

[编程题]二分查找-II
  • 热度指数:188975 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
请实现有重复数字的升序数组的二分查找
给定一个 元素有序的(升序)长度为n的整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的第一个出现的target,如果目标值存在返回下标,否则返回 -1

数据范围:
进阶:时间复杂度,空间复杂度
示例1

输入

[1,2,4,4,5],4

输出

2

说明

从左到右,查找到第1个为4的,下标为2,返回2    
示例2

输入

[1,2,4,4,5],3

输出

-1
示例3

输入

[1,1,1,1,1],1

输出

0
要注意题目要求找第一个出现的,所以在找到时再往前进行二分查找(递归)
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 如果目标值存在返回下标,否则返回 -1
     * @param nums int整型一维数组 
     * @param target int整型 
     * @return int整型
     */
    public int search (int[] nums, int target) {

        return search(nums, 0, nums.length-1, target);
    }
    
    
    public int search (int[] nums, int left, int right, int target) {
        int middle = (left+right)/2;
        while(left <= middle && middle <= right) {
            if (nums[middle] == target) {
                // 找到了,再往前找(递归)
                int prev = search(nums, left, middle-1, target);
                return prev==-1? middle : prev;
            }
            // 小于,从左边找
            else if (target < nums[middle]) {
                right = middle-1;
            } else {
                left = middle+1;
            }
            middle=(left+right)/2;
        }
        
        return -1;
    }
}


发表于 2021-09-03 17:40:15 回复(0)
import java.util.*;
public class Solution {
    public int search (int[] nums, int target) { //二分查找的一个变形,本题要求有重复数字,所以处理重复数组是一个关键
        int low=0;
        int high=nums.length-1;
        int mid=0;
        while(low<=high){
            mid=(low+high)/2;
            if(nums[mid]==target){
                while(mid!=0&&(nums[mid-1]==nums[mid])){  //判断所确定元素之前是否有相同元素
                    mid--;
                }
                return mid;
            }else if(nums[mid]>target){
                high=mid-1;
            }else{
                low=mid+1;
            }
        }
        return -1;
    }
}


发表于 2021-03-13 09:04:54 回复(0)

看一个测试用例[1,2,2,3,4],2

无论是否第一个target,其下标索引都一定会在区间[left, mid]中(即nums[mid]>=target),如此将会right=mid。

public class Solution {
    public int search (int[] nums, int target) {
        // write code here
        int left = 0;
        int right = nums.length - 1;
        while (left < right) {
            // 不要使用(left+right)/2,虽然结果相同,但是若left和right太大,直接相加会导致整形溢出
            int mid = left + (right - left) / 2;
            if (nums[mid] < target)
                left = mid + 1;
            else if (nums[mid] >= target)
                //[left,hight]中去寻找第一个target
                right = mid;
        }
        //right>=0是为了应对这种测试用例[],0
        return right>=0 && nums[right]==target ? right : -1;
    }
}

或者,算了,芝姐套用二分查找的框架:

public class Solution {
    public int search (int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;

        //注意这里是<=
        while (left <= right) { 
            // 不要使用(left+right)/2,虽然结果相同,但是若left和right太大,直接相加会导致整形溢出
            int mid = left + (right - left) / 2;
            if (nums[mid] == target) {
                //判断mid之前是否有相同元素(即是否是第一个target)
                //mid!=0,注意是!=,这是输出结果的边界条件
                while (mid!=0 && (nums[mid-1]==nums[mid]))
                    --mid;
                return mid;
            }
            else if (nums[mid] < target)
                left = mid + 1;
            else if (nums[mid] > target)
                //[left,hight]中去寻找第一个target
                right = mid - 1;
        }
        return -1;
    }
}
编辑于 2021-04-30 22:31:24 回复(1)
class Solution:
    def search(self , nums , target ):
        # write code here
        left,right=0,len(nums)-1
        while left<=right:
            mid=(left+right)//2
            if nums[mid]==target:
                temp=mid
                while temp>=0 and nums[temp] == target:
                    temp -= 1
                return temp + 1
            elif nums[mid]>target:
                right=mid-1
            else:
                left=mid+1
        else:
            return -1
        

发表于 2021-08-19 21:53:29 回复(0)
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 如果目标值存在返回下标,否则返回 -1
     * @param nums int整型一维数组 
     * @param target int整型 
     * @return int整型
     */
    public int search (int[] nums, int target) {
        if(nums.length == 0) return -1;
        // write code here
        int l = 0;
        int r = nums.length - 1;
        while(l < r){
            int mid = l + r >> 1;
            if(nums[mid] >= target) r = mid;
            else l = mid + 1;
        }
        return nums[l] == target ? l : -1;
    }
}

发表于 2021-08-17 00:07:09 回复(0)
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 如果目标值存在返回下标,否则返回 -1
     * @param nums int整型一维数组 
     * @param target int整型 
     * @return int整型
     */
    public int search (int[] nums, int target) {
        // write code here
        if(nums == null || nums.length == 0) {
            return -1;
        }
        int left = 0, right = nums.length - 1;
        while(left <= right) {
            //注意mid的求法
            int mid = left + (right - left) >> 1;
            //注意中间元素与目标元素比较
            if(nums[mid] >= target) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
            if(nums[left] == target) {
                return left;
            }
            //不要忘记累加操作
            left++;
            right++;
        }
        return -1;
    }
}

发表于 2022-01-10 09:56:32 回复(3)
class Solution:
    def search(self , nums: List[int], target: int) -> int:
        # write code here
        total_len=len(nums)
        max_index=total_len-1
        min_index=0
        while max_index >= min_index:
            index=(max_index+min_index)//2
            if nums[index]>target:
                max_index=index-1
            elif nums[index]<target:
                min_index=index+1
            elif nums[index] == target:
                if max_index==min_index:
                    return index
                else:
                    max_index=index
        return -1
发表于 2022-01-07 21:15:09 回复(0)
class Solution {
public:
    int search(vector<int>& nums, int target) {
        if(nums.empty()) return -1;
        int left = 0, right = nums.size()-1;
        while(left<right){
            int mid = (left+right)/2;
            if(nums[mid]>target) right = mid-1;
            else if(nums[mid]<target) left = mid+1;
            else right = mid;
        }
        return nums[left]==target? left:-1;
    }
};


发表于 2021-12-21 01:22:21 回复(0)
public int search (int[] nums, int target) {
        // write code here
        int startIndex = 0;
        int endIndex = nums.length-1;
        int midIndex = 0;
        while(startIndex<=endIndex){
            midIndex = (startIndex+endIndex)/2;
            if(nums[midIndex]==target){
                while(midIndex!=0&&nums[midIndex-1] == nums[midIndex]){
                    --midIndex;
                }
                return midIndex;
            }else if(nums[midIndex]>target){
                endIndex = midIndex-1;
            }else if(nums[midIndex]<target){
                startIndex = midIndex+1;
            }
          }
         return -1;
       }
发表于 2021-11-28 16:51:24 回复(0)

思路:利用while循环,设置左右指针left,right。跳出循环的条件为left>right。mid = (left + right) / 2; 当中间值大于target,将left指针设置为mid + 1。当中间值小于target,将right指针设置为mid - 1;
当找到和target值相同的值时,需要遍历前面是否有相同的值,最小的为所要求的结果。单循环条件一定要注意加上mid <= 1。

public int search (int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        while (left <= right) {
            int mid = (right + left) / 2;
            if (nums[mid] == target) {
                while (mid >= 1 && nums[mid] == nums[mid - 1]) {
                    mid--;
                }
                return mid;
            } else if (nums[mid] > target) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return -1;
    }
发表于 2021-09-29 23:03:57 回复(0)
直接用find函数,然后return就好了;//没想到有生之年也能一行代码解决问题
return (find(nums.begin(), nums.end(), target)-nums.begin()+1)%(nums.size()+1)-1;

发表于 2021-09-26 16:08:20 回复(1)
function search( nums ,  target ) {
    // write code here
    let index = -1;
    let low = 0;
    let hight = nums.length-1;
    while(hight >= low){
//这里要注意指针的要大于等于,因为有可能出现最后一个是要找的目标值
        let mid = low + Math.floor((hight - low)/2);
        if(nums[mid] == target){
            index = mid;
            hight = mid -1;
        }else if(nums[mid] < target){
            low = mid +1;
        }else{
            hight = mid-1;
        }
        
    }
    return index;
    
}
发表于 2021-09-17 14:05:42 回复(0)
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 如果目标值存在返回下标,否则返回 -1
     * @param nums int整型vector 
     * @param target int整型 
     * @return int整型
     */
    int search(vector<int>& nums, int target) {
        // write code here
        int start = 0, end = nums.size() - 1, middle;
        while (start <= end) {
            middle = start + ((end - start) >> 1);
            if (nums[middle] == target && (middle == 0 || nums[middle - 1] < nums[middle])) return middle;
            else if (nums[middle] >= target) end = middle - 1;
            else start = middle + 1;
        }
        return -1;
    }
};

发表于 2021-09-07 22:30:09 回复(0)
int cond(int* nums, int mid, int target) {
  return *(nums + mid) >= target;
}

int binary_search(int* nums, int numsSize, int target, int (*cond) (int*, int, int)) {
  int l = 0, r = numsSize, m;
  while (l < r) {
    m = l + ((r - l) >> 1);
    if (cond(nums, m, target)) r = m;
    else l = m + 1;
  }
  return l;
}

int search(int* nums, int numsLen, int target) {
  int index = binary_search(nums, numsLen, target, cond);
  if (index == numsLen || *(nums + index) > target)
    return -1;
  return index;
}

发表于 2021-08-02 19:51:07 回复(0)
//本来是一行的,但是这一行太长导致放不下(面试可别这么做)
class Solution {
public:
    int search(vector<int>& nums, int target) {
        return binary_search(nums.begin(), nums.end(), target)?distance(nums.begin(),lower_bound(nums.begin(), nums.end(), target)):-1;
    }
};
编辑于 2021-06-22 05:17:56 回复(0)
golang代码,调试正确,提交后,用例12没有实际输出?有人可以解答下吗,谢谢

func search( nums []int ,  target int ) int {
    fmt.Scan(&nums, &target)
    return BinarySearch(nums, target, 0, len(nums)-1)
}

func BinarySearch(nums []int, target, start, end int) int {
    index := -1 
    for start <= end {
        mid := start + (end - start) / 2 
        if nums[mid] == target {
            index = mid
            end = mid - 1
        }else if nums[mid] > target {
            end = mid - 1
        }else {
            start = mid + 1
        }
    }
    return index

编辑于 2021-03-09 22:40:05 回复(7)
1、二分法的思想精髓就是我们把数组一分为二得到中间值,来判断该值和我们目标值的大小。
2、因为该数组是个升序数组,所以如果中间的值大于目标值,那么值就在前半段,我们把后面的指针放到mid-1这个位置
3、如果之间的值小于目标值,那么值就在后半段,我们把前面的指针放到mid+1这个位置
4、如果中间mid指针指向的值和目标值相等,那么我们也不要急着返回,假如该指针前面一位也是该值,那么我们返回的值就不对了
5、就着该指针往前不断减1,直到不相等,否则返回值会不断减1

代码如下:
public int Search(int[] nums,int target){
    //前一个为0
    int front = 0;
    //后一个为数组长度-1
    int last = nums.length-1;
    //返回结果先设为0
    int index = 0;
    //首先满足的条件为左指针小于等于右指针
    while(front<=last){
        //先计算出中间指针的值
        int mid = front + (last - front)/2;
        //如果中间指针的值和目标值相等
        if(nums[mid]==target){
            //看看左边是否还有相等值,直到不相等为止
            while(mid!=0 && nums[mid-1]==nums[mid]){
                index--;
            }
            return index;
        }
        else if(nums[mid]<target){
            //如果中间节点小于目标值,那么就在右半边,右指针不动,左指针在中间节点右侧
            left = mid+1;
        }
        else{
            //同理在左半边,那么右指针变为中间点左一个
            right = mid-1;
        }
        return -1;
    }
}


发表于 2021-06-08 21:46:22 回复(1)
 for(int i=0;i<nums.length;i++){
            if(target==nums[i]){ 
                return i;
            }  
        }
        return -1;
    }
发表于 2021-10-22 18:16:50 回复(0)
import java.util.*;


public class Solution {

    public int search (int[] nums, int target) {
        for(int x=0;x<nums.length-1;x++){
            if(nums[x]==target){
                return x;
            }
        }
        return -1;
    }
}

这个需要二分吗,我没太看懂,直接遍历,如果有,返回第一个出现的序号,如果没有,返回-1
发表于 2021-08-26 15:18:42 回复(0)
百度搜索架构一面,面试官一直说 low <= high 有问题,可能他背的答案是 < 吧😂
int search(vector<int>& nums, int target) {
    int low = 0, high = nums.size() - 1;
    while (low <= high) {
        int mid = low + (high - low) / 2;
        if (nums[mid] >= target) {
            high = mid - 1;
        } else {
            low = mid + 1;
        }
    }
    if (low < nums.size() && nums[low] == target) {
        return low;
    }
    return -1;
}


发表于 2021-08-01 16:49:19 回复(2)

问题信息

难度:
200条回答 5375浏览

热门推荐

通过挑战的用户

查看代码