题目描述

编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 ""

示例 1:

  1. 输入: ["flower","flow","flight"]
  2. 输出: "fl"

示例 2:

  1. 输入: ["dog","racecar","car"]
  2. 输出: ""
  3. 解释: 输入不存在公共前缀。

说明:
所有输入只包含小写字母 a-z

题解

纵向扫描

纵向扫码的优势在于当存在不同字符时,能最快的结束扫描。
下面的代码通过将同一位置的字符 Select 出来,再 Count 不同的字符数,仅在字符全相同时 Count 结果才为 1。

  1. public string LongestCommonPrefix(string[] strs)
  2. {
  3. if (strs == null || strs.Length == 0) return "";
  4. if (strs.Length == 1) return strs[0];
  5. var minLength = strs.Min(s => s.Length);
  6. var commonPrefix = "";
  7. for (var i = 0; i < minLength; i++)
  8. {
  9. var count = strs.Select(s => s[i]).Distinct().Count();
  10. if (count > 1) break;
  11. commonPrefix += strs[0][i];
  12. }
  13. return commonPrefix;
  14. }

Binary Search

参考官方,方法如图:
二分搜索,搜索到第一个不相等的部分暂停。
014 最长公共前缀 - 图1

  1. public static string LongestCommonPrefix(string[] strs)
  2. {
  3. if (strs == null || strs.Length == 0) return "";
  4. if (strs.Length == 1) return strs[0];
  5. var minLength = strs.Min(s => s.Length);
  6. var low = 1;
  7. var high = minLength;
  8. while (low <= high)
  9. {
  10. var middle = (low + high) / 2;
  11. if (IsCommonPrefix(strs, middle))
  12. {
  13. low = middle + 1;
  14. }
  15. else
  16. {
  17. high = middle - 1;
  18. }
  19. }
  20. return strs[0].Substring(0, (low + high) / 2);
  21. }
  22. private static bool IsCommonPrefix(IReadOnlyList<string> strs, int len)
  23. {
  24. var str1Prefix = strs[0].Substring(0, len);
  25. for (var i = 1; i < strs.Count; i++)
  26. {
  27. if (!strs[i].StartsWith(str1Prefix)) return false;
  28. }
  29. return true;
  30. }