二分

441 阅读2分钟

最长递增子序列

描述 给定数组arr,设长度为n,输出arr的最长递增子序列。(如果有多个答案,请输出其中 按数值(注:区别于按单个字符的ASCII码值)进行比较的 字典序最小的那个)

示例1 输入: [2,1,5,3,6,4,8,9,7] 返回值: [1,3,4,8,9]

示例2 输入: [1,2,8,6,4] 返回值: [1,2,4]

说明: 其最长递增子序列有3个,(1,2,8)、(1,2,6)、(1,2,4)其中第三个 按数值进行比较的字典序 最小,故答案为(1,2,4)

    public int[] LIS (int[] arr) {
        // write code here
        int len=1;
        int n=arr.length;
        if(n==0){
            return arr;
        }
        //dp[i]记录以arr[i]结尾递增子序列的长度
        int[] dp=new int[n];
        //d[i]表示长度为i,最后一个元素的最小值
        int[] d = new int[n+1];
        d[1]=arr[0];
        dp[0]=1;
        for(int i=1;i<n;i++){
            if(arr[i]>d[len]){
                d[++len]=arr[i];
                dp[i]=len;
            }else{
                //再数组d中找到第一个比arr[i]小的元素,将d[k+1]它的值更新为arr[i]
                int l=1,r=len,pos=0;
                while(l<=r){
                    int mid=(l+r)>>1;
                    if(d[mid]<arr[i]){
                        pos=mid;
                        l=mid+1;
                    }else{
                        r=mid-1;
                    }
                }
                d[pos+1]=arr[i];
                dp[i]=pos+1;
            }
        }
        int[] res = new int[len];
        for(int i=n-1;i>=0;--i){
            if(dp[i]==len){
                res[--len]=arr[i];
            }
        }
        
        return res;
    }

0~n-1中缺失的数字

leetcode-cn.com/problems/qu…

    public int missingNumber(int[] nums) {
        int l=0,r=nums.length-1;
        while(l<=r){
            int mid=(l+r)>>1;
            if(nums[mid]>mid){
                r=mid-1;
            }else{
                l=mid+1;
            }
        }
        return l;
    }

在排序数组中查找元素的第一个和最后一个位置

        if(nums==null||nums.length==0){
            return  new int[]{-1,-1};
        }
        int start=searchStart(nums,target);
        if(start==-1){
            return new int[]{-1,-1};
        }
        int end=start;
        for(;end<nums.length;end++){
            if(nums[end]!=target){
                break;
            }
        }
        return new int[]{start,end-1};
    }

    public int searchStart(int[] nums,int target){
        int l=0,r=nums.length-1;
        if(r==0){
             return nums[l]==target?l:-1;
        }
        while(l<r){
            int mid=(l+r)>>1;
            if(nums[mid]>=target){
                r=mid;
            }else{
                l=mid+1;
            }
        }
        return nums[l]==target?l:-1;
    }

完全二叉树的节点个数

    public int countNodes(TreeNode root) {
        if(root==null){
            return 0;
        }
        TreeNode node=root;
        int level=0;
        while(node.left!=null){
            level++;
            node=node.left;
        }
        int left= 1<<level,right=(1<<(level+1))-1;

        while(left<right){
            int mid=(right-left+1)/2+left;
            if(exists(root,level, mid)){
                left=mid;
            }else{
                right=mid-1;
            }
        }
        return left;
    }

    private boolean exists(TreeNode root,int level,int k){
        TreeNode node=root;
        int bit=1<<(level-1);
        while(node!=null && bit>0){
            if((bit&k)==0){
                node=node.left;
            }else{
                node=node.right;
            }
            bit>>=1;
        }
        return node!=null;
    }

寻找两个正序数组的中位数

leetcode-cn.com/problems/me…

//道理我都懂,就是写不出来,气死了