倒转字符串的另一种BT方法
比如说字符串abcdefgh,那么反转顺序为
abcdefgh => badcfehg => dcbahgfe => hgfedcba
这种算法对于字符串的位数等于2的N次方,是很简单的,比如说,一个长度8的字符串,其反转算法如下:
static string ReverseBitArray2(string str) { if (str == null || str.Length == 1) return str; char[] arr = str.ToCharArray(); int pow = 1; while (pow < arr.Length) { for (int i = 0; i < arr.Length; i = i + pow * 2) { for (int j = i; j < i + pow; j++) { char temp = arr[j]; arr[j] = arr[j + pow]; arr[j + pow] = temp; } } pow *= 2; } return new string(arr); }
如果字符串的位数不等于2的N次方呢?这也是大多数情况,我们需要额外进行很多判断,逻辑不要太复杂,所以未必是一种好办法。
我们不妨考虑,扩展这个需要反转的字符串,为其尾部添加一些字符,使其长度变成2的N次方,然后就可以使用我们上面的算法了,最后记得开头的若干字符是不要的哦,代码如下:
static string ReverseBitArray2(string str) { if (str == null || str.Length == 1) return str; int pow = GetPow(str); if (pow == 0) return ReverseBitArray(str); else { char[] arr = new char[pow]; int i = 0; while (i < str.Length) { arr[i] = str[i]; i++; } return ReverseBitArray(arr, str.Length); } }
为此我们要重载ReverseBitArray函数,以适合最普通的情形:
static string ReverseBitArray(char[] arr, int actualLength) { int pow = 1; while (pow < arr.Length) { for (int i = 0; i < arr.Length; i = i + pow * 2) { for (int j = i; j < i + pow; j++) { char temp = arr[j]; arr[j] = arr[j + pow]; arr[j + pow] = temp; } } pow *= 2; } return new string(arr, arr.Length - actualLength, actualLength); }
注:这里我们用到了GetPow函数,如果str的长度是2的N次幂,就返回0;否则,返回大于str长度的最小2的N次幂:
static int GetPow(string str) { int len = str.Length; int pow = 2; while (pow < len) { pow = pow << 1; } if (pow == len) return 0; else //pow>len return pow; }
但这种算法需要额外的空间,最糟糕的情况,如果字符串长度为2的N次方+1,那么我们就要多分配2的N次方-1的空间。但比起分配一个和原数组等长的栈,大大的节省了空间。
分而治之的思想,妙极!大家细细品味。