C 将一个字符串转换为另一个字符串的最小交换次数

C 将一个字符串转换为另一个字符串的最小交换次数,c,algorithm,C,Algorithm,问题陈述: 找到将一个字符串转换为另一个相同长度的字符串(可能有或可能没有重复字符)的最小交换次数;允许任意互换 min_swaps('kamal', 'amalk') -> 3 # 1 2 3 # kamal -> lamak -> aamlk -> amalk 注意:有许多这样的问题,但似乎没有一个适用于任意掉期 初始方法: let s1 = 'kamal' let s2 = 'amalk' 假设s1是“正确的”顺序,即其

问题陈述:

找到将一个字符串转换为另一个相同长度的字符串(可能有或可能没有重复字符)的最小交换次数;允许任意互换

min_swaps('kamal', 'amalk') -> 3
#       1         2        3
# kamal -> lamak -> aamlk -> amalk
注意:有许多这样的问题,但似乎没有一个适用于任意掉期

初始方法:

let s1 = 'kamal'
let s2 = 'amalk'
假设s1是“正确的”顺序,即其元素以递增顺序映射到序列from
0->N-1

0 1 2 3 4
k a m a l
现在创建一个数组p,它是从
s2
中的字母到s1中正确索引的映射:

1 2 3 4 0
a m a l k 

P = [1,2,3,4,0]
现在我们可以使用修改的mergesort来计算
p
中的数组反转数,这将为我们提供无序元素的数量

修改的合并排序:

int main(int argc, char ** argv) {
   int array[] = { 1,2,3,4,0 };

   int array_size = sizeof(array)/sizeof(array[0]);
   int inversions = merge_sort(array, 0, array_size - 1);

   printf("Found %d inversions\n", inversions);
   return 0;
}

int merge_sort(int a[], int start, int end) {
   if ( end > start ) {
      int mid = start + (end - start) / 2;
      int x = merge_sort(a, start, mid);
      int y = merge_sort(a, mid + 1, end);
      int z = merge(a, start, mid, end);

      return x + y + z;
   }

   return 0;
}

int merge(int a[], int start, int mid, int end) {
   int l = start, r = mid + 1;
   int i = 0;
   int temp[end - start + 1];
   int splitInversionCount = 0;

   while ( l <= mid && r <= end ) {
       if ( a[l] < a[r] ) {
          temp[i++] = a[l++];
       }
       else {
         splitInversionCount += mid - l + 1;
         temp[i++] = a[r++];
       }
   }

   // copy whichever half of the array remains
   while ( l <= mid ) {
      temp[i++] = a[l++];
   }

   while ( r <= end ) {
      temp[i++] = a[r++];
   }

   // copy temp back into a
   int k;
   for(k = 0; k < i; k++) {
      a[k + start] = temp[k];
   }

   return splitInversionCount;
}
int main(int argc,char**argv){
int数组[]={1,2,3,4,0};
int array_size=sizeof(array)/sizeof(array[0]);
整数反转=合并排序(数组,0,数组大小-1);
printf(“发现%d个反转\n”,反转);
返回0;
}
整数合并\排序(整数a[],整数开始,整数结束){
如果(结束>开始){
int mid=start+(end-start)/2;
int x=合并和排序(a、开始、中间);
int y=合并\排序(a,中间+1,结束);
int z=合并(a、开始、中间、结束);
返回x+y+z;
}
返回0;
}
整数合并(整数a[],整数开始,整数中间,整数结束){
int l=开始,r=中间+1;
int i=0;
内部温度[结束-开始+1];
int splitInversionCount=0;

虽然(l我还没有一个完整的解决方案,但我认为陈述这一点对帮助他人是有用的


让我们假设字符串的大小为
N
。让我们调用
k
已经处于其位置的字符数。最初
k是否有时间限制?输入大小?这个问题看起来好像是关于任意交换:您正在寻找和。这个问题大致相当于Rubik的立方体解决方案关于算法。@HunterMcMillen我刚刚编辑了我的评论,因为我意识到第二个答案实际上是一个很好的分析。另外,在任何情况下,如果有人有更好的解决方案,应该将其添加到Subbasis Das的解决方案中。很抱歉,我忘记了排序是不确定的:)如何证明你的贪婪?大小超过2(N个成员)的圆可以保证什么不会在N交换而不是N-1中解决?我不是在提出贪婪算法,我只是在陈述一些关于问题的想法,试图找到解决方案。实际上,我开始怀疑贪婪的存在。我正在阅读Sergey L.发布的链接,但我的数学不是很好。