字符串算法
- 字符串字符判重算法
- 字符串反转算法
- 字符串左旋算法
- 字符串右旋算法
- 字符串旋转匹配算法
- 字符串包含算法
- 字符串删除算法
- 字符串原地替换算法
- 字符串压缩算法
- 字符串变位词检测算法
- 字符串转整数算法
- 字符串全排列算法
- 字符串字典序组合算法
- 字符串的(括号)生成算法
字符串字符判重算法
给定字符串,确定是否字符串中的所有字符全都是不同的。假设字符集是 ASCII。
1 using System;
2 using System.Collections.Generic;
3
4 namespace AlgorithmTesting
5 {
6 class Program
7 {
8 static void Main(string[] args)
9 {
10 Console.WriteLine(IsUniqueChars("asdf5678888888".ToCharArray()));
11 Console.WriteLine(IsUniqueChars("asdf5678!@#$%^&".ToCharArray()));
12 Console.WriteLine(IsUniqueSmallAlphabetChars("asdf5678!@#$%^&".ToCharArray()));
13 Console.WriteLine(IsUniqueSmallAlphabetChars("asdf5678".ToCharArray()));
14 Console.WriteLine(IsUniqueSmallAlphabetChars("asdf{}".ToCharArray()));
15 Console.WriteLine(IsUniqueSmallAlphabetChars("asdf".ToCharArray()));
16 Console.ReadKey();
17 }
18
19 static bool IsUniqueChars(char[] str)
20 {
21 if (str.Length > 256)
22 return false;
23
24 // 为每个字符保存一个是否存在标记
25 bool[] charSet = new bool[256];
26 for (int i = 0; i < str.Length; i++)
27 {
28 var index = (byte)str[i];
29 if (charSet[index])
30 {
31 return false;
32 }
33 charSet[index] = true;
34 }
35
36 return true;
37 }
38
39 static bool IsUniqueSmallAlphabetChars(char[] str)
40 {
41 if (str.Length > 26)
42 return false;
43
44 // 使用位操作以改进空间占用
45 int checker = 0;
46 for (int i = 0; i < str.Length; i++)
47 {
48 int index = str[i] - 'a';
49 if (index < 0
50 || index > 26
51 || (checker & (1 << index)) > 0)
52 {
53 return false;
54 }
55 checker |= (1 << index);
56 }
57
58 return true;
59 }
60 }
61 }
字符串反转算法
有字符串 s1 = "ABC1DEF",要求将其反转成 "FED1CBA"。
1 using System;
2
3 namespace ConsoleApplication1
4 {
5 class Program
6 {
7 static void Main(string[] args)
8 {
9 string text1 = "ABC1DEF";
10 string text2 = "ABC1DEFG";
11 char[] t1 = text1.ToCharArray();
12 char[] t2 = text2.ToCharArray();
13
14 ReversePartOfString(t1, 1, t1.Length - 2);
15 ReversePartOfString(t2, 1, t2.Length - 2);
16
17 string s1 = new string(t1);
18 string s2 = new string(t2);
19 Console.WriteLine(s1);
20 Console.WriteLine(s2);
21
22 string text3 = "ABC1DEF";
23 string text4 = "ABC1DEFG";
24 char[] t3 = text3.ToCharArray();
25 char[] t4 = text4.ToCharArray();
26
27 ReverseArrayByXor(t3);
28 ReverseArrayByXor(t4);
29
30 string s3 = new string(t3);
31 string s4 = new string(t4);
32 Console.WriteLine(s3);
33 Console.WriteLine(s4);
34
35 Console.ReadKey();
36 }
37
38 static void ReversePartOfString(char[] s, int begin, int length)
39 {
40 char temp;
41 for (int i = begin, j = begin + length - 1; i < j; i++, j--)
42 {
43 temp = s[i];
44 s[i] = s[j];
45 s[j] = temp;
46 }
47 }
48
49 static void ReversePartOfStringWithWhile(char[] s, int begin, int length)
50 {
51 // actually, use while is same with use for loop
52 // which one looks better?
53 char temp;
54 int i = begin;
55 int j = begin + length - 1;
56 while (i < j)
57 {
58 temp = s[i];
59 s[i] = s[j];
60 s[j] = temp;
61 i++;
62 j--;
63 }
64 }
65
66 static void ReverseArray(char[] s)
67 {
68 char temp;
69 for (int i = 0, j = s.Length - 1; i < j; i++, j--)
70 {
71 temp = s[i];
72 s[i] = s[j];
73 s[j] = temp;
74 }
75 }
76
77 static void ReverseArrayByXor(char[] s)
78 {
79 for (int i = 0, j = s.Length - 1; i < j; i++, j--)
80 {
81 // XOR 2 values bitwise 3 times and they're switched
82 s[i] ^= s[j];
83 s[j] ^= s[i];
84 s[i] ^= s[j];
85 }
86 }
87 }
88 }
字符串左旋算法
给定一个字符串,要求把字符串前面的若干个字符移动到字符串的尾部,如把字符串 "abcdef" 前面的 2 个字符 'a' 和 'b' 移动到字符串的尾部,使得原字符串变成字符串 "cdefab"。要求对长度为 n 的字符串操作的时间复杂度为 O(n),空间复杂度为 O(1)。
1 using System;
2
3 namespace ConsoleApplication1
4 {
5 class Program
6 {
7 static void Main(string[] args)
8 {
9 string s1 = "abcdefg";
10 string s2 = "abcdefgh";
11
12 char[] a1 = s1.ToCharArray();
13 char[] a2 = s2.ToCharArray();
14
15 LeftRotateStringByGcd(a1, 2);
16 LeftRotateStringByGcd(a2, 2);
17
18 string str1 = new string(a1);
19 string str2 = new string(a2);
20 Console.WriteLine(str1);
21 Console.WriteLine(str2);
22
23 Console.ReadKey();
24 }
25
26 static void LeftRotateString(char[] s, int m)
27 {
28 ReverseString(s, 0, m - 1);
29 ReverseString(s, m, s.Length - 1);
30 ReverseString(s, 0, s.Length - 1);
31 }
32
33 static void ReverseString(char[] s, int begin, int end)
34 {
35 char temp;
36 int i = begin;
37 int j = end;
38 while (i < j)
39 {
40 temp = s[i];
41 s[i] = s[j];
42 s[j] = temp;
43 i++;
44 j--;
45 }
46 }
47
48 static int Gcd(int m, int n)
49 {
50 int k = m % n;
51 if (k == 0)
52 return n;
53 else
54 return Gcd(n, k);
55 }
56
57 static void LeftRotateStringByGcd(char[] s, int m)
58 {
59 int n = s.Length;
60 int g = Gcd(n, m);
61 int e = n / g;
62
63 char temp;
64 for (int i = 0; i < g; i++)
65 {
66 temp = s[i];
67
68 int j = 0;
69 for (; j < e - 1; j++)
70 {
71 s[(i + j * m) % n] = s[(i + (j + 1) * m) % n];
72 }
73
74 s[(i + j * m) % n] = temp;
75 }
76 }
77 }
78 }
字符串右旋算法
给定一个字符串,要求把字符串后面的若干个字符移动到字符串的头部,如把字符串 "abcdef" 后面的 2 个字符 'e' 和 'f' 移动到字符串的头部,使得原字符串变成字符串 "efabcd"。要求对长度为 n 的字符串操作的时间复杂度为 O(n),空间复杂度为 O(1)。
1 using System;
2
3 namespace ConsoleApplication1
4 {
5 class Program
6 {
7 static void Main(string[] args)
8 {
9 string s3 = "abcdefg";
10 string s4 = "abcdefgh";
11
12 char[] a3 = s3.ToCharArray();
13 char[] a4 = s4.ToCharArray();
14
15 RightRotateString(a3, 2);
16 RightRotateString(a4, 2);
17
18 string str3 = new string(a3);
19 string str4 = new string(a4);
20 Console.WriteLine(str3);
21 Console.WriteLine(str4);
22
23 Console.ReadKey();
24 }
25
26 static void RightRotateString(char[] s, int m)
27 {
28 ReverseString(s, 0, s.Length - m - 1);
29 ReverseString(s, s.Length - m, s.Length - 1);
30 ReverseString(s, 0, s.Length - 1);
31 }
32
33 static void ReverseString(char[] s, int begin, int end)
34 {
35 char temp;
36 int i = begin;
37 int j = end;
38 while (i < j)
39 {
40 temp = s[i];
41 s[i] = s[j];
42 s[j] = temp;
43 i++;
44 j--;
45 }
46 }
47 }
48 }
字符串旋转匹配算法
给定两个字符串 s1 和 s2,如何判断 s1 是 s2 的一个旋转版本?
1 using System;
2
3 namespace ConsoleApplication1
4 {
5 class Program
6 {
7 static void Main(string[] args)
8 {
9 // Given two string s1 and s2
10 // how will you check if s1 is a rotated version of s2 ?
11
12 string s1 = "tackoverflows";
13 string s2 = "ackoverflowst";
14 string s3 = "overflowstack";
15 string s4 = "stackoverflwo";
16
17 string pattern = "stackoverflow";
18
19 Console.WriteLine(string.Format("{0}, {1}, {2}", s1, pattern, CheckRotation(s1, pattern)));
20 Console.WriteLine(string.Format("{0}, {1}, {2}", s2, pattern, CheckRotation(s2, pattern)));
21 Console.WriteLine(string.Format("{0}, {1}, {2}", s3, pattern, CheckRotation(s3, pattern)));
22 Console.WriteLine(string.Format("{0}, {1}, {2}", s4, pattern, CheckRotation(s4, pattern)));
23
24 Console.ReadKey();
25 }
26
27 static bool CheckRotation(string s1, string s2)
28 {
29 return s1.Length == s2.Length
30 && (s1 + s1).IndexOf(s2) != -1;
31 }
32 }
33 }
字符串包含算法
给定两个分别由字母组成的字符串 s1 和字符串 s2,如何最快地判断字符串 s2 中所有字母是否都在字符串 s1 里?
1 using System;
2
3 namespace ConsoleApplication1
4 {
5 class Program
6 {
7 static void Main(string[] args)
8 {
9 string s1 = "abcdefg";
10 string s2 = "cfx";
11
12 char[] a1 = s1.ToCharArray();
13 char[] a2 = s2.ToCharArray();
14
15 Console.WriteLine(
16 string.Format("{0}, {1}, {2}", s1, s2, IsContainAllChars(a1, a2)));
17
18 Console.ReadKey();
19 }
20
21 // 给定两个分别由字母组成的字符串a和字符串b
22 // 判断字符串b中所有字母是否都在字符串a里?
23 // 时间复杂度O(n + m),空间复杂度O(1)
24 static bool IsContainAllChars(char[] a, char[] b)
25 {
26 int hash = 0;
27 for (int i = 0; i < a.Length; ++i)
28 {
29 hash |= (1 << (a[i] - 'A'));
30 }
31
32 for (int i = 0; i < b.Length; ++i)
33 {
34 if ((hash & (1 << (b[i] - 'A'))) == 0)
35 {
36 return false;
37 }
38 }
39
40 return true;
41 }
42 }
43 }
字符串原地替换算法
将字符串 s1 中的某字符 p 全部替换成字符串 s2。假设 s1 字符数组尾部有足够的空间存放新增字符。
1 using System;
2 using System.Collections.Generic;
3
4 namespace AlgorithmTesting
5 {
6 class Program
7 {
8 static void Main(string[] args)
9 {
10 // 假设 s1 有足够的冗余空间
11 char[] s1 = new char[100];
12 for (int i = 0; i < 9; i = i + 3)
13 {
14 s1[i] = 'a';
15 s1[i + 1] = 'b';
16 s1[i + 2] = 'c';
17 }
18
19 Console.WriteLine(new string(s1));
20 ReplaceChars(s1, 9, 'b', "%&$".ToCharArray());
21 Console.WriteLine(new string(s1));
22 Console.ReadKey();
23 }
24
25 // 将字符串 s1 中的某字符 p 替换成字符串 s2
26 static void ReplaceChars(char[] s1, int s1Length, char p, char[] s2)
27 {
28 int count = 0;
29 for (int i = 0; i < s1.Length; i++)
30 {
31 if (s1[i] == p)
32 count++;
33 }
34
35 int newLength = s1Length + count * (s2.Length - 1);
36
37 // 从尾部开始编辑,从后向前操作,无须担心覆写原数据
38 for (int i = s1Length - 1; i >= 0; i--)
39 {
40 if (s1[i] == p)
41 {
42 for (int j = 0; j < s2.Length; j++)
43 {
44 s1[newLength - s2.Length + j] = s2[j];
45 }
46 newLength = newLength - s2.Length;
47 }
48 else
49 {
50 s1[newLength - 1] = s1[i];
51 newLength = newLength - 1;
52 }
53 }
54 }
55 }
56 }
字符串压缩算法
给定字符串 s,要求将连续出现的字符压缩至字符和数量,并返回新的字符串。
比如:s = "aabccccaaa",则压缩后的字符串为 s2 = "a2b1c4a3"。
1 using System;
2 using System.Collections.Generic;
3
4 namespace AlgorithmTesting
5 {
6 class Program
7 {
8 static void Main(string[] args)
9 {
10 string s1 = "aabccccaaa";
11 Console.WriteLine(s1);
12 char[] s2 = Compress(s1.ToCharArray());
13 Console.WriteLine(new string(s2));
14
15 string s3 = "aabccdeeaa";
16 Console.WriteLine(s3);
17 char[] s4 = Compress(s3.ToCharArray());
18 Console.WriteLine(new string(s4));
19
20 Console.ReadKey();
21 }
22
23 static char[] Compress(char[] s)
24 {
25 // 如果压缩后比原来还长,则不必压缩
26 int size = CountCompression(s);
27 if (size >= s.Length)
28 return s;
29
30 // 根据计算的压缩后长度生成数组
31 char[] compressed = new char[size];
32
33 int index = 0;
34 char last = s[0];
35 int count = 1;
36 for (int i = 1; i < s.Length; i++)
37 {
38 if (s[i] == last) // 找到重复字符
39 {
40 count++;
41 }
42 else
43 {
44 // 当前字符处理完毕
45 index = AppendChar(compressed, last, index, count);
46
47 // 处理下一个字符
48 last = s[i];
49 count = 1;
50 }
51 }
52
53 // 添加最后一个字符
54 index = AppendChar(compressed, last, index, count);
55
56 return compressed;
57 }
58
59 static int AppendChar(char[] array, char c, int index, int count)
60 {
61 array[index] = c;
62 index++;
63
64 char[] countString = count.ToString().ToCharArray();
65
66 for (int i = 0; i < countString.Length; i++)
67 {
68 array[index] = countString[i];
69 index++;
70 }
71
72 return index;
73 }
74
75 static int CountCompression(char[] s)
76 {
77 if (s == null || s.Length == 0)
78 return 0;
79
80 // 计算压缩后的长度
81 int size = 0;
82
83 char last = s[0];
84 int count = 1;
85 for (int i = 0; i < s.Length; i++)
86 {
87 if (s[i] == last) // 找到重复字符
88 {
89 count++;
90 }
91 else
92 {
93 // 当前字符处理完毕
94 size += 1 + count.ToString().ToCharArray().Length;
95
96 // 处理下一个字符
97 last = s[i];
98 count = 1;
99 }
100 }
101
102 size += 1 + count.ToString().ToCharArray().Length;
103
104 return size;
105 }
106 }
107 }
字符串变位词检测算法
给定字符串 s1 和 s2,判断是否能够将 s1 中的字符重新排列后变成 s2。假设字符全部为小写 a-z 字符,字符串中没有空格。
变位词(anagram):是由变换某个词或短语的字母顺序而构成的新的词或短语。
1 using System;
2 using System.Collections.Generic;
3
4 namespace AlgorithmTesting
5 {
6 class Program
7 {
8 static void Main(string[] args)
9 {
10 Console.WriteLine(IsPermutation(
11 "hello".ToCharArray(), "ehollu".ToCharArray()));
12 Console.WriteLine(IsPermutation(
13 "hello".ToCharArray(), "eholu".ToCharArray()));
14 Console.WriteLine(IsPermutation(
15 "hello".ToCharArray(), "eholl".ToCharArray()));
16 Console.ReadKey();
17 }
18
19 static bool IsPermutation(char[] s1, char[] s2)
20 {
21 if (s1.Length != s2.Length)
22 return false;
23
24 int[] letters = new int[256];
25 for (int i = 0; i < s1.Length; i++)
26 {
27 letters[s1[i]]++;
28 }
29
30 for (int i = 0; i < s2.Length; i++)
31 {
32 letters[s2[i]]--;
33 if (letters[s2[i]] < 0)
34 return false;
35 }
36
37 return true;
38 }
39 }
40 }
字符串删除算法
给定两个分别由字母组成的字符串 s1 和字符串 s2,将字符串 s2 中所有字符都在字符串 s1 中删除?
1 using System;
2
3 namespace ConsoleApplication1
4 {
5 class Program
6 {
7 static void Main(string[] args)
8 {
9 string text = "cdacbcdefabcdef";
10 string pattern = "ab";
11
12 char[] t = text.ToCharArray();
13 char[] p = pattern.ToCharArray();
14
15 // generate hash table of pattern
16 bool[] hash = new bool[256];
17 for (int i = 0; i < p.Length; i++)
18 {
19 hash[p[i]] = true;
20 }
21
22 // compare text chars exist in pattern
23 int faster = 0;
24 int slower = 0;
25 while (faster < t.Length)
26 {
27 // want to save some space
28 if (!hash[t[faster]])
29 {
30 t[slower] = t[faster];
31 faster++;
32 slower++;
33 }
34 else
35 {
36 faster++;
37 }
38 }
39
40 // make string
41 string s = new string(t, 0, slower);
42
43 Console.WriteLine(s);
44 Console.ReadKey();
45 }
46 }
47 }
字符串转整数算法
输入一个由数字组成的字符串,把它转换成整数并输出。例如:输入字符串 "123",输出整数 123。
1 using System;
2
3 namespace ConsoleApplication1
4 {
5 class Program
6 {
7 static void Main(string[] args)
8 {
9 // good
10 Console.WriteLine(string.Format("{0}, {1}",
11 "12345", StringToInt32("12345".ToCharArray())));
12 Console.WriteLine(string.Format("{0}, {1}",
13 "-12345", StringToInt32("-12345".ToCharArray())));
14
15 // max
16 Console.WriteLine(string.Format("{0}, {1}",
17 "2147483647", StringToInt32("2147483647".ToCharArray())));
18 Console.WriteLine(string.Format("{0}, {1}",
19 "-2147483648", StringToInt32("-2147483648".ToCharArray())));
20
21 // overflow
22 Console.WriteLine(string.Format("{0}, {1}",
23 "21474836470", StringToInt32("21474836470".ToCharArray())));
24 Console.WriteLine(string.Format("{0}, {1}",
25 "-21474836480", StringToInt32("-21474836480".ToCharArray())));
26
27 Console.ReadKey();
28 }
29
30 static int StringToInt32(char[] s)
31 {
32 // do you need handle space?
33 // do you need handle bad char?
34
35 // check string null
36 if (s.Length == 0)
37 {
38 return 0;
39 }
40
41 int value = 0;
42 int i = 0;
43
44 // check positive or negative
45 int sign = 1;
46 if (s[0] == '+' || s[0] == '-')
47 {
48 if (s[0] == '-')
49 sign = -1;
50 i++;
51 }
52
53 while (i < s.Length)
54 {
55 int c = s[i] - '0';
56
57 // handle overflow
58 if (sign > 0
59 && (value > int.MaxValue / 10
60 || (value == int.MaxValue / 10
61 && c >= int.MaxValue % 10)))
62 {
63 value = int.MaxValue;
64 break;
65 }
66 else if (sign < 0
67 && (value > -(int.MinValue / 10)
68 || (value == -(int.MinValue / 10)
69 && c >= -(int.MinValue % 10))))
70 {
71 value = int.MinValue;
72 break;
73 }
74
75 // calculate the value based on 10 times
76 value = value * 10 + c;
77
78 i++;
79 }
80
81 return sign > 0
82 ? value
83 : value == int.MinValue ? value : -value;
84 }
85 }
86 }
字符串全排列算法
输入一个字符串,打印出该字符串中字符的所有排列。
例如:输入字符串 "abc",则输出由字符 'a', 'b', 'c' 所能排列出来的所有字符串:abc, acb, bac, bca, cab, cba。
1 using System;
2
3 namespace ConsoleApplication1
4 {
5 class Program
6 {
7 static void Main(string[] args)
8 {
9 // 要求首次输入是有序的,否则需要排序
10 CalculateAllPermutations("abc".ToCharArray());
11
12 Console.ReadKey();
13 }
14
15 static void CalculateAllPermutations(char[] s)
16 {
17 // 输出当前排列
18 Console.WriteLine(new string(s));
19
20 int i, j;
21
22 // 找到排列中最右一个升序的首位位置 i
23 for (i = s.Length - 2; (i >= 0) && (s[i] >= s[i + 1]); --i) ;
24
25 // 已经找到所有排列
26 if (i < 0) return;
27
28 // 找到排列中第 i 位右边最后一个比 s[i] 大的位置 j
29 for (j = s.Length - 1; (j > i) && (s[j] <= s[i]); --j) ;
30
31 // 交换 s[i],s[j]
32 Swap(s, i, j);
33
34 // 将第 i + 1 位到最后的部分反转
35 Reverse(s, i + 1, s.Length - 1);
36
37 // 继续下一次排列
38 CalculateAllPermutations(s);
39 }
40
41 static void Swap(char[] s, int i, int j)
42 {
43 char temp = s[i];
44 s[i] = s[j];
45 s[j] = temp;
46 }
47
48 static void Reverse(char[] s, int begin, int end)
49 {
50 char temp;
51 int i = begin;
52 int j = end;
53 while (i < j)
54 {
55 temp = s[i];
56 s[i] = s[j];
57 s[j] = temp;
58 i++;
59 j--;
60 }
61 }
62 }
63 }
字符串字典序组合算法
输入一个字符串,字符串里的字符是互不相同的,打印出该字符串中字符按照字典序输出所有的组合。
例如:输入字符串 "ab",则输出由字符 'a', 'b' 所能排列出来的所有字符串:aa, ab, ba, bb。
1 using System;
2
3 namespace ConsoleApplication1
4 {
5 class Program
6 {
7 static void Main(string[] args)
8 {
9 // 要求字符是不同的,否则需要去重
10 // 要求输入是有序的,否则需要排序
11 CalculateRepeatablePermutations("abc".ToCharArray(), new char[3], 0);
12
13 Console.ReadKey();
14 }
15
16 static void CalculateRepeatablePermutations(char[] s, char[] permutation, int p)
17 {
18 if (p == s.Length)
19 {
20 Console.WriteLine(new string(permutation));
21 }
22 else
23 {
24 for (int i = 0; i < s.Length; ++i)
25 {
26 permutation[p] = s[i];
27 CalculateRepeatablePermutations(s, permutation, p + 1);
28 }
29 }
30 }
31 }
32 }
字符串的(括号)生成算法
输出 n 对括号的全部有效组合。
1 using System;
2 using System.Collections.Generic;
3
4 namespace AlgorithmTesting
5 {
6 class Program
7 {
8 static void Main(string[] args)
9 {
10 List<string> parenList = GenerateParens(3);
11 foreach (var item in parenList)
12 {
13 Console.WriteLine(item);
14 }
15
16 Console.ReadKey();
17 }
18
19 static List<string> GenerateParens(int count)
20 {
21 char[] str = new char[count * 2];
22 List<string> list = new List<string>();
23 AddParen(list, count, count, str, 0);
24 return list;
25 }
26
27 static void AddParen(
28 List<string> list,
29 int leftRem,
30 int rightRem,
31 char[] str,
32 int count)
33 {
34 // 无效状态
35 if (leftRem < 0 || rightRem < leftRem)
36 return;
37
38 // 无括号可用
39 if (leftRem == 0 && rightRem == 0)
40 {
41 string s = new string(str);
42 list.Add(s);
43 }
44 else
45 {
46 // 还有左括号可用
47 if (leftRem > 0)
48 {
49 str[count] = '(';
50 AddParen(list, leftRem - 1, rightRem, str, count + 1);
51 }
52
53 // 还有右括号可用
54 if (rightRem > leftRem)
55 {
56 str[count] = ')';
57 AddParen(list, leftRem, rightRem - 1, str, count + 1);
58 }
59 }
60 }
61 }
62 }

浙公网安备 33010602011771号