算法-------LIS算法(Java版本)

題目

LIS(Longest Increasing Subsequence)最長上升(不下降)子序列

解決方法:

方法一:
    public int lengthOfLIS(int[] nums) {
        int[] dp = new int[nums.length];
        int len = 0;
        for (int num : nums) {
            int i = Arrays.binarySearch(dp, 0, len, num);
            if (i < 0) {
                i = -(i + 1);
            }
            dp[i] = num;
            if (i == len) {
                len++;
            }
        }
        return len;
    }
補充:
        //binarySearch 方法 如果找到 返回正數  如果數字正好在第0個位置 那麼就返回0        //
        // 否則返回負數
        //如果返回負數,負數的值爲 -(1+理論上存在的index)
        //比如下面的例子  3應該出現的位置 在第三個 所以返回-(1 + 2)
        int[] ints = {1,2,4};
        System.out.println(Arrays.binarySearch(ints, 0, ints.length, 3));

        //這個直接返回0
        System.out.println(Arrays.binarySearch(ints, 0, ints.length, 1));
方法二:
    public int longestIncreceSubsquence2(int[] nums){
        int piles = 0, n = nums.length;
        int[] top = new int[n];
        for (int i = 0; i < n; i++) {
            // 要處理的撲克牌
            int poker = nums[i];
            int left = 0, right = piles;
            // 二分查找插入位置
            while (left < right) {
                int mid = (left + right) / 2;
                if (top[mid] == poker){
                    left = mid;
                    break;
                }
                if (top[mid] >= poker)
                    right = mid;
                else
                    left = mid + 1;
            }
            if (left == piles) piles++;
            // 把這張牌放到牌堆頂
            top[left] = poker;
        }
        // 牌堆數就是 LIS 長度
        return piles;
    }
方法三:
    public int longestIncreceSubsquence(int[] arr){
        int temp[] = new int[arr.length];
        int size = 0,left =0,mid,right;
        for (int i : arr) {
            //對於每一個數字 查找插入位置
            left = 0;
            right = size;
            while (left < right){
                //查找位置
                mid = (left + right) / 2;
                //如果找到了 沒有什麼問題
                //如果沒有找到 那麼對於左右兩邊的兩個數來說
                //left + right /2 結果一定等於left 的值
                if (temp[mid] == i){
                    left = mid;
                    break;
                }else if (temp[mid] > i) {
                    //我們找的就是第一個比自己大的值  所有右邊要包含當前值
                    right = mid;
                }else {
                    left = mid + 1;
                }
            }
            if (left > size) {
                size ++;
            }
            if (left == size) {
                if (i > temp[left]) {
                    size++;
                    if (left + 1 < temp.length) {
                        left ++;
                    }
                }
            }
            //如果比所有的數都大
            temp[left] = i;
        }
        return size;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章