【问题标题】:Best way to find longest common suffix of two arrays找到两个数组的最长公共后缀的最佳方法
【发布时间】:2017-11-21 10:31:10
【问题描述】:

给定两个数组,我需要找到最长的公共后缀。

更准确地说,我需要在每个数组中找到索引,然后出现该后缀。

例如:

// Input
arr1 = [1,2,3,4,5,6];
arr2 = [11,12,13,5,6];

// Output
ind1 = 4;
ind2 = 3;

这是我的代码:

let ind1 = arr1.length - 1;
let ind2 = arr2.length - 1;
while (ind1 >= 0 && ind2 >= 0 && arr1[ind1] == arr2[ind2]) {
    ind1--;
    ind2--;
}
ind1++;
ind2++;

我可以在这里应用一个单语句技巧(或一般的“更清洁”方式)吗?

【问题讨论】:

  • 请添加数组和想要的结果。
  • 几天前我读过一个类似的问题。如果我能找到链接,我会尝试。
  • @NinaScholz:完成,谢谢。
  • 两个数组的长度总是相等的?
  • @goodvibration 我需要找到最长的公共后缀,所以最长的后缀是7,8,9而不是1,2

标签: javascript arrays


【解决方案1】:

这绝对不是单语句技巧更简洁的方法,但它本质上比你现有的代码做得更多。

根据讨论:

如果数组是这样的:[1,2,3,4,5,6,7,8,9],[1,2,6,5,4,7,8,9]? – 拉杰什

@Rajesh:试试代码。它应该给你 ind1 = 0 和 ind2 = 0。- goodvibration

@goodvibration 我需要找到最长的公共后缀,所以最长的后缀是 7,8,9 而不是 1,2 - Rajesh

哦,对不起,我认为它们在您的示例中是相同的。是的,这里的后缀是7,8,9,所以输出应该是ind1 = 6 and ind2 = 5。 --goodvibration

您正在寻找一个返回最大序列起始索引的逻辑。为此,您必须在返回索引之前捕获所有序列并检查它们的长度。

你可以试试下面的逻辑:

  • 创建一个临时对象来保持位置。
  • 现在循环数组。
    • 如果 Array1 的起始位置未定义,则查找匹配元素的索引。
    • 将此索引保存在临时对象中并继续。
    • 如果定义了 startPosition,则查找两个数组中的下一个值是否相等。
    • 如果相等,继续。
    • 如果没有,请创建一个组并从此索引重新开始该过程。

function getLongestSuffixIndex(a1, a2) {
  var temp = {}
  var groups = [];
  var lastA2Index = 0;
  var a2Index = -1;
  var part;

  function addGroup() {
    if (temp.startA1Index !== undefined) {
      groups.push({
        a1Index: temp.startA1Index,
        a2Index: temp.startA2Index,
        count: temp.endA1Index - temp.startA1Index + 1
      });
      temp = {};
    }
  }

  function checkForIndex(i) {
    a2Index = part.indexOf(a1[i]);
    if (a2Index >= 0) {
      temp.startA1Index = i;
      temp.startA2Index = a2Index + lastA2Index;
      lastA2Index += a2Index;
    }
  }

  for (var i = 0, len = a1.length; i < len; i++) {
    part = a2.slice(lastA2Index);
    if (temp.startA1Index === undefined) {
      checkForIndex(i);
    } else {
      var index = (temp.startA2Index || 0) + (temp.count|| 0) + 1
      if (a1[i] === a2[index]) {
        temp.endA1Index = i;
        temp.count = i - temp.startA1Index;
      } else {
        addGroup();
        checkForIndex(i);
      }
    }
  }
  addGroup();

  return groups.length ? groups.reduce(function(p, c) {
    return ((p.count || 0) > (c.count || 0)) ? p : c
  }) : undefined;
}

var arr1 = [1, 2, 3, 4, 5, 6];
var arr2 = [11, 12, 13, 5, 6];

console.log(getLongestSuffixIndex(arr1, arr2))
console.log(getLongestSuffixIndex([1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 6, 5, 4, 7, 8, 9]))

【讨论】:

  • “您正在寻找一个返回最大序列起始索引的逻辑”-“最大序列”到底是什么意思?听起来不太像我要找的东西。
  • 表示最长公共后缀
【解决方案2】:

您可以使用单个变量从数组末尾向上计数。

var array1 = [1, 2, 3, 4, 5, 6],
    array2 = [11, 12, 13, 5, 6],
    l1 = array1.length - 1,
    l2 = array2.length - 1,
    i = 0;
    
while (i <= l1 && i <= l2 && array1[l1 - i] === array2[l2 - i]) {
    i++;
}

console.log('index array1', l1 - i + 1);
console.log('index array2', l2 - i + 1);

【讨论】:

  • 我不认为 OP 想要这个输出,但是我什至不明白真正的问题。
  • 与我已有的代码相比,这段代码在任何方面都不是“更干净”,此外,也不安全(空数组例外)
  • 它从两个数组的末尾返回公共元素(正如我所理解的问题......)。
  • 谁在说深度比较?
  • @NinaScholz:没问题。该代码可以正常工作,与我已经拥有的代码相比,它在任何方面都没有更清洁或更简单(至少据我所知)。所以它并没有真正满足我的要求。不过还是谢谢你。
【解决方案3】:

~ind1可以代替ind1 &gt;= 0作为ind1 != -1的缩写:

while (~ind1 && ~ind2 && arr1[ind1] == arr2[ind2]) { ind1--; ind2--; }

可以移动减量以避免.length - 1(两个减量都需要&amp;):

var i = arr1.length, j = arr2.length; while (~--i & ~--j && arr1[i] == arr2[j]) { }

对于数值,条件可以更短,因为undefined - undefinedNaN

while (arr1[--i] - arr2[--j] == 0) { } 

我把每一个都放在一行与原来的比较,很抱歉混乱..

for ([a, b] of [ [[1,2,3,4], [1,'3',4]], [[1], [0,1]], [[], []], [[,], [0]] ]) 
{
  var i = a.length - 1; var j = b.length - 1; while (i >= 0 && j >= 0 && a[i] == b[j]) { i--; j--; } i++; j++; console.log(i, j, a.length - i)   /* original version */

  var i = a.length, j = b.length; while (~--i & ~--j && a[i] == b[j]) { } i++; j++; console.log(i, j, a.length - i)   /* ~--i is short for (i = i - 1) != -1 */

  var i = a.length, j = b.length; while (a[--i] - b[--j] == 0) { } i++; j++; console.log(i, j, a.length - i)   /* a bit shorter, but minus works only with values convertible to Number */
}

作为旁注,我希望一个通用的后缀函数返回一个字符串或字符数。

【讨论】:

    猜你喜欢
    • 2014-10-13
    • 2011-12-23
    • 1970-01-01
    • 1970-01-01
    • 2012-02-01
    • 1970-01-01
    • 2021-09-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多