【问题标题】:DSA question: remove duplicates from array of array containing same associative valuesDSA 问题:从包含相同关联值的数组中删除重复项
【发布时间】:2021-04-08 06:21:27
【问题描述】:

假设我们有一个数组数组,其中包含一些数字:

let arr = [ [1,2,3] ,[5,6,9] ,[2,1,3],[3,2,4],[4,3,5], [6,9,5] ]

这里 arr[0]arr[2] 具有 相同的关联值 (1,2,3),尽管位置是不一样。

相同的 arr[1]arr[5] 具有 相同的关联值 (5,6,9),尽管位置是不一样

我想删除重复项,并希望得到结果:

final= [ [1,2,3] ,[5,6,9] ,[3,2,4],[4,3,5] ]

javascript 或 python 中的任何解决方案都会很棒,也欢迎其他语言,如 c++(我对此知之甚少),伪代码也很有帮助。

我想知道什么是最好的 BIG-O 算法。

【问题讨论】:

  • 你试过什么?它的大 O 复杂度是多少?
  • 这个问题仅限于二维(a,b,c) -> (b-a,c-a)?
  • 你可以为这个问题添加一些约束吗?我可以将它视为 n x m 即 n 个单个数组,并且每个 n 个数组包含最多 m 个元素。如果 n, m
  • Ieequals 定义为return (x_b-x_a == y_b-y_a) && (x_c-x_a == y_c-y_a) 的哈希集可能会做得很好,具体取决于您想要的保证程度。

标签: arrays algorithm


【解决方案1】:

给定一个长度为 N * M 的 2 级数组(N 元素,每个元素都是带有 M 数字的子数组),您必须至少查看一次 N * M 数字以检测重复。因此,硬性下限是O(N*M)。一个非常简单的方法是将每个子数组与所有其他子数组进行比较 - 成本为O(N * (N-1) * M * M),具有 4 个嵌套循环。这当然可以改进。

一种可能性是对数组及其子数组进行排序(例如,使用子数组编号的字典顺序)。这将需要O((N log N) * (M log M)) 时间,但允许在 O(M) 中查找子数组是否与另一个子数组相同 - 因为对于每个数字,您只需要检查相应的数字是否相等。因此,对于这种方法,您将获得 O((N log N) * (M log M)) 的成本(这比在所有内容都排序后实际清除重复项所需的 O(N * M) 更大,因此在成本方面占主导地位)。这也非常接近最优。

let arr = [ [1,2,3] ,[5,6,9] ,[2,1,3],[3,2,4],[4,3,5], [6,9,5] ]

function dedupBySorting(a) {
   // sort sub-arrays
   a = a.map(a => a.sort())
   // sort main array
   a = a.sort();
   // define equality of two sub-arrays
   const same = (x, y) => {
       if (x.length != y.length) return false;
       for (let i=0; i<x.length; i++) {
           if (x[i] != y[i]) return false;
       }
       return true;
   }
   // take the 1st of each run 
   return a.filter((item, index) => {
     return index==0 || !same(item, a[index-1]);
   });
}

console.log(dedupBySorting(arr));

另一种可能性是使用散列:将所有内容放入一个散列集(不接受重复项),并输出剩余的子数组。您的散列函数必须至少为O(M)(否则它不会很好),并且无论子数组中数字的顺序如何,它都必须产生相同的散列。假设很少有冲突,您将能够在O(N * M) 中构建哈希集,这将是最佳的。在我的例子中,我已经对子数组进行了排序,在 O(N * M * log M) 中发生 - 其他选项可能更快,但会产生更多冲突。

let arr = [ [1,2,3] ,[5,6,9] ,[2,1,3],[3,2,4],[4,3,5], [6,9,5] ]

function dedupByHashing(a) {
    // build a hashable key such that k([1,2,3]) == k([2,1,3]); that is, it ignores order
    const key = (v) => JSON.stringify(v.sort());
    // build the set, and use it to filter out duplicates
    let seen = new Set();
    return a.filter(item => {
        let k = key(item);
        return seen.has(k) ? false : seen.add(k);
    });
}

console.log(dedupByHashing(arr));

请注意,此代码不会产生您的确切输出,因为在您的输出中,您似乎以与在输入中找到它们的顺序完全相同的顺序包含非重复输入,并且您仅输出每次运行的第一个,使用元素也按输入顺序排列。但是这两个答案都可以修改为只输出稍作改动的结果,这不会影响它们的复杂性。

注意:您可能也有兴趣在 this excellent writeup 中查找有关 javascript 中的重复数据删除的信息。它帮助我为这两个答案编写了更简洁的实现。

【讨论】:

  • 非常喜欢这个答案。非常感谢
猜你喜欢
  • 1970-01-01
  • 2018-07-01
  • 1970-01-01
  • 2013-01-11
  • 1970-01-01
  • 2020-01-16
  • 2021-05-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多