最大唯一连续子序列

时间:2018-06-29 09:45:30

标签: algorithm math dynamic-programming

给出一个整数序列:

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问题,但不知道如何处理

3 个答案:

答案 0 :(得分:1)

创建哈希图(如果值的范围很短,则使用布尔数组)。

制作两个索引-leftright,并在开头设置它们。

移动right索引。在每一步中,检查t = A[right]是否已在地图中。设为true时停止。

移动left索引,从映射中删除A[left],直到满足等于t的值为止。

重复移动步骤直到序列结束

rightleft之间的最大差异是最大长度

答案 1 :(得分:0)

首先,我们可以通过以下观察来对操作进行某种程度的限制:如果我们发现了一些唯一的序列,那么我们就不必检查任何较短的序列。因此,我们迭代j in [i+ans, n]

接下来,如果我们知道序列从ij的唯一性中断,则无需进一步扩展-我们知道不再使用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