给出一个整数序列:
a[0], a[1], a[2], ..., a[n]
如果满足以下条件,则子序列a[i]...a[j]
是唯一的:
for each x, y between i and j and x != y:
a[x] != a[y]
我需要找到最大唯一个连续子序列的长度
我的方法:
我尝试了许多启发式方法,但是没有用。
然后我写了bruteforce,它给O(n^3)
带来了复杂性,如果n = 10^6
则无法计算
ans = 1
for i in [0, n]
for j in [i, n]
if unique a[i]...a[j]
ans = max(ans, j-i+1)
我认为这是典型的dp
问题,但不知道如何处理
答案 0 :(得分:1)
创建哈希图(如果值的范围很短,则使用布尔数组)。
制作两个索引-left
和right
,并在开头设置它们。
移动right
索引。在每一步中,检查t = A[right]
是否已在地图中。设为true时停止。
移动left
索引,从映射中删除A[left]
,直到满足等于t
的值为止。
重复移动步骤直到序列结束
right
和left
之间的最大差异是最大长度
答案 1 :(得分:0)
首先,我们可以通过以下观察来对操作进行某种程度的限制:如果我们发现了一些唯一的序列,那么我们就不必检查任何较短的序列。因此,我们迭代j in [i+ans, n]
。
接下来,如果我们知道序列从i
到j
的唯一性中断,则无需进一步扩展-我们知道不再使用i
作为序列开始将是独特的。因此,在您的支票else
语句中,我们只是打破了内部循环。
通过这种方式,迭代次数似乎类似于O(n)
,因为j
索引永远不会返回。
upd:关于 Ishpreet 的答案(由于我无法发表评论,因此将其张贴在此处)。
此代码不适用于最长子序列不是第一个子序列的序列。例如,考虑以下数组:[2,3,4,3,1,5,2]
。正确答案应为5
-4,3,1,5,2
的长度;但是上面的代码给出的答案将是3
。原因是这段代码实际上删除了第一个重复出现之前收集的所有序列,这不是我们所需要的,因为我们可以在第一个重复数字之后(包括第二个 (现在不重复)-如本例所示。
此外,这种方法存在一个基本问题。如果我们不存储(或以其他方式检查)重复位置,我们将不知道它是否会干扰当前找到的子序列,因此我们也不知道我们必须丢弃多少精确度(我们是否完全需要) 。可能是在当前子序列开始之前,又被另一个副本遮盖了;或者可能只是在前一个数字中,这迫使我们从头开始。
这里有一段代码试图涵盖这些情况(但尚未检查其全部正确性):
var map = {}
var arr = [2,3,4,4,5,1,6,2,8,5,9,3];
var ans = 1, currentSeqLength = 0;
for(var i=0; i<arr.length; i++){
if(arr[i] in map && map[arr[i]] >= i - currentSeqLength) {
currentSeqLength -= map[arr[i]];
} else {
currentSeqLength++;
}
map[arr[i]] = i;
ans = Math.max(ans, currentSeqLength);
}
console.log(ans); // 6 i.e. Length of 4,5,1,6,2,8
答案 2 :(得分:0)
这可以在 O(n)中完成。
如果使用Javascript,则可以使用哈希图或对象。然后,保留一个变量以跟踪到目前为止子序列的最大长度。
在每次迭代中,只需检查该值是否存在于哈希映射中即可。
var map = {}
var arr = [2,3,4,5,1,3,2];
var ans = 1, currentSeqLength = 0;
for(var i=0; i<arr.length; i++){
if(arr[i] in map) currentSeqLength = 0;
else map[arr[i]] = true;
currentSeqLength++;
ans = Math.max(ans, currentSeqLength);
}
console.log(ans); // 5 i.e. Length of 2,3,4,5,1