今天做的题目是有关二分查找的:
1.二分查找基本题目(力扣704):
在以前的基础上,考虑给定值比数组中最小的小或最大的大的情况。
public int search(int[] nums, int target) { int low = 0; int high = nums.length-1; int result; if((target<nums[0])||(target>nums[nums.length-1])) return -1; while ((nums[(low+high)/2] != target)&&(low<=high)) { if(nums[(low+high)/2]<target){ low = (low+high)/2+1; } else high = (low+high)/2-1; } if (low>high) return -1; else return (low+high)/2; }
2.二分查找+插入位置(力扣35):
题目要求在O(logn)的时间复杂度内完成,因此考虑二叉树结构,采用二分查找;若不在则返回插入位置,若存在则插到相同元素之前。
public int searchInsert(int[] nums, int target) { if(target<nums[0]) return 0; if(target>nums[nums.length-1]) return nums.length; int low = 0; int high = nums.length-1; while ((nums[(low+high)/2])!=target&&(low<=high)) { if (nums[(low+high)/2]<target) low = (low+high)/2+1; else high = (low+high)/2-1; } //根据存在不存在,分别返回 if(low>high) return (low+high)/2+1; else return (low+high)/2; }
3.二分查找提升题(力扣34)
题目同样要求在O(logn)的时间复杂度内完成,继续选择二叉树结构,由于数组升序,选择二分查找。要注意数组越界问题。
public int[] searchRange(int[] nums, int target) { // if(nums.length == 0) // return new int[]{-1,-1}; if((nums.length == 0)||(target<nums[0])||(target>nums[nums.length-1])) return new int[]{-1,-1}; int low = 0; int high = nums.length-1; int i,j;//用来指向目标值在数组中的开始和结束位置 while (((nums[(low+high)/2])!=target) && (low<=high)){ if(nums[(low+high)/2] < target) low = (low+high)/2+1; else high = (low+high)/2-1; } if (low>high) return new int[]{-1,-1}; else { i = (low+high)/2; j = (low+high)/2; while ((i>0)&&(nums[i-1] == target)) i--; while ((j<nums.length-1)&&(nums[j+1] == target)) j++; } return new int[]{i,j}; }
4.二分查找应用题,x的平方根(力扣69)
当x大于1时,其平方根小于等于x/2,根据此,在1到x/2的区间内查找其平方根,属于二分查找的应用。同时避免数过大,将乘法变为除法,也要避免除以0。
public int mySqrt(int x) { if(x==0||x==1) return x; //low设置为1防止下面mid==0造成除0 int low = 1; //当x>1时,其平方根小于等于这个数的一半 int high = x/2; int mid = (low+high)/2; //防止mid的平方大于2^31-1,循环中采用除法 while (low<=high){ if(mid == x/mid) return mid; else if(mid>x/mid){ high = mid-1; mid = (low+high)/2; } else{ low = mid+1; mid = (low+high)/2; } } return mid; }
5.二分查找应用题,跟完全平方有关(力扣367) 这里注意int类型的数运算完会向下取整(如2 == 5/2 是成立的),因此将mid定义为double类型(2.0 == 5/2.0 是不成立的) public boolean isPerfectSquare(int num) { if(num == 0 || num == 1) return true; int low = 1; int high = num/2; double mid = (low+high)>>1; while (low<=high){ if(mid == num/mid) return true; else if(mid < num/mid) { low = (int)mid+1; mid = (low+high)>>1; } else { high = (int)mid-1; mid = (low+high)>>1; } } return false; }