二分常考面试题


二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法,前提是数据结构必须先排好序,可以在数据规模的对数时间复杂度内完成查找。下面的题目都是基于整数二分,不要搞错哦!二分细节太多了(大家可以理解为玄学,哈哈哈!)

二分代码模板

话不多说,直接上代码。

bool check(int x) {/* ... */} // 检查x是否满足某种性质

// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:
int bsearch_1(int l, int r)
{
    while (l < r)
    {
        int mid = l + r >> 1;
        // check()判断mid是否满足性质
        if (check(mid)) r = mid;    
        else l = mid + 1;
    }
    return l;
}
// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:
int bsearch_2(int l, int r)
{
    while (l < r)
    {
    	//注意:这种划分的话mid需要+1,否则会造成死循环
        int mid = l + r + 1 >> 1;
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    return l;
}

下面结合图片来理解一下:
在这里插入图片描述

0~n-1中缺失的数字

https://leetcode-cn.com/problems/que-shi-de-shu-zi-lcof/

class Solution {
    public int missingNumber(int[] nums) {
        if(nums == null || nums.length == 0) {
            return -1;
        }
        int l = 0;
        int r = nums.length - 1;
        while(l < r) {
            int mid = l + r >> 1;
            if(nums[mid] != mid) {
                r = mid;
            }else {
                l = mid + 1;
            }
        }
        if(nums[l] == l) {
            l++;
        }
        return l;
    }
}

搜索插入位置

https://leetcode-cn.com/problems/search-insert-position/

//for循环O(n)
class Solution {
    public int searchInsert(int[] nums, int target) {
        for(int i = 0; i < nums.length;i++){
        if(nums[i] >= target){
            return i;
        }
    }
    return nums.length;
    }
}
//二分
class Solution {
    public int searchInsert(int[] nums, int target) {
         int left = 0, right = nums.length - 1;
        while(left <= right) {
            int mid = left + right >> 1;
            if(nums[mid] == target) {
                return mid;
            } else if(nums[mid] < target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return left;
    }
}

在排序数组中查找数字 I

https://leetcode-cn.com/problems/zai-pai-xu-shu-zu-zhong-cha-zhao-shu-zi-lcof/

class Solution {
    public int search(int[] nums, int target) {
        if(nums == null || nums.length == 0) {
            return 0;
        }
        int l = 0, r = nums.length - 1;
        while(l < r){
            int mid = l + r >> 1;
            if(nums[mid] >= target) {
                r = mid;
            }else {
                l = mid + 1;
            }
        }
        int count = 0;
        while(l < nums.length && nums[l] == target) {
            count++;
            l++;
        }
        return count;
    }
}

搜索二维矩阵I

题目链接:https://leetcode-cn.com/problems/search-a-2d-matrix/

在这里插入图片描述

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
    if(matrix == null || matrix.length == 0) {
            return false;
        }
        int i = 0, j = matrix[0].length - 1;
        while(i < matrix.length && j >= 0) {
            if(matrix[i][j] > target) {
                j--;
            }else if(matrix[i][j] < target) {
                i++;
            }else {
                return true;
            }
        }
        return false;
    }
}

搜索二维矩阵II

https://leetcode-cn.com/problems/search-a-2d-matrix-ii/
在这里插入图片描述

class Solution {
    public boolean searchMatrix(int[][] nums, int target) {
        if(nums == null || nums.length == 0 || nums[0].length == 0) {
            return false;
        }
        int n = nums.length - 1;
        int m = nums[0].length - 1;
        int i = 0;
        int j = m;
        while(i <= n && j >= 0) {
            if(nums[i][j] < target) {
                i++;
            }else if(nums[i][j] > target) {
                j--;
            }else {
                return true;
            }
        }
        return false;
    }
}

旋转数组中的最小数字

问题链接:https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof/

class Solution {
    public int minArray(int[] nums) {
        if(nums == null || nums.length == 0) return -1;
        int n = nums.length - 1;    
        while(n > 0 && nums[n] == nums[0]) n--;
        if(nums[n] > nums[0]) return nums[0];
         int l = 0, r = n;
        while(l < r) {
            int mid = l + r >> 1;
            if(nums[mid] < nums[0]) {
                r = mid;
            }else{
                l = mid + 1;
            }
        }
        return nums[l];
    }
}

搜索旋转排序数组

https://leetcode-cn.com/problems/search-in-rotated-sorted-array-ii/

class Solution {
    public boolean check(int[] nums, int target, int l, int r) {
        while(l < r) {
            int mid = l + r >> 1;
            if(nums[mid] >= target) {
                r = mid;
            }else {
                l = mid + 1;
            }
        }
        return nums[l] == target;
    }
    public boolean search(int[] nums, int target) {
        if(nums == null || nums.length == 0) return false;
        int n = nums.length - 1;
        while(n > 0 && nums[n] == nums[0]) n--;
        int l = 0, r = n;
        while(l < r) {
            int mid = l + r >> 1;
            if(nums[mid] < nums[0]) {
                r = mid;
            }else {
                l = mid + 1;
            }
        }
        if(target >= nums[0]) return check(nums, target, 0, l);
        else return check(nums, target, l, n);
    }
}

在排序数组中查找元素中第一个和最后一个位置

问题链接:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/

问题描述:

class Solution {
    public int[] searchRange(int[] nums, int target) {
        if(nums == null || nums.length == 0) {
            return new int[]{-1, -1};
        }
        int n = nums.length - 1;
        int l = 0, r = n;
        while(l < r) {
            int mid = l + r >> 1;
            if(nums[mid] >= target) {
                r = mid;
            }else {
                l = mid + 1;
            }
        }
        if(nums[l] != target) {
            return new int[]{-1, -1};
        }
       
        while(r < n) {
            if(nums[r] == nums[r + 1]) {
                r++;
            }else {
                break;
            }
        }
        return new int[]{l, r};
    }
}

寻找峰值

问题链接:https://leetcode-cn.com/problems/find-peak-element/

class Solution {
    public int findPeakElement(int[] nums) {
        if(nums == null || nums.length == 0) return -1;
        int n = nums.length - 1;
        int l = 0, r = n;
        while(l < r) {
            int mid = l + r >> 1;
             if (nums[mid] > nums[mid + 1]) {
                r = mid;
            } else {
                l = mid + 1;
            }
        }
        return l;
    }
}

寻找重复数

问题链接:https://leetcode-cn.com/problems/find-the-duplicate-number/

class Solution {
    public int findDuplicate(int[] nums) {
        if(nums == null || nums.length == 0) return -1;
        int n = nums.length - 1;
        int l = 0, r = n;
        while (l < r) {
            int mid = l + r >> 1;      
            int cnt = 0;
            for (int num : nums) {
                if (num <= mid) {
                    cnt += 1;
                }
            }
            if (cnt > mid) {
            
                r = mid;
            } else {
                l = mid + 1;
            }
        }
        return l;
    }
}

pow(x,n) 快速幂

题目链接:https://leetcode-cn.com/problems/powx-n/

class Solution {
    public double myPow(double x, int n) {
        if(x == 0) return 0;
        long b = n;
        double res = 1.0;
        if(b < 0) {
            x = 1 / x;
            b = -b;
        }
        while(b > 0){
            // 最后一位为1,需要乘上该位上的权重
            if((b & 1) == 1){
                res *= x;
            }
            x *= x;
            b >>= 1;
        }
        return res;
    }
}

在两个长度相等的排序数组中找到上中位数

https://www.nowcoder.com/practice/6fbe70f3a51d44fa9395cfc49694404f?tpId=117&&tqId=37808&&companyId=665&rp=1&ru=/company/home/code/665&qru=/ta/job-code-high/question-ranking

  • 暴力解法
import java.util.*;
public class Solution {
    public int findMedianinTwoSortedAray (int[] arr1, int[] arr2) {
        // write code here
        int index1 = 0, index2 = 0;
        int count = 0;
        int min = 0;
        while(count < arr1.length){
            if(arr1[index1] < arr2[index2]){
                min = arr1[index1++];
                count++;
            }else{
                min = arr2[index2++];
                count++;
            }
        }
        return min;
    }
}
  • 二分
import java.util.*;
public class Solution {
    public int findMedianinTwoSortedAray (int[] arr1, int[] arr2) {
        // write code here
        int l1 = 0,l2 = 0;
        int r1 = arr1.length - 1, r2 = arr2.length - 1;
        int mid1 = 0, mid2 = 0;
        while(l1 < r1){
            mid1 = l1 + r1 >> 1;
            mid2 = l2 + r2 >> 1;
            int offset = (r1 - l1) % 2;
            if(arr1[mid1] == arr2[mid2]){
                return arr1[mid1];
            }else if ((arr1[mid1] > arr2[mid2])){
                r1 = mid1 ;
                l2 = mid2 + offset;
            }else{
                l1 = mid1 + offset;
                r2 = mid2 ;
            }
        }
        return arr1[l1] < arr2[l2] ? arr1[l1] : arr2[l2];
    }
}

持续更新中。。。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值