我正在尝试使用代码来打印增长最长的子序列,代码可以工作,但它不会打印正确的最长增长子序列。
例如,如果输入为:3,5,11,8,4,7,1,2,10,12,9,6
我正在调试插入和打印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 :(得分:2)
您的方法不能有效。您正在使用一个列表来收集最长的序列。但是您的输入序列可以具有多个递增序列。也许从索引0到5;另一个从索引10到20。
换句话说;你需要一个不同的策略;而“直截了当”的方法就是:
当然,这可以进一步优化 - 您不需要记住所有增加的序列,您只需记住您之前看到的“最长完成”序列。
但正如所说:第一个,天真的实现是简单地识别输入列表中的所有“增加+完成”序列。然后你从那里开始工作。
(因为我认为这是某种家庭作业项目,我只提供指导性的想法,而不是源代码。实施留给读者练习)
编辑:解决评论“如何避免记住'相等'序列”。
假设您的输入是这个序列: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本质上确保存储在该集合中的所有条目都不相等。换句话说:当您向Set对象添加两个具有相同内容的列表时,最后,Set将仅包含这两个列表中的一个。 (有一点需要注意 - 当你在这里使用HashSet时,添加操作的顺序就会丢失。)
最后:您也可以使用Set<List<Integer>>
而不是使用Map<Integer, Integer>
,而“key”是序列的长度;和“value”是输入列表中的第一个索引。
换句话说:除了记住整个序列,您还可以记住序列在哪个位置开始,以及序列有多少个元素。
长话短说:使用各种数据结构和循环/计数机制,有许多不同的方法来解决这个难题。所以,不要停留在第一个工作版本,但继续玩。