【问题标题】:Longest Increasing Subsequence, Dynamic Programing最长递增子序列,动态规划
【发布时间】:2017-04-26 17:31:10
【问题描述】:

我有以下问题:

找到给定序列/数组的最长递增子序列。

换句话说,找到数组的一个子序列,其中子序列的 元素严格按递增顺序排列,其中 子序列尽可能长。这个子序列不是 必然是连续的,或唯一的。在这种情况下,我们只关心 最长递增子序列的长度。

例子:

输入:[0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15] 输出 : 6 序列:[0, 2, 6, 9, 13, 15] 或 [0, 4, 6, 9, 11, 15] 或 [0, 4、6、9、13、15]

这是一个 DP 问题,我在记忆步骤中确实有一些问题。 这是我的代码:

public int lis(final List<Integer> a) {
    return maxIncreasing(0, Integer.MIN_VALUE, a);
}
HashMap<Integer, Integer> memo = new HashMap<>();
private int maxIncreasing(int index, int lastElt, final List<Integer> a) {
    if(memo.containsKey(index)) return memo.get(index);
    // end?
    if(index >= a.size()) return 0;
    int weTake = Integer.MIN_VALUE;
    // can we take it?
    if(a.get(index) > lastElt) {
        // take it or don't
        weTake = maxIncreasing(index + 1, a.get(index), a) + 1;
    }
    int weDoNot = maxIncreasing(index + 1, lastElt, a);
    int max = Math.max(weTake, weDoNot);
    memo.put(index, max);
    return max;
}

如果没有备忘录 HashMap,我得到了正确的结果,我不知道为什么一旦到位就会给我错误的结果。

谢谢。

【问题讨论】:

    标签: java algorithm dynamic-programming


    【解决方案1】:

    那是因为你没有照顾lastElt。基本上,对于给定的index,您可以有多个解决方案,具体取决于lastElt 的值。因此,您的memo 必须有一个Key,其中包含index 和lastElt。

    你可以这样做:

        class Key {
            final int index;
            final int lastEl;
    
            Key(int index, int lastEl) {
                this.index = index;
                this.lastEl = lastEl;
            }
    
            @Override
            public boolean equals(Object o) {
                if (this == o) return true;
                if (o == null || getClass() != o.getClass()) return false;
    
                Key key = (Key) o;
    
                if (index != key.index) return false;
                return lastEl == key.lastEl;
    
            }
    
            @Override
            public int hashCode() {
                int result = index;
                result = 31 * result + lastEl;
                return result;
            }
        }
    
        public int lis(final List<Integer> a) {
            return maxIncreasing(0, Integer.MIN_VALUE, a);
        }
        HashMap<Key, Integer> memo = new HashMap<>();
        private int maxIncreasing(int index, int lastElt, final List<Integer> a) {
            Key key = new Key(index ,lastElt);
            if(memo.containsKey(key)) return memo.get(key);
            // end?
            if(index >= a.size()) return 0;
            int weTake = Integer.MIN_VALUE;
            // can we take it?
            if(a.get(index) > lastElt) {
                // take it or don't
                weTake = maxIncreasing(index + 1, a.get(index), a) + 1;
            }
            int weDoNot = maxIncreasing(index + 1, lastElt, a);
            int max = Math.max(weTake, weDoNot);
            memo.put(key, max);
            return max;
        }
    

    【讨论】:

    • 感谢这个解决方案是有效的,但是仍然给我一些性能方面的问题,可能是递归导致内存开销。
    • 您应该尝试使用动态编程来实现它。您应该使用数组来计算所有结果,而不是使用递归和记忆,如下所示:geeksforgeeks.org/…
    猜你喜欢
    • 2016-05-02
    • 1970-01-01
    • 2011-02-07
    • 2012-10-25
    • 2019-05-28
    • 2016-09-30
    • 1970-01-01
    • 2013-07-03
    相关资源
    最近更新 更多