编程之美 - 数组循环移位

原创 2016年06月01日 23:03:47
问题描述:
将一个数组向右循环移位 k 位,要求只使用两个参数,时间复杂度为 O(N)。

思路 1:
采用蛙跳的方式,用当前的元素 i,替换第i+k个元素,这样逐一替换N次后,数组被移位完成。
当然这时要区分能两种情况,N整除k 和 N不能整除k,这时跳的方式是不一样的。
时间复杂度 O(N)

假设 N = 7 k = 3 (N不能整除k),  假设 N = 9 k = 3 (N能整除k)

pic_1
思路 2:
例如 1 2 3 4 5 6 7,移位3位后会变成  5 6 7 1 2 3 4。 

找规律, 发现 5 6 7是会被移动的,所以书中的想法是把数组分成两个部分 一部分是 0 到 N-k-1,另一部分是 N - k 到 N。

第一次变化: 将数组中 0 到  N-k-1进行翻转
第二次变化: 将数组中 N - k 到 N进行翻转
第三次变化: 将整个数组进行翻转

1 2 3 4 5 6 7   == 第一次变化 ==>  4 3 2 15 6 7   == 第二次变化 ==>  4 3 2 1 7 6 5  == 第三次变化  ==>  5 6 7 1 2 3 4

要遍历两次数组 2xN,时间复杂度 O(N)

#include <iostream>

using namespace std;

void printarr(int arr[], int len)
{
    int i = 0;
    for (i = 0 ; i < len; i++)
    {
        cout << arr[i] << "  ";
    }
    cout << endl << endl;
}

/////////////////////////////////////////////////////
//  algorithm one
/////////////////////////////////////////////////////
void swap1(int arr[], int len, int k)
{
    int i = 0, cnt=0;

    cout << "Algorithm 1: "<< "shift: " << k << endl;
    k %= len;

    if (len%k == 0)
    {
        cnt = 0;
        while(cnt < k)
        {
            for (i = cnt+k; i < len; i=i+k)
            {
                arr[cnt] = arr[cnt] ^ arr[i];
                arr[i] = arr[i] ^ arr[cnt];
                arr[cnt] = arr[cnt] ^ arr[i];
            }
            cnt++;
        }
    }
    else
    {
        while(cnt < len-1)
        {
            i = i + k;
            if (i < len)
            {
                cout << arr[0] << "<==>" << arr[i] << endl;
                arr[0] = arr[0] ^ arr[i];
                arr[i] = arr[i] ^ arr[0];
                arr[0] = arr[0] ^ arr[i];
            }
            else
            {
                i = i%len;
                cout << arr[0] << "<==>" << arr[i] << endl;
                arr[0] = arr[0] ^ arr[i];
                arr[i] = arr[i] ^ arr[0];
                arr[0] = arr[0] ^ arr[i];
            }
            cnt++;
        }
    }
    printarr(arr, len);
}

/////////////////////////////////////////////////////
//  algorithm two
/////////////////////////////////////////////////////
void reserve(int arr[], int l, int r)
{
    int tmp = 0;
    for(; l < r; l++, r--)
    {
        tmp = arr[l];
        arr[l] = arr[r];
        arr[r] = tmp;
    }
}
void swap2(int arr[], int len, int k)
{
    cout << "Algorithm 2: "<< "shift: " << k << endl;

    k %= len;
    reserve(arr, 0, len-k-1);
    reserve(arr, len-k, len-1);
    reserve(arr, 0, len-1);

    printarr(arr, len);
}

int main()
{
    int len = 0, k = 0;
    int test[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    len = sizeof(test)/sizeof(test[0]);

    int *parr = new int[len];

    k = 4;
    memcpy(parr, test, len*sizeof(int));
    cout << "----------------------------------" << endl;
    printarr(parr, len);

    swap1(parr, len, k);
    memcpy(parr, test, len*sizeof(int));
    swap2(parr, len, k);

    k = 2;
    memcpy(parr, test, len*sizeof(int));
    cout << "----------------------------------" << endl;
    printarr(parr, len);
    swap1(parr, len, k);
    memcpy(parr, test, len*sizeof(int));
    swap2(parr, len, k);

    k = 1;
    memcpy(parr, test, len*sizeof(int));
    cout << "----------------------------------" << endl;
    printarr(parr, len);
    swap1(parr, len, k);
    memcpy(parr, test, len*sizeof(int));
    swap2(parr, len, k);

    k = 3;
    memcpy(parr, test, len*sizeof(int));
    cout << "----------------------------------" << endl;
    printarr(parr, len);
    swap1(parr, len, k);
    memcpy(parr, test, len*sizeof(int));
    swap2(parr, len, k);
    delete[] parr;
    cin >> len;
    return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

编程之美6:数组循环移位

楼主又来~(≧▽≦)/~啦啦啦,科研,就是要这么一鼓作气。额,其实楼主的老本行是推公式啊,做这些算法题,其实是楼主在偷懒。额,话不多说了,快请出我们今天的主角吧!还是关于数组的-数组循环移位。下面我们...

编程之美2.17 数组循环移位

问题描述把一个含有N个元素的数组循环右移K位,如K=4的时候abcd1234->1234abcd。一般考虑K>0的情况,即右移;同时K=N的话可以通过K%=N得到一样的结果 解法思路详见代码注释/**...

编程之美:第二章 数字之魅 2.17数组循环移位

/* 数组循环移位: 设计一个算法,把一个含有N个元素的数组循环右移K位,要求时间复杂度为O(N),且只允许使用两个附加变量。 此题已经做过,但本题的收获是注意循环移位,即,当K大于N时,注意到移N位...

[编程之美] PSet2.17 数组循环移位

设计一个算法,把一个含有N个元素的数组循环右移K位,要求时间复杂度为O(N),且只允许使用两个附件变量。比如abcd1234右移4位后为:1234abcd。...

编程之美---数组循环移位

设计一个算法,把一个含有N个元素的数组循环右移K位,要求时间复杂度为 O(N), 且只允许使用两个附加变量。 解法一:简单的办法是,每次将数组中的元素右移一位,循环K次。abcd1234 -> 4ab...

《编程之美》学习笔记——2.17数组循环移位

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

旋转字符串;编程珠玑第二章;rotate a one-dimensional vector;循环移位数组;编程之美

一:问题描述: 编程珠玑第二章的第二个问题是字符串(或者理解为向量)旋转问题,具体描述如下: rotate a one-dimensional vector of n elements left...

每天学习一点编程(14)(数组/字符串循环移位)

设计一个算法,把一个含有N个元素的数组循环右移K位,要求时间复杂度为O(N),且只允许使用两个附加变量。 不合题意的解法如下: 我们先试验简单的办法,可以每次将数组中的元素右移一位,循环K次。...

程序员面试100题之十一:数组循环移位

设计一个算法,把一个含有N个元素的数组循环右移K位,要求时间复杂度为O(N),且只允许使用两个附加变量。      不合题意的解法如下:      我们先试验简单的办法,可以每次将数组中的元素右移...

左旋转字符串(数组循环移位)

题目描述: 定义字符串的左旋转操作:把字符串前面的若干个字符移动到字符串的尾部。 如把字符串abcdef左旋转2位得到字符串cdefab。 请实现字符串左旋转的函数,要求对长度为n的字符串操作的...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:编程之美 - 数组循环移位
举报原因:
原因补充:

(最多只允许输入30个字)