字符串旋转与移位

来源:互联网 发布:计算机技术专硕 网络 编辑:程序博客网 时间:2024/05/16 23:39

 

     在好多字符串处理中,旋转与移位是很常见到的,在大规模的数据处理中设计高效的算法是必须的

示例:

把字符串abcdefgh循环左移3位,变为defghabc

输入字符串str与移位数m,输出结果

1、看到题之后一般的想法就是一位一位的移动

  • abcdefgh
  • bcdefgha
  • cdefghab
  • defghabc

      实现代码如下

 

void movebit(string &str,int num){int len=str.length();for (int i=0;i<num;++i){char temp=str[0];for (int j=1;j<len;++j){str[j-1]=str[j];}str[--j]=temp;}}


        这样算法的时间复杂度为O(m*n)

2、在第一种方法中是一个字符一个字符的向后移动,这样后边的字符也得跟着移动m次,那么能不能一次就向后移动m个字符呢,答案是肯定的,这就是第二种方法,一次向后移动m个字符

  • abcdefgh
  • defabcgh
  • defghcab
  • defghabc

示例代码如下:

void movechar(string & ch,int num){int len=ch.length();if (len<=0||num>=len){return;}int first=0;                    //第一次交换的字符位置int middle=num;int second=middle;              //与之交换的位置while (1){char temp=ch[first];ch[first]=ch[second];ch[second]=temp;first++;second++;if (first==middle){if (second>=len)        //交换完成,退出{return;}else                    //进行下一轮交换{middle=second;}}else if (second>=len)       //前半部分长,后半部分短,如defg abc h{second=middle;}}}


3、接下来这种方法是利用字符串的翻转

     先把字符串按移位的个数分为两部分,abc 与 defgh

     思想是先对第一部分反转交换,第一个与最后一个交换,依次类推,交换之后分别为 cba 与 hgfed

     最后对所得的字符串cbahgfed整体翻转,结果为defghabc,即我们要得到的结果

    实现代码如下:

    字符串翻转函数:

void revote(char *ch,int start,int end){char temp;while (start<end){temp=ch[start];ch[start]=ch[end];ch[end]=temp;++start;--end;}}
void translate(char * ch,int num){ if (ch==NULL||num<=0||num>=strlen(ch)) {  return; } revote(ch,0,num-1);                   //对前一部分翻转 revote(ch,num,strlen(ch)-1);          //对后一部分翻转 revote(ch,0,strlen(ch)-1);            //整体翻转}


4、最后一种方法是用最大公约数法,移动字符

     利用公式  index=(i+m*j)%n

    设m与n的最大公约数为k,则i为从0到k-1循环k次

    如在示例中m=3,n=7,最大公约数为1,所以i只为0

    下标计算结果为:0,3,6,2,5,1,4,0

     依照这样的顺序进行移位,最后得到最终的结果

   实现代码如下:

//用辗转相除法求最大公约数函数int GCD(int m,int n){if (n==0){return m;}else {return GCD(n,m%n);}}
void Rotate(string &str,int num){int len=str.length();int commonNum=GCD(len,num);                    //求出的最大公约数int time=len/commonNum;                        //计算内循环次数for (int i=0;i<commonNum;++i){char temp=str[i];for (int j=0;j<time-1;++j){str[(i+j*num)%len]=str[(i+(j+1)*num)%len];  //下标计算 (i+j*num)%len}str[(i+j*num)%len]=temp;}}

小结:总共介绍了4中字符串旋转的方法,其中第四种字符移动次数最少

当然,如果是循环右移m位,可以转变为循环左移n-m位
	
				
		
原创粉丝点击