最少操作次数

之余看到pongo网上有这么一题,便想了一下,其实比我想象的要简单。不是学生,没有在pongo网上测试

题目:给定两个字符串,仅由小写字母组成,它们包含了相同字符。 求把第一个字符串变成第二个字符串的最小操作次数,且每次操作只能对第一个字符串中的某个字符移动到此字符串中的开头。 例如给定两个字符串“abcd" "bcad" ,输出:2,因为需要操作2次才能把"abcd"变成“bcad" ,方法是:abcd->cabd->bcad。


最开始时看到这题想可能要用到递归吧,其实这题可以巧解。

对于str1 = "abcd",str2 =“bcad”这个测试用例讲解一下

strlen(str1) = strlen(str2) = 4

其实需要先理解对于任意两个字符串str1, str2,操作次数最多需要strlen(str1) - 1(这个应该很简单看出来),既然这样我们先构造一个需要最多操作次数两字符串。举几个例子,观察一下

str1 = “abdc”, str2 = "abcd"

str1 = “badc”, str2 = "abcd"

str1 = “bdca”, str2 = "abcd"

str1 = “bdac”, str2 = "abcd"

......

这些都是需要3次操作的。它们有什么共同的特征了(这是解题的关键),str2的最后两个字符是‘d’和‘c’

在str1中字符串只要是“***d***c***”形式,就是‘d’在‘c’前面,就需要最多操作次数。为什么了?原因是,对于此时的

str1,str2,第一次移动str1必定是移动‘c’到最前面,那么剩下的的字符(除d’和‘c’),都需要按一定顺序移动到最前面即可,所以加

起来便是1 + strlen(str1) - 2 = strlen(str1) - 1 。

那么当str2 = “abcd”时,str1中的‘c’在‘d’前面时,这种情况需要多少次了,此时操作次数是去掉str1和str2中的‘d’剩下的字符需要操作的次数。

对于题目原始的列子str1 = "abcd",str2 =“bcad"

同str1= “abc”, str2 = “bca”的操作次数相同,此时的移动次数为2(不用再解释了吧,str1中‘c’在‘a’后面)。

剩下就是写代码了,讲到这里想必大家都知道该怎么写了,我把我的代码贴出来,我是考虑到字符串中可能有重复的字符,所以从后面遍历的了


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int getNum(const char * str1, const char * str2)
{
   int len = strlen(str2);
   char * str3 = strdup(str1);
   for(int i = len - 1; i > 0; i--)
   {
	   for(int j = len - 1; j > 0; j--)
	   {
			if(str3[j] == str2[i])
			{
				str3[j] = '\0';
				break;
			}
			else if(str3[j] == str2[i-1])
			{
				free((void *)str3);
				return i;
			}
	   }
   }
   free((void *)str3);
   return 0;
}

int main()
{    
    printf("%d\n",getNum("bdac", "bdac"));
}





猜你喜欢

转载自blog.csdn.net/Yshe_xun/article/details/19326845