二分
二分查找也称折半查找(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;
}
}
在两个长度相等的排序数组中找到上中位数
- 暴力解法
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];
}
}
持续更新中。。。。。。