Niuke.com、最長増加部分列(特定のシーケンスを出力するため)

タイトル説明

ここに画像の説明を挿入

解決

重要:終了配列と添え字の意味を理解してください。

長さi + 1の各サブシーケンスの最後の要素の最小値をインデックスiで記録します。これにより、サブシーケンスを可能な限り拡張できます。つまり、end [i]は長さi +の増加するすべてのサブシーケンスの末尾を表します。 1最小要素を持つシーケンス
int [] end = new int [arr.length];
int len = 0; // end array end [len]は、実際の長さがlen + 1
int [である文字列の最小終了要素を記録します。] dp = new int [arr.length]; // iで終わるサブシーケンスの最大長を記録します

import java.util.*;
public class Solution {
    
    
    /**
     * retrun the longest increasing subsequence
     * @param arr int整型一维数组 the array
     * @return int整型一维数组
     */
    public int[] LIS (int[] arr) {
    
    
        if(arr==null || arr.length<1) return arr;
    // write code here
        //记录索引为i的长度为i+1的每个子序列最后一个元素的最小值,尽可能地使得子序列可以扩展,即end[i]表示的是所有长度为i+1的递增子序列中尾部元素最小的那个序列
        int[] end = new int[arr.length];
        //最后我们可以得知该序列是严格递增的,所以方便之后的二分
       int[] dp = new int[arr.length];//记录以i为结尾的子序列的最大长度
        end[0] = Integer.MAX_VALUE;
       int len=0;//end数组end[len]记录实际长度为len+1的字串的最小结尾元素
        for(int i=0;i<arr.length;i++){
    
    
            if(arr[i]>end[len]){
    
    //当前的字串长度是否可以扩展,大于则可以扩展,且不需要调整end数组
                len++;
                end[len] = arr[i];
                //记录当前元素结尾的最长字串的长度
                dp[i] = len+1;//len+1映射实际的长度
            }else{
    
    //不能扩充end的长度,需要调整end数组,使得对应每个i+1长度的字序列最后一个元素尽量小
                
                  //调整
                int left = 0,right = len;//使用二叉查找找到第一个比arr[i]大的数,注意这里的end[len]里面已经存在数了,所以下面为left<=end
                //找到最后一个比arr[i]小的数,选择最大左边界和最小右边界
                while(left<=right){
    
    //[left,right)
                    int mid = (left+right)/2;
                    if(end[mid]>arr[i]){
    
    
                        right = mid-1;//这里注意,我们如果找到了第一个比他大的,则替换它
                    }else{
    
    
                        left = mid+1;
                    }
                }
                end[left] = arr[i];//填入一个,更新end数组
                dp[i] = left+1;//当前以arr[i]为结尾的最大字串长度更新
            }
        }
    //此时的end数组里面记录len则为最大长度的而且我们应该找字典序最小的
        int []result = new int[len+1];
        for(int i=arr.length-1;i>=0;i--){
    
    
            if(dp[i]==len+1){
    
    //dp[i]记录的是以i为结尾元素的最长递增字串长度
                result[len] = arr[i];
                len--;
            }
        }
        return result;
    }
}

おすすめ

転載: blog.csdn.net/qq_44861675/article/details/114989529