这是在参加小米科技时遇到的一个题,当时去晚了,做题时也没仔细想。反正是悲剧了,现在把这个题的贴出来供自己反省。
题目:有两个字符串,用户可以通过删除、插入字符等操作使两个字符串变成相同。要求求出最小操作次数。
例:str1="xiaomi", str2="miliao" 输出最小操作次数为5
分析:
我们从第一个字符开始,假设*str1=*str2,也就是说比较的字符串两个字符相等,那么这里不需要进行操作,接下来求 str1+1和str2+1的最小操作次数。
假设 *str1!=*str2 那么这里肯定要执行一个操作了,具体操作情况可以是以下情况
删除*str1这个字符,继续求 str1+1和str2的最小操作次数
删除*str2这个字符,继续求str1和str2+1的最小操作次数
同时删除*str1和*str2这两个字符,继续求str1+1和str2+1的最小操作次数
通过这样分析可以用递归的方法进行求解,以下是代码:
int threemin(int a,int b,int c)//求三个数中的最小数
{
return a<(b<c?b:c)?a:(b<c?b:c);
}
int minchang(char *str1,char *str2)
{
if(*str1=='\0')//如果字符串1到末尾了,那么改变次数肯定为当前字符串2的长度
return strlen(str2);
if(*str2=='\0')//如果字符串2到末尾了,那么改变次数肯定为当前字符串1的长度
return strlen(str1);
if(*str1==*str2)
{
return minchang(str1+1,str2+1);
}
else
{
return 1+threemin(minchang(str1+1,str2),minchang(str1,str2+1),minchang(str1+1,str2+1));
}
}
当然此题也可以用动态规划方法进行求解,具体分析就不详细说明了,动态规划还是有点儿复杂的。这里只给出状态方程。
如下:
f[i][j]=f[i-1][j-1] if(str1[i]==str2[j]);
f[i][j]=1+min(f[i-1][j],f[i][j-1],f[i-1][j-1]) if(str1[i]!=str2[j]);
这下面是代码:
int dpchang(char *str1,char *str2)
{
int result[100][100];//用来保存每个阶段的状态
int i,j;
for(i=0;i<strlen(str1);i++)//当字符串2长度为0时,那么改变次数为字符串1的长度
{
result[i][0]=i;
}
for(i=0;i<strlen(str2);i++)++)//当字符串1长度为0时,那么改变次数为字符串2的长度
{
result[0][i]=i;
}
for(i=1;i<=strlen(str1);i++)
{
for(j=1;j<=strlen(str2);j++)
{
if(str1[i-1]==str2[j-1])
{
result[i][j]=result[i-1][j-1];
}
else
{
result[i][j]=1+threemin(result[i-1][j],result[i][j-1],result[i-1][j-1]);
}
}
}
return result[i-1][j-1];
}