1.二分查找
/*
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:40.9 MB, 在所有 Java 提交中击败了5.26%的用户
*/
class Solution {
public int search(int[] nums, int target) {
if (nums==null||nums.length==0) return -1;
int left = 0;
int right = nums.length-1;
while (left<=right){
int mid = (left+right)/2;
if (nums[mid]==target) return mid;
else if (nums[mid]>target) right = mid-1;
else left = mid +1;
}
return -1;
}
}
2. x 的平方根
/*
执行用时:1 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:36.5 MB, 在所有 Java 提交中击败了5.55%的用户
*/
class Solution {
public int mySqrt(int x) {
int left = 0;
int right = x;
int temp = 0;
while(left<=right){
int mid = (right+left)/2;
if((long)mid*mid<=x) {temp = mid;left=mid+1;}
else right = mid-1;
}
return temp;
}
}
3.猜数字大小
/*
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:36.3 MB, 在所有 Java 提交中击败了10.00%的用户
*/
public class Solution extends GuessGame {
public int guessNumber(int n) {
int left = 1;
int right = n;
int mid = 0;
while(left<=right){
mid = left + (right-left)/2;
if(guess(mid)==0) return mid;
else if(guess(mid)==1) left = mid+1;
else right = mid-1;
}
return 0;
}
}
4.搜索旋转排序数组
/*
借鉴评论区大佬的思路,利用中间值和left、right值的大小比较来判断他们是否有序
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:39.3 MB,在所有 Java 提交中击败了17.74%的用户
*/
class Solution {
public int search(int[] nums, int target) {
if (nums==null||nums.length==0) return -1;
int left = 0;
int right = nums.length-1;
while (left<=right){
int mid = left + (right-left)/2;
if (nums[mid]==target) return mid;
//当左半部分是有序时
else if (nums[left]<=nums[mid]){
if (nums[left]<=target&&nums[mid]>target)
right = mid -1;
else
left = mid+1;
}
//当右半部分是有序时
else {
if (nums[mid]<target&&nums[right]>=target)
left = mid+1;
else
right = mid-1;
}
}
return -1;
}
}
5.第一个错误的版本
/*
执行用时:17 ms, 在所有 Java 提交中击败了42.34%的用户
内存消耗:36.5 MB, 在所有 Java 提交中击败了8.33%的用户
*/
public class Solution extends VersionControl {
public int firstBadVersion(int n) {
int left = 1;
int right = n;
int res = 0;
while(left<=right){
int mid = left+(right-left)/2;
if(isBadVersion(mid)) {res = mid;right = mid-1;}
else left = mid+1;
}
return res;
}
}
6.寻找峰值
/*
当nums[mid+1]比nums[mid]大时,峰值肯定在右边,反之峰值肯定在左边
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:39.4 MB, 在所有 Java 提交中击败了10.00%的用户
*/
class Solution {
public int findPeakElement(int[] nums) {
int left = 0;
int right = nums.length-1;
while (left<right){
int mid = left+(right-left)/2;
if (nums[mid]>nums[mid+1]) right = mid;
else left = mid+1;
}
return left;
}
}
7.在排序数组中查找元素的第一个和最后一个位置
/*
结合左边界的二分搜索和右边界的二分搜索
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:42.8 MB, 在所有 Java 提交中击败了70.18%的用户
*/
class Solution {
public int[] searchRange(int[] nums, int target) {
if(nums.length==0) return new int[]{-1,-1};
int left = searchLeftRange(nums,target);
int right = searchRightRange(nums,target);
if(left==-1||right==-1) return new int[] {-1,-1};
else return new int[]{left,right};
}
private int searchLeftRange(int[] nums, int target) {
int left = 0;
int right = nums.length-1;
while(left<=right){
int mid = left+(right-left)/2;
if (nums[mid]==target) right = mid-1;
else if(nums[mid]>target) right = mid - 1;
else left = mid +1;
}
if (left>=nums.length||nums[left]!=target) return -1;
else return left;
}
private int searchRightRange(int[] nums, int target) {
int left = 0;
int right = nums.length-1;
while(left<=right){
int mid = left+(right-left)/2;
if (nums[mid]==target) left = mid+1;
else if(nums[mid]>target) right = mid-1;
else left = mid+1;
}
if (right<0||nums[right]!=target) return -1;
else return right;
}
}
8.找到 K 个最接近的元素
/*
借鉴的评论区的思路,寻找所求区间的左边界
执行用时:10 ms, 在所有 Java 提交中击败了40.04%的用户
内存消耗:41.2 MB, 在所有 Java 提交中击败了11.11%的用户
*/
class Solution {
public List<Integer> findClosestElements(int[] arr, int k, int x) {
List<Integer> ret = Arrays.stream(arr).boxed().collect(Collectors.toList());
int left = 0; int right = arr.length-k-1;
while(left<=right){
int mid = left+(right-left)/2;
//当左边界与x的差值等于或者小于右边界与x的差值时,即左边界的比较大时,向左找
if(x-arr[mid]<=arr[mid+k]-x) right = mid-1;
//当左边界与x的差值大于右边界与x的差值时,即左边界的值比较小时,向右找
else if(x-arr[mid]>arr[mid+k]-x) left = mid+1;
}
return ret.subList(left, left + k);
}
}
写了半天的寻找右边界,一直出错,如果有大佬写出来了,麻烦贴一下。
9.Pow(x, n)
/*
菜鸡的我,只有捣鼓这个了。看官方解答之后,才发现人与人之间的差距这么大
*/
class Solution {
public double myPow(double x, int n) {
double temp= 0.0;
temp = Math.pow(x,n);
return temp;
}
}
/*
快速幂+递归
*/
class Solution {
public double myPow(double x, int n) {
long N = n;
return N>=0?judge(x,N):1.0/judge(x,-N);
}
private double judge(double x, long n) {
if(n==0) return 1.0;
double res = judge(x,n/2);
return n%2==0?res*res:res*res*x;
}
}
/*
快速幂+迭代
*/
class Solution {
public double myPow(double x, int n) {
long N = n;
return N>=0?judge(x,N):1.0/judge(x,-N);
}
private double judge(double x, long n) {
double res = 1.0;
double temp = x;
//将n换为二进制模式,当当前位为1时,就乘temp! 妙!
while (n>0){
if (n%2==1){
res *= temp;
}
temp*=temp;
n = n/2;
}
return res;
}
}
10.有效的完全平方数
/*
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:36.4 MB, 在所有 Java 提交中击败了9.52%的用户
*/
class Solution {
public boolean isPerfectSquare(int num) {
long left = 1;
long right = num;
while(left<=right){
long mid = left+(right-left)/2;
if(mid*mid==num) return true;
else if(mid*mid<num) left = mid+1;
else right = mid-1;
}
return false;
}
}
11.寻找比目标字母大的最小字母
/*
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:40.3 MB, 在所有 Java 提交中击败了11.11%的用户
*/
class Solution {
public char nextGreatestLetter(char[] letters, char target) {
int left = 0;
int right = letters.length-1;
int res = 0;
while(left<=right){
int mid = left+(right-left)/2;
if(letters[mid]<=target) left = mid+1;
else if(letters[mid]>target) right = mid -1;
}
if(right<0||right>=letters.length-1) return letters[0];
return letters[(right+1)%letters.length];
}
}
12.寻找旋转排序数组中的最小值
/*
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:38.9 MB, 在所有 Java 提交中击败了5.55%的用户
*/
class Solution {
public int findMin(int[] nums) {
int left = 0;
int right = nums.length-1;
while(left<right){
int mid = left+(right-left)/2;
if(nums[mid]>nums[right]) left = mid+1;
else right = mid;
}
return nums[left];
}
}
13.寻找旋转排序数组中的最小值Ⅱ
/*
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:39.8 MB, 在所有 Java 提交中击败了60.00%的用户
*/
class Solution {
public int findMin(int[] nums) {
int left = 0;
int right = nums.length-1;
while(left<right){
int mid = left+(right-left)/2;
if(nums[mid]>nums[right]) left = mid+1;
else if(nums[mid]==nums[right]) right = right-1;
else right = mid;
}
return nums[left];
}
}
14.两个数组的交集
/*
这东西咋用二分实现
执行用时:15 ms, 在所有 Java 提交中击败了5.37%的用户
内存消耗:39.3 MB, 在所有 Java 提交中击败了5.72%的用户
*/
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
int len1 = nums1.length;
int len2 = nums2.length;
LinkedList<Integer> list = new LinkedList<Integer>();
for(int i = 0;i<len1;i++){
for(int j = 0;j<len2;j++){
if(nums1[i]==nums2[j]&&!list.contains(nums1[i])) list.add(nums1[i]);
}
}
Integer temp[] = Arrays.copyOfRange(list.toArray(), 0, list.size(), Integer[].class);
int[] arr = Arrays.stream(temp).mapToInt(Integer::valueOf).toArray();
return arr;
}
}
15.寻找重复数
/*
哇,这个运行时间很真实了,太菜了!
执行用时:1314 ms, 在所有 Java 提交中击败了5.04%的用户
内存消耗:40.9 MB, 在所有 Java 提交中击败了6.67%的用户
*/
class Solution {
public int findDuplicate(int[] nums) {
int len = nums.length;
if(len==0) return 0 ;
LinkedList<Integer> res = new LinkedList<>();
int ans = 0;
for(int i=0;i<len;i++){
if(!res.contains(nums[i])) res.add(nums[i]);
else return nums[i];
}
return ans;
}
}
/*
官方题解
执行用时:3 ms, 在所有 Java 提交中击败了60.55%的用户
内存消耗:40.1 MB, 在所有 Java 提交中击败了6.67%的用户
*/
class Solution {
public int findDuplicate(int[] nums) {
int left = 0;
int right = nums.length-1;
while(left<right){
//因为数组中的元素个数为n+1,而元素的取值为0-n,所以mid就为数组元素的中位数
int mid = left+(right-left)/2;
int temp = 0;
// 循环整个数组,判断值小于mid的个数,
for(int i = 0;i<nums.length;i++){
if(mid>=nums[i]) temp++;
}
if(temp>mid) right = mid;
else left = mid+1;
}
return left;
}
}