第一次被微软的人面试就被面了一个好题目,好在自己答上了,现在show一下,和大家分享一下。
题目:写一个函数给它三个字符串作为参数,它们分别是str1,str2,str3, 让函数返回在str1中以str2开头,str3结尾的字符串,并写出测试用例。
2. public static List<string> FindSubString(string str1, string str2, string str3)
3. {
4. if (str1.IndexOf(str2) == -1 || str1.IndexOf(str3) == -1)
5. {
//str1中不包含str2或者str3.
6. throw new ArgumentException(“The start string or the end string does not exist in str1.”);
7. }
//搜索并记录str1中str2的位置
8. List<int> startPos = new List<int>();
9. int searchPos = 0;
10. while (searchPos != -1)
11. {
12. searchPos = str1.IndexOf(str2,searchPos);
13. if (searchPos != -1)
14. {
15. startPos.Add(searchPos);
16. }
17. else
18. {
19. break;
20. }
21. searchPos++;
22.
23. }
//搜索并记录str1中str3的位置
24. List<int> endPos = new List<int>();
25. searchPos=0;
26. while (searchPos != -1)
27. {
28. searchPos = str1.IndexOf(str3,searchPos);
29. if (searchPos != -1)
30. {
31. endPos.Add(searchPos);
32. }
33. else
34. {
35. break;
36. }
37. searchPos++;
38.
39. }
//通过str2和str3的位置来找处以str2开头,以str3结尾的字符串
40. List<string> r = new List<string>();
//str2的位置从头扫描
41. foreach (int s in startPos)
42. {
43. int[] e = endPos.ToArray();
//str3的位置从尾部扫描
44. for (int i = e.Length – 1; i >= 0; i–)
45. {
//如果str2的位置+它的长度 〈= str3的位置+它的长度:表明str2没有把str3包含再它里面,是我们想要的字符串。
46. if (s <= e[i] && s+str2.Length <= e[i]+str3.Length)
47. {
48. string temp = str1.Substring(s, e[i]-s+str3.Length);
49. if (!r.Contains(temp))
50. {
//结果字符串的集合内没有包含这个字符串再把它加入。
51. r.Add(temp);
52. }
53. }
54. else
55. {
56. break;
57. }
58. }
59. }
60. return r;
}
原以为这个程序ok了,后来发现还是有许多defect的,不过思想是对的,但原来的程序没有对str1,str2和str3为null的情况的考虑,以及str2,str3为string.Empty的考虑,还有一个问题就把最后的字符串添加到list中,用list.Contains去判断,这样他的时间复杂度是O(n),整个程序的时间复杂度就是O(n*n*n),我们可以用Diectory去替换,最后的时间复杂度就是O(n*n),下面是这个程序的改进版本:
public static List<string> FindSubString(string str1, string str2, string str3)
{
if(str1 == null ||str2==null ||str3==null)
{
throw new NullReferenceException(“str1 str2 and str3 can not be null!”);
}
if(str2.Length > str1.Length || str3.Length > str1.Length)
{
throw new ArgumentOutOfRangeException(“str1 is not long enough!”);
}
List<string> result = new List<string>();
if (str2 ==string.Empty && str3 !=string.Empty)
{
if (str1.IndexOf(str3) != -1)
{
result.Add(str3);
}
return result;
}
if ((str3 == string.Empty && str2 != string.Empty) || str2 == str3)
{
if (str1.IndexOf(str2) != -1)
{
result.Add(str2);
}
return result;
}
Dictionary<string,string> resultDic = new Dictionary<string,string>();
// require two integer list to store the position where the str2 and str3 in str1.
List<int> str2Pos = new List<int>();
List<int> str3Pos = new List<int>();
//find position of str2 and str3 in str1.
int pos = -1;
do
{
pos = str1.IndexOf(str2, pos + 1);
if (pos != -1)
{
str2Pos.Add(pos);
}
} while (pos != -1);
do
{
pos = str1.IndexOf(str3, pos + 1);
if (pos != -1)
{
str3Pos.Add(pos);
}
} while (pos != -1);
for (int i = 0; i < str2Pos.Count; ++i)
{
for (int j = str3Pos.Count – 1; j >= 0; –j)
{
if (str2Pos[i] <= str3Pos[j])
{
//str2 doesn’t contains str3
if (str3Pos[j] + str3.Length >= str2Pos[i] + str2.Length)
{
string item =str1.Substring(str2Pos[i], str3Pos[j] + str3.Length-str2Pos[i]);
if(!resultDic.ContainsKey(item))
{
resultDic.Add(item,item);
}
}
}
else
{
break;
}
}
}
return resultDic.Keys.ToList();
}