使用布尔数组在O(n)中查找字符串的第一个非重复字符?

时间:2012-01-19 21:43:47

标签: arrays string algorithm

我的问题与之前的问题有关

  

Find the first un-repeated character in a string

在我的一次采访中,我被要求编写一个函数来确定时间O(n)中字符串中的第一个唯一字符,使用长度为n的布尔数组作为额外空间。也就是说,仅使用O(n)复杂度和长度为n的bool数组找到字符串中的第一个非重复字母。有人可以建议如何使用bool数组解决它吗?

6 个答案:

答案 0 :(得分:10)

好吧,如果字符集的大小是不变的......例如,比如0-255 ...

扫描字符串,查找字符0。

然后扫描字符串,寻找字符1。

然后扫描字符串,寻找字符2.

...

最后,扫描字符串,查找字符255。

这需要256 * n次操作,即O(n)。

在每次扫描期间,如果字符是唯一的,请在位图中标记其位置。最后在第一个标记位置返回字符。 (或者只使用k + log(n)位记录第一个唯一字符及其位置。使用硬编码查找表或任何非常小的n;否则,n位是慷慨的。)

虽然不知怎的,我怀疑这不是面试官的想法。

答案 1 :(得分:0)

    private static void FirstNonRepeatingCharacters()
    {
        string s = "abbazccdde";
        var result = from item in s
                     group item by item into groupedItems
                     where groupedItems.Count() == 1
                     select groupedItems.Key;
        Console.WriteLine(result.First());                    
    }

C#实施

答案 2 :(得分:0)

单通道解决方案

维护2个数据结构:

  1. 用于跟踪每个字符数的数组/位图/哈希表
  2. LinkedHashMap用于跟踪到目前为止仅发生过一次的字符。
  3. LinkedHashMap有

    • O(1)插入
    • O(1)删除
    • O(1)搜索

      class Node
      {
        char data;
        Node next;
        Node prev;
      };
      
      class LinkedHashMap
      {
              // This will keep the insertion order intact
              Node listHead;
              Node currentTail = listHead;
              HashTable<char, Node> charExistsMap;
      
          void Add(char ch) 
          {
              if(!charExistsMap.ContainsKey(ch)) 
              {
                  // Add to both hashtable and linkedlist
                  Node n = new Node(ch);
                  n->next = null;
                  n->prev = curentTail; // Added To List
                  currentTail = n;
                  charExistMap.Add(ch, n);
              }
              else 
              {
                  // Remove from both hashtable and linkedlist
                  Node n = charExistMap.Remove(ch);
                  if(n->prev != null) 
                  {
                      n->prev->next = n->next
                      listHead = n->next; // update head
                  }
                  if(n->next != null)
                      n->next->prev = n->prev;
               }
          }
      
          char GetFirstNonRepeatingChar()
          {
              return listHead->data;
          }
      

      }

    遍历原始字符串后,LinkedHashMap的头部将包含不重复的第一个字符。

答案 3 :(得分:0)

public class FirstUniqueChar {

  public static void main(String[] args) {

    String test = "ABxacd";

    test = test.toUpperCase();
    for (int i = 0; i < test.length(); i++) {
        int firstIndex = test.indexOf(test.charAt(i));
        int lastIndex = test.lastIndexOf(test.charAt(i));
        if (firstIndex == lastIndex) {
            System.out.println("First unique char of String " + test.charAt(i));
            break;
        }

    }

  }
}

答案 4 :(得分:0)

两次通过:

第一遍:创建大小为256的bool数组,并为文本中的每个字符标记索引的元素int(即char)。这需要O(n)。

第二遍:对于文本中的每个字符,检查是否标记了相应的数组元素。如果没有,那么你找到了答案。这也需要O(n)。

答案 5 :(得分:-2)

有两个布尔数组,seenOnce和seenMany。 循环遍历字符串填充数组。 再次循环遍历字符串,检查字符是否在seeFirst中,但不在seeMany中。如果这是你的第一个非重复的角色。

这是python中的一些示例代码。

subject = "ttojxxlma"

seenOnce = [False for i in range(256)]
seenMany = [False for i in range(256)]

for c in subject:
    index = ord(c)
    if seenOnce[index] == False:
        seenOnce[index] = True
    else:
        seenMany[index] = True

for c in subject:
    index = ord(c)
    if seenOnce[index]==True and seenMany[index] != True:
        print(c)
        break

好吧仍然使用太布尔数组(或python lists = P)。要只使用一个数组,您可以拥有一个数字加倍的数组。而不是访问第二个数组加倍索引并访问大索引。但那简直太乱了。

不确定是否可以用更少的空间来完成。