程序员面试100题之一:字符数组左移

题目:一个字符数组含有N个字符,要求设计一个算法可以返回字符左移K位后的字符数组,要求时间复杂度为O(N),空间复杂度只允许使用两个附加变量。比如字符串abcdefg左移3位得到defgabc。

解法一:最先想到的肯定是暴力模拟。也就是说每次移动头字符到字符串末尾,移动K次。比如abcdefg -> bcdefga -> cdefgab -> defgabc。

在正式写代码之前,我们需要对K的范围以及正负性进行讨论,比如对于N为7的情况,K可能为-16,也可能为+16,因为字符串左移N位还是原来的字符串。所以我们可以得到如下结论,如果K为负数,则我们只需要左移K%N+N位,当N、K分别为7、-16时,只需左移5位。如果K为非负数,则我们只需要左移K%N位。

解法1的代码如下:

void left_move(char *arr,int K,int N) {
    if(K<0)
        K=K%N+N;
    else
        K=K%N;
    while(K--) {
        char head=arr[0];
        for(int i=1; i<N; i++) {
            arr[i-1]=arr[i];
        }
        arr[N-1]=head;
    }

}

但是解法1的时间复杂度为O(N^2),使用了两个附加变量,分别为i和head。

解法二:这种解法比较巧妙,跟矩阵的转置非常相像。将字符串左移K位,则可以把字符串左侧K位记为X,右侧剩余位记为Y。我们定义一种操作T可以将字符串逆序,也就是说把abcd变为dcba。由定义可知(XT)T=X。我们题目要求将XY转变为YX,而需要注意的一点是,X和Y中的字符顺序并没有发生改变!因此我们仔细思考一下,是否可以利用操作T来达到字符串左移的目的呢?答案是可以的。(XTYT)T=(YT)T(XT)T=YX。因此我们可以首先逆序X,然后逆序Y,最后再将XTYT逆序,即可得到YX。代码如下:

void reverse(char *arr, int b, int e) {
    for(; b<e; b++,e--) { //注意这种写法,要将abcde变为edcba,只需要从两头不断逼近就行,逼近之前进行交换。
        char t = arr[b];
        arr[b] = arr[e];
        arr[e] = t;
    }
}
void left_move(char *arr, int K, int N) {
    if(K<0)
        K = K%N+N;
    else
        K = K%N;
    reverse(arr, 0, K-1);
    reverse(arr, K, N-1);
    reverse(arr, 0, N-1);

}

上面算法的时间复杂度为O(N),计算方式为K/2+N-K/2+N/2=N,其中K/2为逆序X的时间复杂度,N-K/2为逆序Y的时间复杂度。附加变量为b和e。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值