数组:左旋转|破解编码访谈黑客排名 - (由于超时而终止)

时间:2017-04-12 03:34:15

标签: c++ arrays algorithm

我是一名非常普通的程序员,并且正在尝试通过Hacker-rank网站提供的不同挑战来提高我的技能。我试图解决这个数组左旋转算法,并能够通过除最后一个数字大文件之外的每个测试用例。经过一些研究后我发现由于超时错误导致的终止是由于算法不够有效,我认为黑客等级对每个测试用例都有某种时间限制或速度测试,而我的算法速度不够快。下面我提供了问题和我实现的代码,如果有人可以帮我减少优化这个算法(EXPLAIN!)为什么我的算法速度慢我真的很感激它。很多爱CK


解释:
在大小为n的阵列上的左旋转操作将每个阵列的元素1单元向左移位。例如,如果在数组[1,2,3,4,5]上执行了2次左旋转,则数组将变为[3,4,5,1,2]。

给定n个整数和数字d的数组,在数组上执行左旋转。然后将更新的数组打印为一行以空格分隔的整数。


输入格式

第一行包含两个以空格分隔的整数,表示n(整数)和d(必须执行的左旋转数)的相应值。 第二行包含n个以空格分隔的整数,用于描述数组初始状态的各个元素。
约束

1< = n< = 10 ^ 5
1< = d< = n
1< = ai< = 10 ^ 6

输出格式
在执行左旋转后,打印一行n个以空格分隔的整数,表示数组的最终状态。

示例输入

5 4
1 2 3 4 5


样品输出

5 1 2 3 4

当我们执行d = 4左旋转时,阵列经历以下变化序列:
[1,2,3,4,5] - > [2,3,4,5,1] - > [3,4,5,1,2] - > [4,5,1,2,3] - > [5,1,2,3,4]

因此,我们将数组的最终状态打印为单行空格分隔值,即5 1 2 3 4.


代码:

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <string>
#include <bitset>
#include <cstdio>
#include <limits>
#include <vector>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <fstream>
#include <numeric>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <unordered_map>

using namespace std;

vector<int> array_left_rotation(vector<int> a, int n, int k) {
    int tmp=0,x=0;
    while(x < k){
        tmp = a[0];
        for(int i=0; i < n; i++){
            a[i]=a[i+1];
            if(i+1 == n) a[i]= tmp;
        }
        x++;
    }
    return a;
}

int main(){
    int n;
    int k;
    cin >> n >> k;
    vector<int> a(n);
    for(int a_i = 0;a_i < n;a_i++){
        cin >> a[a_i];
    }
    vector<int> output = array_left_rotation(a, n, k);
    for(int i = 0; i < n;i++)
        cout << output[i] << " ";
    cout << endl;
    return 0;
}

2 个答案:

答案 0 :(得分:4)

这是我更高效的算法 -

逆转算法

要在位置k处旋转数组(将k移动到n元素到左侧),我们可以这样做:

  1. 反向子阵列arr[0 .... k - 1],即O(k)
  2. 反向子阵列arr[k .... n - 1],即O(n - k)
  3. 最后,反向子阵列arr[0 .... n],即O(n)
  4. 整体复杂度为O(n),空间复杂度不变。

    你必须照顾k >= nk < 0等角落案件。

    void leftRotate(vector<int>& arr, int k)
    {
        int n = (int)arr.size();
        if(k >= n) k = k % n;
        reverse(arr.begin(), arr.begin() + k);
        reverse(arr.begin() + k, arr.end());
        reverse(arr.begin(), arr.end());
    }
    

    希望它有所帮助!

答案 1 :(得分:1)

对我而言,任务听起来似乎根本不需要执行旋转。您只需要打印结果,完全跳过轮换!

基本上您只需要执行以下操作:

  1. 阅读nd
  2. 创建一个向量并将第一个d数字读入其中
  3. 读入其余数字并立即输出
  4. 输出向量中的数字
  5. 就是这样,我不认为你可以比完全省略工作更有效率; - )