繁体   English   中英

如何找到增长最长的子序列?

[英]How to find the longest increasing subsequence?

我正在尝试使用代码来打印最长的增加子序列,代码可以工作,但它不会打印正确的最长增加子序列。


例如,如果输入是: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;
}

你的方法无法奏效。 您正在使用一个列表来收集最长的序列。 但是您的输入序列可以有多个递增序列。 也许从索引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<Integer> ; 然后“正确”代码将收集三个列表; 第一个和第三个相等 (因为它们包含相同的数字)。

当您将这些列表存储在List<List<Integer>> ,是的,您的代码必须考虑重复。 避免这种情况的一种方法可能是使用Set<List<Integer>> - 因为Set本质上确保存储在该集合中的所有条目都不相等。 换句话说:当你添加两个列表具有相同内容的集合对象,那么,到了最后,设置将只包含这两个列表之一 (有一点需要注意 - 当你在这里使用HashSet时, 添加操作的顺序就会丢失)。

最后:代替使用Set<List<Integer>>您还可以使用Map<Integer, Integer>其中“key”是序列的长度 ; 并且“value”是输入列表中的第一个索引

换句话说:您不仅要记住整个序列,还可以记住序列在哪个位置开始,以及序列有多少个元素。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM