最少操作次数(英雄会)

来源:互联网 发布:电脑淘宝店铺直播 编辑:程序博客网 时间:2024/05/17 23:50

作者博客链接

题目详情:

给定两个字符串,仅由小写字母组成,它们包含了相同字符。

求把第一个字符串变成第二个字符串的最小操作次数,且每次操作只能对第一个字符串中的某个字符移动到此字符串中的开头。

例如给定两个字符串“abcd" "bcad" ,输出:2,因为需要操作2次才能把"abcd"变成“bcad" ,方法是:abcd->cabd->bcad。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------

由于算法基础薄弱,题做出来了,却不知道自己用的是什么算法,等后面有时间了一定得好好补下。

我的做法是:如果能找到 不移动 " 不必要移动的字符" 并且 "必须要移动的字符“  只移动一次的的方法,那么这种方法的操作次数必然是最少的。

其中不必要移动字符是指 通过移动其他的字符而能使自己达到目的字符串中的位置,而必须要移动的字符恰恰相反;


现在需要做的是找出这两种字符,然后看能否找到"必须要移动的字符“  只移动一次的方法;


看下面的例子,由上面的字符串 A 转换为下面的字符串 B :


根据结果B中的字符位置的限定,我们来找出A中哪些字符是不必要移动,而另外一些无论如何都是需要被移走的,显然x、y、z是没必要移动(比如y可以通过移走e、f、g达到B中的正确位置),而g,f,e,d,c,b,a这7个字符是必须要移走的(因为如果f不被移走的话,那么z不可能成为最后一个字符,所以f是必须要移走的)。同时发现不必要移动的字符是目的字符串B中某个末尾子串,并且这个子串中的字符在A中的先后顺序与B中的顺序一致。

然后需要考虑的是有没有上述理想的移动方法呢?答案是有的,如下:

按B中除去末尾不必要移动的字符的子串的逆序来移动A中必要移动的元素,正好可以将A转换为B。

可以认为移动分为两步,删除所有必须移动的元素,再按合理顺序插入这些字符,即可以认为是将这些必要移动的字符先放在另外的串C,然后将这些字符按合理的顺序插入到xyz前面。自己可以动手画下上面的例子,依次移动g,f,e,d,c,b,a到开头即能将A转换为B。

由于题目只要求求最少的操作次数,那么我们只需统计需要被移走的字符个数即可,代码如下:

#include <stdio.h>  #include <iostream>  #include <string>  using namespace std;  class Test {  public:      static int getNumber (string   a,string   b){          int i=a.size()-1,j=i,cnt=0;        for(;i>=0;i--){            if(a[i]!=b[j]) cnt++;            else   j--;        }        return cnt;      }  };  //start 提示:自动阅卷起始唯一标识,请勿删除或增加。  int main()  {         cout<<Test::getNumber("abxcdyezfg", "abcdefgxyz")<<endl;     }   //end //提示:自动阅卷结束唯一标识,请勿删除或增加


0 0