Implement strStr().
Returns a pointer to the first occurrence of needle in haystack, or null if needle is not part of haystack.
needle in the haystack 大海捞针的意思
其实就是找出 “短字符串” 在 “长字符串” 中的位置。
1 public static string strStr(string haystack, string needle) 2 { 3 if (haystack.Length == 0) 4 return string.Empty; 5 if (needle.Length == 0) 6 return string.Empty; 7 if (needle.Length > haystack.Length) 8 return string.Empty; 9 10 for (int i = 0; i < haystack.Length; i++) 11 { 12 bool found = true; 13 for (int j = 0; j < needle.Length; j++) 14 { 15 if (haystack[i + j] != needle[j]) 16 { 17 found = false; 18 break; 19 } 20 } 21 if(found) 22 return haystack.Substring(i); 23 } 24 25 return string.Empty; 26 }
代码分析:
第一时间想到的应该是这个两重循环的方法,O(n2)。
1 public static string strStrOpt(string haystack, string needle) 2 { 3 if (haystack.Length == 0) 4 return string.Empty; 5 if (needle.Length == 0) 6 return string.Empty; 7 if (needle.Length > haystack.Length) 8 return string.Empty; 9 10 //Create a partial match table 11 int[] table = new int[needle.Length]; 12 partial_table(needle, table); 13 14 // Search 15 int h_index = 0; 16 int n_index = 0; 17 18 while (h_index + n_index < haystack.Length) 19 { 20 if (needle[n_index] == haystack[h_index + n_index]) 21 { 22 if (n_index == needle.Length - 1) 23 return haystack.Substring(h_index); 24 else 25 ++n_index; 26 } 27 else 28 { 29 h_index = h_index + n_index - table[n_index]; 30 if (table[n_index] > -1) 31 n_index = table[n_index]; 32 else 33 n_index = 0; 34 } 35 } 36 37 return string.Empty; 38 } 39 40 public static void partial_table(string word, int[] table) 41 { 42 if (0 == table.Length) 43 return; 44 45 if (1 == table.Length) 46 { 47 table[0] = -1; 48 return; 49 } 50 51 table[0] = -1; 52 table[1] = 0; 53 54 int pos = 2; 55 int cnd = 0; 56 57 while (pos < table.Length) 58 { 59 if (word[pos - 1] == word[cnd]) 60 table[pos++] = ++cnd; 61 else if (cnd > 0) 62 cnd = table[cnd]; 63 else 64 table[pos++] = 0; 65 } 66 }
代码分析:
为了提高效率,我们希望直接跳到needle长度后一个字符来比较。比如说。
“ABDABDABC”中找“ABC"。如果对比完第一个"ABD"发现不相等,我们希望跳到下一个"A"开始,而不是从字符串中第二个字符"B"开始。
但是如果needle字符串中带有重复的。比如 "ABABACAB" 中找 “ABAC" 比较完 "ABAB" != "ABAC"以后,不能跳到第3个"A"开始比较,因为needle中有重复的,这样会错过了从第二个”A"开始的“ABAC".
所以,以上代码使用了一个array来 看needle字符串中重复位置。
”ABAC" 会生成ARRAY [ -1,0,0,1], 当比较到"B" != "C", h_index = h_index + n_index - table[n_index], 从第2个“A”开始再比较。