zoukankan      html  css  js  c++  java
  • <Binary Search> 81 (高频)34 (很难hard, 高频)315 (hard)354

    81. Search in Rotated Sorted Array II

    如果中间的数小于最右边的数,则右半段是有序的,若中间数大于最右边数,则左半段是有序的。而如果可以有重复值,就会出现来面两种情况,[3 1 1] 和 [1 1 3 1],对于这两种情况中间值等于最右值时,目标值3既可以在左边又可以在右边,那怎么办么,对于这种情况其实处理非常简单,只要把最右值向左一位即可继续循环,如果还相同则继续移,直到移到不同值为止

    class Solution {
        public boolean search(int[] nums, int target) {
            int n = nums.length, left = 0, right = n - 1;
            while(left <= right){
                int mid = left + (right - left) / 2;
                if(nums[mid] == target) return true;
                if(nums[mid] < nums[right]){
                    if(nums[mid] < target && target <= nums[right]) left = mid + 1;
                    else right = mid - 1;
                }else if(nums[mid] > nums[right]){
                    if(nums[left] <= target && target < nums[mid]) right = mid - 1;
                    else left = mid + 1;
                }else --right;
            }
            return false;
        }
    }

     34. Find First and Last Position of Element in Sorted Array(高)

    上面的算法不是严格意义上的 O(logn) 的算法,因为在最坏的情况下会变成 O(n),比如当数组里的数全是目标值的话,从中间向两边找边界就会一直遍历完整个数组,那么下面来看一种真正意义上的 O(logn) 的算法,使用两次二分查找法,第一次找到左边界,第二次调用找到右边界即可

    class Solution {
        public int[] searchRange(int[] nums, int target) {
            int[] res = new int[2];
            res[0] = -1;
            res[1] = -1;
            if(nums == null || nums.length == 0) return res;
            res[0] = findFirst(nums, target);
            res[1] = findLast(nums,target);
            return res;
        }
        
        private int findFirst(int[] nums, int target){
            int start = 0, end = nums.length - 1;
            while(start + 1 < end){
                int mid = start + (end - start) / 2;
                if(nums[mid] >= target){// 往左边找
                    end = mid;
                }else{
                    start = mid;
                }
            }
            if(nums[start] == target) return start;
            else if(nums[end] == target) return end;
            return -1;
        }
        
        private int findLast(int[] nums, int target){
            int start = 0, end = nums.length - 1;
            while(start + 1 < end){
                int mid = start + (end - start) / 2;
                if(nums[mid] <= target){//往右边找
                    start = mid;
                }else{
                    end = mid;
                }
            }
            if(nums[end] == target) return end;
            else if(nums[start] == target) return start;
            return -1;
        }
    }

    354. Russian Doll Envelopes

    以width升序, 当width相同时采用降序。

    信封的宽度还是从小到大排,但是宽度相等时,我们让高度大的在前面。那么现在问题就简化了成了找高度数字中的LIS,完全就和之前那道Longest Increasing Subsequence一样了

    t

    class Solution {
        public int maxEnvelopes(int[][] envelopes) {
            if(envelopes.length < 2) return envelopes.length;
            
            Arrays.sort(envelopes, new EnvelopeComparator());
            int[] dp = new int[envelopes.length];
            int size = 0;
            
            for(int[] envelope : envelopes){
                int left = 0, right = size, mid = 0;
                while(left < right){
                    mid = left + (right - left) / 2;
                    if(dp[mid] < envelope[1]) left = mid + 1;
                    else right = mid;
                }
                
                dp[left] = envelope[1];
                if(left == size) size++;
            }
            return size;
        }
        
        class EnvelopeComparator implements Comparator<int[]>{
            public int compare(int[] e1, int[] e2){
                return e1[0] == e2[0] ? e2[1] - e1[1] : e1[0] - e2[0];
            }
        }
    }

    315. Count of Smaller Numbers After Self

    BST: 时间复杂度O(nlongn) ~O(n^2 ),当BST不平衡时时间复杂度O(n ^2)。用merge sort能够稳定在O(nlongn),但较难理解。

    把数组从后往前添加到BST中,

      1. val == root.val, root.count++,表示这个节点的值相同的个数+1

      2. val < root.val,说明这个数值更小,添加到左子树内.

      

    ,

    class Solution {
        class Node{
            int val, count, left_count;
            Node left, right;
            public Node(int val){
                this.val = val;
                this.count = 1;
            }
            public int less_or_equal(){
                return count + left_count;
            }
        }
        public List<Integer> countSmaller(int[] nums) {
            List<Integer> ans = new ArrayList<>();
            if(nums.length == 0) return ans;
            int n = nums.length;
            Node root = new Node(nums[n - 1]);
            ans.add(0);
            for(int i = n - 2; i >= 0; i--){
                ans.add(insert(root, nums[i]));    
            }
            Collections.reverse(ans);
            return ans;
        }
        
        private int insert(Node root, int val){
            if(root.val == val){
                ++root.count;
                return root.left_count;
            }else if(val < root.val){
                ++root.left_count;
                if(root.left == null){
                    root.left = new Node(val);
                    return 0;
                }
                return insert(root.left, val);
            }else{
                if(root.right == null){
                    root.right = new Node(val);
                    return root.less_or_equal();
                }
                return root.less_or_equal() + insert(root.right, val);
            }
        }
    }
  • 相关阅读:
    MySQL常用命令记录
    VM新安装centos7无法连接网络的问题
    nginx + tomcat实现负载均衡
    Redis集群分布(Windows版)
    7.2 基础知识ArrayMap
    7.1 基础知识Android消息处理机制
    6.5 Android硬件访问服务使用反射
    6.4 Android硬件访问服务编写HAL代码
    6.3 Android硬件访问服务APP代码
    6.2、Android硬件访问服务编写系统代码
  • 原文地址:https://www.cnblogs.com/Afei-1123/p/12021691.html
Copyright © 2011-2022 走看看