【问题标题】:How to find the longest increasing subsequence?如何找到最长的递增子序列?
【发布时间】:2016-10-11 12:39:38
【问题描述】:

我正在尝试使用代码打印最长递增子序列,该代码有效,但它不打印正确的最长递增子序列。


例如,如果输入是:3,5,11,8,4,7,1,2,10,12,9,6

输出为:[1, 2, 6, 9, 12]

我想要的输出是:3,4,7,10,12

我已经调试了插入和打印arraylist的方式和它的正确性,我认为这里有问题,为什么是错误的?为什么它改变了数字的顺序!?

public static ArrayList<Integer> lengthOfsequance(ArrayList<Integer> nums) {

    if (nums == null || nums.size() == 0)
        return null;
    ArrayList<Integer> list = new ArrayList<Integer>();
    for (int num : nums) 
    {
        if (list.size() == 0 || num > list.get(list.size() - 1)) 
            list.add(num);
        else
        {
            int i = 0;
            int j = list.size() - 1;
            while (i < j) 
            {
                int mid = (i + j) / 2;
                if (list.get(mid) < num) 
                    i = mid + 1;
                else
                    j = mid;
            }
           list.set(j, num);
        }
    }
    return list;
}

【问题讨论】:

  • 您的示例中想要的输出是什么?
  • 1,2,6,9,12 不是您声明的输入 3,5,11,8,4,7,1,2,10,12,9,6 的子序列.
  • 我认为那是他的程序输出,不是他想要的
  • 我想要的是 3,4,7,10,12 而不是 1,2,6,9,12 我也不应该改变数字的顺序
  • 我很感激这个惊喜接受:-)

标签: java arraylist


【解决方案1】:

您的方法行不通。您正在使用 one 列表来收集最长的序列。但是您的输入序列可以有多个递增序列。也许是从索引 0 到 5;另一个从索引 10 到 20。

换句话说;您需要不同的策略;而“直截了当”的方法类似于:

  1. 迭代输入列表,以“收集”所有递增序列(换句话说:这将是一个列表列表)。
  2. 然后,您查看列表列表以找到最大长度的列表

当然,这可以进一步优化 - 你不需要记住所有递增序列,你只需要记住你之前看到的“最长完成”序列。

但如前所述:第一个简单的实现是简单地识别输入列表中的所有“递增 + 完整”序列。然后你从那里开始工作。

(因为我假设这是某种家庭作业项目,我只提供指导思想,而不是源代码。实现留给读者作为练习)

编辑:解决评论“如何避免记住'相等'序列”。

假设您的输入是这个序列:1,2,3,0,1,2,3,4,1,2,3 当你在那里寻找增加的序列时,你应该发现:

(1, 2, 3) 和 (0, 1, 2, 3, 4), 和 (1, 2, 3)

你是对的:如果你把上面的元组表示为List&lt;Integer&gt;;那么“正确”的代码将收集 三个 列表;其中第一个和第三个将相等(因为它们包含完全相同的数字)。

当您将这些列表存储在 List&lt;List&lt;Integer&gt;&gt; 中时,是的,您的代码必须考虑重复项。 一种避免这种情况的方法可能是改用Set&lt;List&lt;Integer&gt;&gt; - 因为 Set 本质上确保存储在该集合中的所有条目都不相等。换句话说:当您将两个具有相同内容的列表添加到 Set 对象时,最终,Set 将只包含这两个列表中的 一个。 (需要注意的一件事 - 当您在此处使用 HashSet 时,add 操作的顺序会丢失)。

最后:除了使用Set&lt;List&lt;Integer&gt;&gt;,您还可以使用Map&lt;Integer, Integer&gt;,其中“key”是序列的长度;而“value”是输入列表中的第一个索引

换句话说:除了记住整个序列之外,您还可以只记住序列从哪个位置开始,以及该序列有多少元素。

长话短说:有很多不同的方法可以解决这个难题,使用各种数据结构和循环/计数机制。所以,不要停止使用第一个工作版本,而是继续玩。

【讨论】:

  • 谢谢!我想到了你所说的,我唯一的问题是当我想记住所有增加的序列时我怎么知道我之前还没有准备好记住这个子序列?
  • 更新了我的答案以解决该部分......再次。
  • 那么,复杂度不是 o(2^n) 吗?
  • 当然。这就是我说的原因:您可能希望从创建和测试简单的实现开始。然后你继续改进你的解决方案。你肯定可以在 O(n) 中解决这个问题——这意味着你只需要遍历输入数组就可以找到其中最大的递增序列。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-23
  • 1970-01-01
  • 2013-07-03
相关资源
最近更新 更多