【问题标题】:Count all lists of adjacent nodes stored in an array计算存储在数组中的所有相邻节点列表
【发布时间】:2010-04-01 13:06:50
【问题描述】:

有很多天真的方法可以解决这个问题,但我正在寻找一个好的解决方案。这是问题(将在Java中实现):

你有一个函数 foo(int a, int b) 如果“a”与“b”“相邻”则返回 true,如果“a”与“b”不相邻则返回 false。你有一个这样的数组[1,4,5,9,3,2,6,15,89,11,24],但实际上有一个很长的长度,比如120,并且会一遍又一遍地重复(它是一个遗传算法适应度函数)这就是为什么效率很重要。

我想要一个函数,它返回数组中每个可能的邻接“列表”的长度,但不包括只是较大列表子集的“列表”。

例如,如果 foo(1,4) -> true, foo(4,5) -> true, foo(5,9)-> false, foo(9,3) & foo(3,2) & foo(2,6), foo(6,15) -> true, 然后有'列表' (1,4,5) 和 (9,3,2,6),所以长度为 3 和 4。我不但不希望它返回 (3,2,6),因为这只是 9,3,2,6 的子集。

谢谢。

编辑

抱歉,我才意识到我没有解释整个问题,剩下的部分太难了。让我们重新开始。忘记第一个帖子。这会让我们感到困惑。

假设有一个函数 foo(int[] array) 如果数组是“好”数组则返回 true,如果数组是“坏”数组则返回 false。什么是好是坏在这里并不重要。

给定完整的数组 [1,6,8,9,5,11,45,16,9],假设子数组 [1,6,8] 是一个“好”数组,而 [9,5, 11,45] 是一个“好”的数组。此外 [5,11,45,16,9] 是一个“好”数组,也是最长的“好”子数组。请注意,虽然 [9,5,11,45] 是“好”数组,而 [5,11,45,16,9] 是“好”数组,但 [9,5,11,45,16,9 ] 是一个“坏”数组。

我们想要所有“好”数组的长度计数,而不是“好”数组的子数组。此外,如上所述,一个“好”数组可能从另一个“好”数组的中间开始,但两者的组合可能是一个“坏”数组。

【问题讨论】:

  • 定义naive approach。你想要比O(n^2)更好的东西吗?
  • 如果您一遍又一遍地执行此操作,并且速度比内存更重要,并且列表在运行之间会发生变化(略有变化),那么可能值得存储一个指向开头的指针每个链条。这样,当列表发生变化时,您就可以限制更新链列表所需的内容。

标签: java algorithm arrays function


【解决方案1】:

我认为这个O(n) 算法可以满足您的需求。我怀疑您是否可以更快地做到这一点,因为您必须分析每个元素。

count = 1;
for each index i from 1 to N
    if ( foo(array[i-1], array[i]) == true )
        ++count;
    else
        print count;
        count = 1;

这是有效的,因为如果某个数字破坏了邻接链,那么破坏该链的数字之前的任何数字都不能成为更长链的一部分,因此您不妨从那一点继续。

在你的例子上工作:

例如,如果 foo(1,4) -> true, foo(4,5) -> true, foo(5,9)-> false, foo(9,3) & foo(3,2) & foo(2,6), foo(6,15) -> true, 那么有'列表' (1,4,5) 和 (9,3,2,6),所以长度为 3 和 4。我不知道但不希望它返回 (3,2,6),因为这只是 9,3,2,6 的子集

foo(1, 4) -> true -> count = 2
foo(1, 5) -> true -> count = 3
foo(5, 9) -> false -> print 3, count = 1
foo(9, 3) -> true -> count = 2
foo(3, 2) -> true -> count = 3
foo(2, 6) -> true -> count = 4
foo(6, 15) -> true -> count = 5

数组结束,只打印计数,所以print 5。我猜你的例子是错误的,因为(9, 3, 2, 6)(9, 3, 2, 6, 15) 的子集...

【讨论】:

    【解决方案2】:

    我认为,这是最长子字符串类型的问题,只要你有属性,如果从 A 到 B 的子数组是“好”,那么任何较小的子数组也是好的。

    算法是这样的:

    • 从包含第一个元素(或对,或任何最短的单元)的子数组开始。
    • 向前推进子数组(即同时推进子数组的开始和结束),直到得到“好”的答案。
    • 推进子数组的末尾,直到得到“坏”的答案。在你得到“坏”之前的子数组是那个位置最长的好子数组——数一下(或者保存它,或者你想用它做什么)。
    • 现在将子数组的开头向前推进,直到得到“好”的答案;如果您赶上子数组的末尾,请向前滑动。然后重复上一步。
    • 当子数组的末尾到达整个数组的末尾时,您就完成了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多