一道微软面试时碰到的,经典的,关于字符串操作的面试题目

第一次被微软的人面试就被面了一个好题目,好在自己答上了,现在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();

        } 

 

点赞