左右移位字符串

本文探讨如何设计一个算法,在O(N)的时间复杂度内,仅使用两个额外变量,将一个包含N个元素的数组进行K位的循环右移操作。这种算法对于处理大规模数据时的效率至关重要。

问题:设计一个算法,把一个含有N个元素的数组循环右移K位,要求时间复杂度为O(N),且只允许使用两个附加变量。

方法1.思路:移位可以看成是字符串的翻转。
(1)将一个字符串abcdef分成两部分:X:abc, Y:def
(2)X/Y翻转:X->X^T,即abc->cba;Y->Y^T,即def->fed。得到cbafed。
(3)整个翻转:(X^TY^T)^T=YX,得到defabc。

解答:右移字符串
#include <stdio.h>
Reverse(char* arr,int b,int e){
    for(;b<e;b++,e--){
        int temp=arr[e];
        arr[e]=arr[b];
        arr[b]=temp;
        printf("%d: %s\n",b,arr);
    }
}

RightShift(char* arr,int N,int K){
    K%=N;  //因为有可能会出现K>N,这种情况下右移K-N次与右移K次的效果是相同的
    Reverse(arr,0,N-K-1);  //如果是左移,就写成Reverse(arr,0,K-1);
    Reverse(arr,N-K,N-1);  //Reverse(arr,K,N-1);
    Reverse(arr,0,N-1);
}

int main(){
    int N=0,K=0;
    char s[100];
//    memset(s,'0',sizeof(char)*100);
    scanf("%s%d",s,&K);
    N = strlen(s);
    RightShift(s,N,K);
    printf("%s\n",s);
    return 0;
}

方法2.还有一种方法,就是
1.将要移位的字符串存放在另外的数组p中;
2.将目的字符数组a中的字符进行移位;
3.将数组p中字符赋给数组a。
实现代码如下:
/*
 *Author:cbjust 
 *Date:2013-01-10 
 *
 */
#include <stdio.h>
#include <string.h>
//左移
void leftShift(char a[],int N,int K){
    int i;
    char p[1001];
    memset(p,'0',sizeof(p));
    //将数组a中要移位的字符串存放在数组p中
    for(i=0;i<K;i++){
      p[i] = a[i];
    }
    //将数组a中元素前移K个位置
    for(i=0;i<N-K;i++){
     a[i] = a[i+K];
    }
    //将数组p中元素赋值给数组a
    for(i=N-K;i<N;i++){
     a[i]=p[i-N+K];
    }
}

//右移
void rightShift(char a[],int N,int K){
    int i;
    char p[1001];
    memset(p,'0',sizeof(p));
    //将数组a中要移位的字符串存放在数组p中
    for(i=0;i<K;i++){
      p[i] = a[i+N-K];
    }
    //将数组a中元素后移K个位置
    for(i=0;i<N-K;i++){
     a[N-1-i] = a[N-1-i-K];
    }
    //将数组p中元素赋值给数组a
    for(i=0;i<K;i++){
     a[i]=p[i];
    }
}

int main(){
    char a[1001];
    int K,N;
    scanf("%s%d",a,&K);
    N = strlen(a);
//    leftShift(a,N,K);
//    printf("%s\n",a);
    rightShift(a,N,K);
    printf("%s\n",a);
    return 0;
}

方法2相比方法1,只是增加了数组p的开销~时间复杂度依然为O(n)

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值