从字符串中删除重复项,不使用HASHMAP和O(n)时间复杂度

时间:2013-06-18 19:13:21

标签: string performance algorithm

Microsoft面试问题

  

从字符串中删除重复项,不使用HASHMAP和O(n)时间复杂度

O(n 2 )时间复杂度有一个解决方案,但面试问题特别提到没有HASHMAP和O(n)时间。

任何指针都很受欢迎,因为我不能想到任何低于O(n log n)时间的东西,它采用排序并使用O(n)空间。

3 个答案:

答案 0 :(得分:11)

你做了一种斗式排序。

  • 制作一个包含每个字符的数组
  • 创建一个包含其对应char的计数的数组

我们使用这样的2个数组的唯一原因是因为你明确禁止哈希映射。您可以随意代表这种结构。如果允许将字符转换为int s,则只需使用1个数组。

由于我们假设可能的字符数量有限,因此每个数组的大小都是常数,或 O(1)

  • 对您的字符串进行迭代,并为您找到的每个count增加char。如果count已经大于0,那么您发现了重复。

在char数组中搜索特定字符需要 O(1)时间,因为字符数量有限。

你将进行n次搜索,净运行时间为 O(n)


如果数组不好,那么您可以使链接列表仅保留您找到的值。它仍然是常量,因为链表的大小仍然受可能字符数的限制。

如果你这样做,你或多或少会做同样的事情,除了它在外观上看起来不像桶式排序策略。

答案 1 :(得分:3)

我可能有另一个解决方案,我认为它更糟糕,但它适用于小字符数组。算法如下:

  
      
  1. 我们将每个字母分配给从2开始的素数。 - 这将是我们的查找表。
  2.   
  3. 我们找到了所有数字的乘积。 - >为O(n)
  4.   
  5. 在循环中 - > O(n)我们检查产品%k * k == 0如果是,我们发现了重复的k。
  6.   

此解决方案仅存储1个数字,但很容易溢出。主表将占用很多空间。

编辑: 如果我们添加一个只有40个唯一字符可用的约束,我们可以使用Euler的二次多项式来找到素数。

  

P(n)= n * n - n + 41

除了产品之外,这不需要任何额外的空间。

答案 2 :(得分:0)

traverse the list for i= 0 to n-1 elements
{
  check for sign of A[abs(A[i])] ;
  if positive then
     make it negative by   A[abs(A[i])]=-A[abs(A[i])];
  else  // i.e., A[abs(A[i])] is negative
     this   element (ith element of list) is a repetition
}

您可以在阵列中轻松将其修改为0。如果是字符,您可以使用其整数代码。