leetcode-探索二分查找

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;
        
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值