14.最长公共前缀
14.1 题目
编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 ""
。
示例:
示例 1:
- 输入:
strs = ["flower","flow","flight"]
- 输出:
"fl"
- 输入:
示例 2:
- 输入:
strs = ["dog","racecar","car"]
- 输出:
""
- 解释:输入不存在公共前缀。
- 输入:
提示:
1 <= strs.length <= 200
0 <= strs[i].length <= 200
strs[i]
仅由小写英文字母组成
14.2 题解
遍历每个字符串的每个字符,找到最长公共前缀
// 方法一:遍历每个字符串的每个字符,找到最长公共前缀
static string LongestCommonPrefix1(string[] strs)
{
// 如果输入的字符串数组为空或长度为0,返回空字符串
if (strs == null || strs.Length == 0)
{
return "";
}
// 获取字符串数组中最短字符串的长度
int minStringLength = GetMinStringLength(strs);
// 使用 StringBuilder 构建最终的最长公共前缀
StringBuilder stringBuilder = new StringBuilder();
// 遍历每个字符位置,直到最短字符串的长度
for (int i = 0; i < minStringLength; i++)
{
// 如果在当前字符位置所有字符串的字符相同,则将该字符添加到结果中
if (CompareStringsIndexCharIsEqual(strs, i))
{
stringBuilder.Append(strs[0][i]);
}
// 如果在当前字符位置有不相同的字符,停止遍历
else
{
break;
}
}
// 返回构建的最长公共前缀
return stringBuilder.ToString();
}
// 获取字符串数组中的最小字符串长度
static int GetMinStringLength(string[] strs)
{
// 如果数组为空或长度为0,抛出异常
if (strs == null || strs.Length == 0)
{
return 0;
}
// 初始化最小长度为第一个字符串的长度
int minLength = strs[0].Length;
// 遍历数组,找出最短字符串的长度
foreach (string str in strs)
{
int currentLength = str.Length;
// 如果当前字符串长度小于最小长度,更新最小长度
if (currentLength < minLength)
{
minLength = currentLength;
}
}
// 返回最小长度
return minLength;
}
// 比较所有字符串在指定位置的字符是否相同
static bool CompareStringsIndexCharIsEqual(string[] strs, int i)
{
// 获取第一个字符串在指定位置的字符
char charValue = strs[0][i];
// 遍历其余字符串,检查字符是否相同
for (int j = 1; j < strs.Length; j++)
{
// 如果当前字符位置超过当前字符串的长度,或字符不相同,返回 false
if (i >= strs[j].Length || strs[j][i] != charValue)
{
return false;
}
}
// 如果所有字符串在指定位置的字符都相同,返回 true
return true;
}
两两字符逐个比较 逐渐缩小并更新前缀长度
// 方法二:两两字符逐个比较 逐渐缩小并更新前缀长度
static string LongestCommonPrefix2(string[] strs)
{
// 如果数组为空,可以根据实际需求返回一个默认值或抛出异常
if (strs == null || strs.Length == 0)
{
return "";
}
// 将第一个字符串设置为初始比较字符串
string compareStr = strs[0];
// 将初始比较字符串设置为结果字符串
string resultStr = compareStr;
// 遍历字符串数组,从第二个字符串开始比较
for (int arrayIndex = 1; arrayIndex < strs.Length; arrayIndex++)
{
// 每次两两比较前将结果字符串重置为空字符串
resultStr = "";
// 遍历当前字符串和比较字符串的每个字符
for (int stringIndex = 0;
stringIndex < strs[arrayIndex].Length && stringIndex < compareStr.Length;
stringIndex++)
{
// 如果当前字符和比较字符串的对应字符相同,将该字符添加到结果字符串
if (strs[arrayIndex][stringIndex] == compareStr[stringIndex])
{
resultStr += compareStr[stringIndex];
}
else
{
// 如果遇到不同的字符,结束当前字符位置的比较
break;
}
}
// 将比较字符串更新为当前比较的结果字符串
compareStr = resultStr;
// 如果比较字符串为空,表示没有公共前缀,结束循环
if (compareStr == "")
{
break;
}
}
// 返回最终的结果字符串,即最长的公共前缀
return resultStr;
}
分治分割字符串数组两两比较后递归返回前缀
// 方法三:分治分割字符串数组两两比较后递归返回前缀
static string LongestCommonPrefix3(string[] strs)
{
// 如果数组为空,可以根据实际需求返回一个默认值或抛出异常
if (strs == null || strs.Length == 0)
{
return "";
}
// 调用递归方法,传入字符串数组、起始索引和结束索引
return SplitStrs(strs, 0, strs.Length - 1);
}
// 分割字符串数组递归方法,将字符串数组分为左右两部分,然后比较左右两部分的最长公共前缀
static string SplitStrs(string[] strs, int startIndex, int endIndex)
{
// 如果起始索引和结束索引相等,说明只有一个字符串,直接返回该字符串
if (startIndex == endIndex)
{
return strs[startIndex];
}
else
{
// 计算中间索引,用于将数组分为左右两部分
int middleIndex = (endIndex + startIndex) / 2;
// 递归调用,分别处理左右两部分的字符串数组
string leftStr = SplitStrs(strs, startIndex, middleIndex);
string rightStr = SplitStrs(strs, middleIndex + 1, endIndex);
// 调用比较方法,比较左右两部分的最长公共前缀
return CompareStr(leftStr, rightStr);
}
}
// 比较两个字符串的最长公共前缀并返回
static string CompareStr(string leftStr, string rightStr)
{
// 初始化StringBuilder用于构建公共前缀字符串
StringBuilder stringBuilder = new StringBuilder();
// 遍历两个字符串的每个字符,比较它们是否相等
// 遍历的次数为两个字符串中较短的那个的长度
for (int i = 0; i < Math.Min(leftStr.Length, rightStr.Length); i++)
{
// 如果当前字符相等,将该字符添加到StringBuilder中
if (leftStr[i] == rightStr[i])
{
stringBuilder.Append(leftStr[i]);
}
// 如果字符不相等,说明公共前缀结束,退出循环
else
{
break;
}
}
// 将StringBuilder中的字符转换为字符串并返回
return stringBuilder.ToString();
}
14.3 代码
using System;
using System.Text;
class Program
{
static void Main()
{
#region 题目
// 编写一个函数来查找字符串数组中的最长公共前缀。
// 如果不存在公共前缀,返回空字符串 ""。
// 示例 1:
// 输入:strs = ["flower","flow","flight"]
// 输出:"fl"
// 示例 2:
// 输入:strs = ["dog","racecar","car"]
// 输出:""
// 解释:输入不存在公共前缀。
// 提示:
// 1 <= strs.length <= 200
// 0 <= strs[i].length <= 200
// strs[i] 仅由小写英文字母组成
#endregion
#region 测试
// 示例 1
string[] strs1 = { "flower", "flow", "flight" };
string result11 = LongestCommonPrefix1(strs1);
Console.WriteLine($"示例1 方法1 输出:{result11}");
string result12 = LongestCommonPrefix2(strs1);
Console.WriteLine($"示例1 方法2 输出:{result12}");
string result13 = LongestCommonPrefix3(strs1);
Console.WriteLine($"示例1 方法3 输出:{result13}");
// 示例 2
string[] strs2 = { "dog", "racecar", "car" };
string result21 = LongestCommonPrefix1(strs2);
Console.WriteLine($"示例2 方法1 输出:{result21}");
string result22 = LongestCommonPrefix2(strs2);
Console.WriteLine($"示例2 方法2 输出:{result22}");
string result23 = LongestCommonPrefix3(strs2);
Console.WriteLine($"示例2 方法3 输出:{result23}");
#endregion
}
#region 答案
// 方法一:遍历每个字符串的每个字符,找到最长公共前缀
static string LongestCommonPrefix1(string[] strs)
{
// 如果输入的字符串数组为空或长度为0,返回空字符串
if (strs == null || strs.Length == 0)
{
return "";
}
// 获取字符串数组中最短字符串的长度
int minStringLength = GetMinStringLength(strs);
// 使用 StringBuilder 构建最终的最长公共前缀
StringBuilder stringBuilder = new StringBuilder();
// 遍历每个字符位置,直到最短字符串的长度
for (int i = 0; i < minStringLength; i++)
{
// 如果在当前字符位置所有字符串的字符相同,则将该字符添加到结果中
if (CompareStringsIndexCharIsEqual(strs, i))
{
stringBuilder.Append(strs[0][i]);
}
// 如果在当前字符位置有不相同的字符,停止遍历
else
{
break;
}
}
// 返回构建的最长公共前缀
return stringBuilder.ToString();
}
// 获取字符串数组中的最小字符串长度
static int GetMinStringLength(string[] strs)
{
// 如果数组为空或长度为0,抛出异常
if (strs == null || strs.Length == 0)
{
return 0;
}
// 初始化最小长度为第一个字符串的长度
int minLength = strs[0].Length;
// 遍历数组,找出最短字符串的长度
foreach (string str in strs)
{
int currentLength = str.Length;
// 如果当前字符串长度小于最小长度,更新最小长度
if (currentLength < minLength)
{
minLength = currentLength;
}
}
// 返回最小长度
return minLength;
}
// 比较所有字符串在指定位置的字符是否相同
static bool CompareStringsIndexCharIsEqual(string[] strs, int i)
{
// 获取第一个字符串在指定位置的字符
char charValue = strs[0][i];
// 遍历其余字符串,检查字符是否相同
for (int j = 1; j < strs.Length; j++)
{
// 如果当前字符位置超过当前字符串的长度,或字符不相同,返回 false
if (i >= strs[j].Length || strs[j][i] != charValue)
{
return false;
}
}
// 如果所有字符串在指定位置的字符都相同,返回 true
return true;
}
// 方法二:两两字符逐个比较 逐渐缩小并更新前缀长度
static string LongestCommonPrefix2(string[] strs)
{
// 如果数组为空,可以根据实际需求返回一个默认值或抛出异常
if (strs == null || strs.Length == 0)
{
return "";
}
// 将第一个字符串设置为初始比较字符串
string compareStr = strs[0];
// 将初始比较字符串设置为结果字符串
string resultStr = compareStr;
// 遍历字符串数组,从第二个字符串开始比较
for (int arrayIndex = 1; arrayIndex < strs.Length; arrayIndex++)
{
// 每次两两比较前将结果字符串重置为空字符串
resultStr = "";
// 遍历当前字符串和比较字符串的每个字符
for (int stringIndex = 0;
stringIndex < strs[arrayIndex].Length && stringIndex < compareStr.Length;
stringIndex++)
{
// 如果当前字符和比较字符串的对应字符相同,将该字符添加到结果字符串
if (strs[arrayIndex][stringIndex] == compareStr[stringIndex])
{
resultStr += compareStr[stringIndex];
}
else
{
// 如果遇到不同的字符,结束当前字符位置的比较
break;
}
}
// 将比较字符串更新为当前比较的结果字符串
compareStr = resultStr;
// 如果比较字符串为空,表示没有公共前缀,结束循环
if (compareStr == "")
{
break;
}
}
// 返回最终的结果字符串,即最长的公共前缀
return resultStr;
}
// 方法三:分治分割字符串数组两两比较后递归返回前缀
static string LongestCommonPrefix3(string[] strs)
{
// 如果数组为空,可以根据实际需求返回一个默认值或抛出异常
if (strs == null || strs.Length == 0)
{
return "";
}
// 调用递归方法,传入字符串数组、起始索引和结束索引
return SplitStrs(strs, 0, strs.Length - 1);
}
// 分割字符串数组递归方法,将字符串数组分为左右两部分,然后比较左右两部分的最长公共前缀
static string SplitStrs(string[] strs, int startIndex, int endIndex)
{
// 如果起始索引和结束索引相等,说明只有一个字符串,直接返回该字符串
if (startIndex == endIndex)
{
return strs[startIndex];
}
else
{
// 计算中间索引,用于将数组分为左右两部分
int middleIndex = (endIndex + startIndex) / 2;
// 递归调用,分别处理左右两部分的字符串数组
string leftStr = SplitStrs(strs, startIndex, middleIndex);
string rightStr = SplitStrs(strs, middleIndex + 1, endIndex);
// 调用比较方法,比较左右两部分的最长公共前缀
return CompareStr(leftStr, rightStr);
}
}
// 比较两个字符串的最长公共前缀并返回
static string CompareStr(string leftStr, string rightStr)
{
// 初始化StringBuilder用于构建公共前缀字符串
StringBuilder stringBuilder = new StringBuilder();
// 遍历两个字符串的每个字符,比较它们是否相等
// 遍历的次数为两个字符串中较短的那个的长度
for (int i = 0; i < Math.Min(leftStr.Length, rightStr.Length); i++)
{
// 如果当前字符相等,将该字符添加到StringBuilder中
if (leftStr[i] == rightStr[i])
{
stringBuilder.Append(leftStr[i]);
}
// 如果字符不相等,说明公共前缀结束,退出循环
else
{
break;
}
}
// 将StringBuilder中的字符转换为字符串并返回
return stringBuilder.ToString();
}
#endregion
}
14.4 运行结果
示例1 方法1 输出:fl
示例1 方法2 输出:fl
示例1 方法3 输出:fl
示例2 方法1 输出:
示例2 方法2 输出:
示例2 方法3 输出:
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com