Monday, August 5, 2013

[Microsoft] string permutation with upcase and lowcase

Give a string, which only contains a-z. List all the permutation of upcase and lowcase.
For example, str = "ab",  the output should be
"ab", "aB", "Ab", "AB"
for str = "abc", the output should be
"abc", "abC", "aBc", "aBC", "Abc", "AbC", "ABc", "ABC"

[Thoughts]
首先,肯定可以用递归来做,每一个节点有大小两种可能。代码可以简单的写成:
  1: void ListPermutation(string sample, int depth, string& result)
  2: {
  3:     if(depth == sample.size())
  4:     {
  5:         prinf("%s\r\n", result.c_str());
  6:         return;
  7:     }
  8:     
  9:     // process low-case char
 10:     result.push_back(sample[depth]);
 11:     ListPermutation(sample, depth+1, result);
 12:     result.pop_back();
 13:     
 14:     //process up-case char
 15:     result.push_back(sample[depth]-32);
 16:     ListPermutation(sample, depth+1, result);
 17:     result.pop_back();
 18: }

但是,如果考虑空间复杂度的话,这是个指数级的实现。如果字符串有几千行或者几万行,内存就不得了了。

如果换个思路想想的话,其实这个题有简单的解法。因为,大写和小写只有两种变化,其实就是0和1的变化。简单的说,如果字符串长L,那么遍历区间[0,2^L-1],对于任意i,将其转换为长度为L的二进制表示,然后根据每一位二进制是0还是1,来决定输出大写还是小写。实现如下:
  1: void ListPermutation(string sample)
  2: {
  3:     int L = sample.size();
  4:     long end = pow(2, L) -1;
  5:     for(int i =0; i< end; i++)
  6:     {
  7:         // Convert Dec to Binary, 
  8:         // return a string to represent binary data with size L
  9:         string binaryRep = ConvertDecToBinany(i, L);
 10:         
 11:         string output;
 12:         for(int j=0; j<L; j++)
 13:         {
 14:             if(binaryRep[j] == '0') //low case
 15:             {
 16:                 output.push_back(sample[j]);
 17:             }
 18:             else
 19:             {
 20:                 output.push_back(sample[j]-32);
 21:             }        
 22:         }
 23:         printf("%s\r\n", output.c_str());
 24:     }
 25: }

这样的话,整体思路就更清晰,而且内存使用是O(L)。





No comments: