这是在参加小米科技时遇到的一个题,当时去晚了,做题时也没仔细想。反正是悲剧了,现在把这个题的贴出来供自己反省。

题目:有两个字符串,用户可以通过删除、插入字符等操作使两个字符串变成相同。要求求出最小操作次数。

例: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];
}