String 在O(n)时间内,使用恒定空间,即不使用额外的辅助数组,查找给定字符串中的非唯一字符

String 在O(n)时间内,使用恒定空间,即不使用额外的辅助数组,查找给定字符串中的非唯一字符,string,algorithm,String,Algorithm,给定仅包含小写字母a-z的字符串s,查找(即打印)重复的字符 对于ex,如果字符串s=aabcacdddec 输出:a c d 解决这一问题的方法有三种: [brute force]检查字符串的每个字符,即s[i]与其他每个字符,如果两者相同,则打印 时间复杂度:在^2上 空间复杂度:O1 [排序,然后比较相邻元素]在logn time上排序后,遍历字符串并检查s[i]和s[i+1]是否相等 时间复杂度:On logn+On=On logn 空间复杂度:O1 [将字符计数存储在数组中]创建一个大

给定仅包含小写字母a-z的字符串s,查找(即打印)重复的字符

对于ex,如果字符串s=aabcacdddec

输出:a c d

解决这一问题的方法有三种:

[brute force]检查字符串的每个字符,即s[i]与其他每个字符,如果两者相同,则打印 时间复杂度:在^2上 空间复杂度:O1

[排序,然后比较相邻元素]在logn time上排序后,遍历字符串并检查s[i]和s[i+1]是否相等 时间复杂度:On logn+On=On logn 空间复杂度:O1

[将字符计数存储在数组中]创建一个大小为26的数组,以跟踪a-z,并且对于数组中的每个s[i],增量值存储在索引=s[i]-26处。最后遍历数组并打印所有元素,即值大于1的“a”+i 时间复杂性:On 空间复杂度:O1,但我们有一个单独的数组来存储每个元素的频率

是否有不使用任何数组/哈希表/映射等的On方法

提示:使用位向量

这是最简单的,所以一般来说-没有额外的空间,没有办法在On中解决它

但是,如果您将字母表视为常量大小,则a-z字符是非常常量的,您可以在O1空间中创建这些字符的位集[它是常量!],或者检查On中的每个字符,如果它重复多次,则它将是O常量*n,它仍处于On状态

第一个解决方案的伪代码:

bit seen[] = new bit[SIZE_OF_ALPHABET] //contant!
bit printed[] =  new bit[SIZE_OF_ALPHABET] //so is this!
for each i in seen.length: //init:
    seen[i] = 0
    printed[i] = 0
for each character c in string: //traverse the string:
    i = intValue(c)
    //already seen it and didn't print it? print it now!
    if seen[i] == 1 and printed[i] == 0: 
        print c
        printed[i] = 1
    else:
        seen[i] = 1
for each character c from a-z: //constant number of repeats is O(1)
   count = 0
   for each character x in the string: //O(n)
        if x==c:
           count += 1
   if count > 1
        print count
第二种解决方案的伪代码:

bit seen[] = new bit[SIZE_OF_ALPHABET] //contant!
bit printed[] =  new bit[SIZE_OF_ALPHABET] //so is this!
for each i in seen.length: //init:
    seen[i] = 0
    printed[i] = 0
for each character c in string: //traverse the string:
    i = intValue(c)
    //already seen it and didn't print it? print it now!
    if seen[i] == 1 and printed[i] == 0: 
        print c
        printed[i] = 1
    else:
        seen[i] = 1
for each character c from a-z: //constant number of repeats is O(1)
   count = 0
   for each character x in the string: //O(n)
        if x==c:
           count += 1
   if count > 1
        print count

字符集的大小是一个常量,因此可以扫描输入26次。您只需要一个计数器来存储您看到与当前迭代对应的角色的次数。在每次迭代结束时,如果计数器大于1,则打印该字符

它在运行时打开,在辅助空间中打开O1。

在Java中实现

public static void findDuplicate(String str) {
        int checker = 0;
        char c = 'a';
        for (int i = 0; i < str.length(); ++i) {
            int val = str.charAt(i) - c;
            if ((checker & (1 << val)) > 0) {
                System.out.println((char)(c+val));
            }else{
                       checker |= (1 << val);                        
                    }

        }
    }
使用as int作为存储,并执行逐位运算符查找重复项

它在……上。。解释如下

输入为abddc

i==0

  STEP #1 : val = 98 - 98  (0)  str.charAt(0) is a and conversion char to int is 98 ( ascii of 'a')

  STEP #2 : 1 << val equal to ( 1 << 0 ) equal to 1  finally 1 & 0 is 0 
  STEP #3 :  checker = 0 | ( 1 << 0)  equal to 0 | 1 equal to 1 checker is 1
i==1

  STEP #1 : val = 99 - 98  (1)  str.charAt(1) is b and conversion char to int is 99 ( ascii of 'b')

  STEP #2 :  1 << val equal to ( 1 << 1 ) equal to 2  finally 1 & 2 is 0 
  STEP #3 :  checker = 2 | ( 1 << 1)  equal to 2 | 1 equal to 2 finally checker is 2
i==2

  STEP #1 : val = 101 - 98  (3)  str.charAt(2) is d and conversion char to int is 101 ( ascii of 'd')

  STEP #2 :  1 << val equal to ( 1 << 3 ) equal to 8  finally 2 & 8 is 0 
  STEP #3 :  checker = 2 | ( 1 << 3)  equal to 2 | 8 equal to 8 checker is 8
i==3

  STEP #1 : val = 101 - 98  (3)  str.charAt(3) is d and conversion char to int is 101 ( ascii of 'd')

  STEP #2 :  1 << val equal to ( 1 << 3 ) equal to 8  finally 8 & 8 is 8
     Now print 'd'  since the value > 0

您也可以使用位向量,这取决于它将节省空间的语言。在java中,我更愿意在C递归解决方案中使用int来实现这个固定的26常量大小写

 static void getNonUniqueElements(string s, string nonUnique)
    {
        if (s.Count() > 0)
        {
            char ch = s[0];
            s = s.Substring(1);
            if (s.LastIndexOf(ch) > 0)
            {
                if (nonUnique.LastIndexOf(ch) < 0)
                    nonUnique += ch;

            }
            getNonUniqueElements(s, nonUnique);
        }
        else
        {
            Console.WriteLine(nonUnique);
            return;
        }
    }
    static void Main(string[] args)
    {
        getNonUniqueElements("aabcacdddec", "");
        Console.ReadKey();
    }

使用位集意味着您可以在一次过程中完成此操作,甚至比我的答案更好。常量空格并不意味着没有空格。该数组将具有恒定大小的26个元素。