LeetCode 354. 俄罗斯套娃信封问题

Posted 数据结构和算法

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 354. 俄罗斯套娃信封问题相关的知识,希望对你有一定的参考价值。

截止到目前我已经写了 500多道算法题,其中部分已经整理成了pdf文档,目前总共有1000多页(并且还会不断的增加),大家可以免费下载
下载链接https://pan.baidu.com/s/1hjwK0ZeRxYGB8lIkbKuQgQ
提取码:6666

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

最长上升子序列的计算这里就不在赘述,具体可以看下《413,动态规划求最长上升子序列》,我们来看下这题的最终代码。

public int maxEnvelopes(int[][] envelopes) {
    //边界条件判断
    if (envelopes == null || envelopes.length == 0)
        return 0;
    //先对信封进行排序
    Arrays.sort(envelopes, (int[] arr1, int[] arr2) -> {
        if (arr1[0] == arr2[0])
            return arr2[1] - arr1[1];
        else
            return arr1[0] - arr2[0];
    });
    return lengthOfLIS(envelopes);
}

//求最长上升子序列
public int lengthOfLIS(int[][] nums) {
    int[] dp = new int[nums.length];
    //初始化数组dp的每个值为1
    Arrays.fill(dp, 1);
    int max = 1;
    for (int i = 1; i < nums.length; i++) {
        for (int j = 0; j < i; j++) {
            //如果当前值nums[i]大于nums[j],说明nums[i]可以和
            //nums[j]结尾的上升序列构成一个新的上升子序列
            if (nums[i][1] > nums[j][1]) {
                dp[i] = Math.max(dp[i], dp[j] + 1);
            }
        }
        //记录构成的最大值
        max = Math.max(max, dp[i]);
    }
    return max;
}

在这里插入图片描述

public int maxEnvelopes(int[][] envelopes) {
    //边界条件判断
    if (envelopes == null || envelopes.length == 0)
        return 0;
    //先对信封进行排序
    Arrays.sort(envelopes, (int[] arr1, int[] arr2) -> {
        if (arr1[0] == arr2[0])
            return arr2[1] - arr1[1];
        else
            return arr1[0] - arr2[0];
    });
    return lengthOfLIS(envelopes);
}

//最长上升子序列
public int lengthOfLIS(int[][] nums) {
    //list中保存的是构成的上升子序列
    ArrayList<Integer> list = new ArrayList<>(nums.length);
    for (int[] num : nums) {
        //如果list为空,我们直接把num加进去。如果list的最后一个元素小于num,
        //说明num加入到list的末尾可以构成一个更长的上升子序列,我们就把num
        //加入到list的末尾
        if (list.size() == 0 || list.get(list.size() - 1) < num[1])
            list.add(num[1]);
        else {
            //如果num不小于list的最后一个元素,我们就用num把list中第一
            //个大于他的值给替换掉,这样我们才能保证list中的元素在长度不变
            //的情况下,元素值尽可能的小
            int i = Collections.binarySearch(list, num[1]);
            //因为list是从小到大排序的,并且上面使用的是二分法查找。当i大
            //于0的时候,说明出现了重复的,我们直接把他替换即可,如果i小于
            //0,我们对i取反,他就是list中第一个大于num值的位置,我们把它
            //替换即可
            list.set((i < 0) ? -i - 1 : i, num[1]);
        }
    }
    return list.size();
}

对于二分法查找的代码可以看下《202,查找-二分法查找》,也可以看下官方提供的代码

/**
 * Searches the specified list for the specified object using the binary
 * search algorithm.  The list must be sorted into ascending order
 * according to the {@linkplain Comparable natural ordering} of its
 * elements (as by the {@link #sort(List)} method) prior to making this
 * call.  If it is not sorted, the results are undefined.  If the list
 * contains multiple elements equal to the specified object, there is no
 * guarantee which one will be found.
 *
 * <p>This method runs in log(n) time for a "random access" list (which
 * provides near-constant-time positional access).  If the specified list
 * does not implement the {@link RandomAccess} interface and is large,
 * this method will do an iterator-based binary search that performs
 * O(n) link traversals and O(log n) element comparisons.
 *
 * @param  <T> the class of the objects in the list
 * @param  list the list to be searched.
 * @param  key the key to be searched for.
 * @return the index of the search key, if it is contained in the list;
 *         otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>.  The
 *         <i>insertion point</i> is defined as the point at which the
 *         key would be inserted into the list: the index of the first
 *         element greater than the key, or <tt>list.size()</tt> if all
 *         elements in the list are less than the specified key.  Note
 *         that this guarantees that the return value will be &gt;= 0 if
 *         and only if the key is found.
 * @throws ClassCastException if the list contains elements that are not
 *         <i>mutually comparable</i> (for example, strings and
 *         integers), or the search key is not mutually comparable
 *         with the elements of the list.
 */
public static <T>
int binarySearch(List<? extends Comparable<? super T>> list, T key) {
    if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
        return Collections.indexedBinarySearch(list, key);
    else
        return Collections.iteratorBinarySearch(list, key);
}

private static <T>
int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key) {
    int low = 0;
    int high = list.size()-1;

    while (low <= high) {
        int mid = (low + high) >>> 1;
        Comparable<? super T> midVal = list.get(mid);
        int cmp = midVal.compareTo(key);

        if (cmp < 0)
            low = mid + 1;
        else if (cmp > 0)
            high = mid - 1;
        else
            return mid; // key found
    }
    return -(low + 1);  // key not found
}

以上是关于LeetCode 354. 俄罗斯套娃信封问题的主要内容,如果未能解决你的问题,请参考以下文章

力扣技巧之动态规划力扣354:俄罗斯套娃信封问题C++

LeetCode——俄罗斯套娃信封问题

Leetcode 动态规划刷题总结

leetcode刷题总结351-400

俄罗斯套娃信封问题

数据结构与算法之深入解析“俄罗斯套娃信封问题”的求解思路与算法示例