数据位置变换

77 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 13 天,点击查看活动详情

Day41 2023/02/16

难度:简单

题目

image.png

示例

输入:arr = {0, 1, 2, 3, 4};  p=3
输出:arr = {3, 4, 0, 1, 2}

思路


要尽可能的高效的时间和空间复杂度,所以这里最好使用逆序的方式来解题,我们可以先将数组原地逆序,再将前n-p个元素逆序,最后在将后p个元素逆序即可。 例如:arr = {0, 1, 2, 3, 4}; p =3
具体步骤:

  1. 数组原地逆序得到:arr = {4, 3, 2, 1, 0}
  2. 前2个元素逆序的:arr = {3, 4, 2, 1, 0}
  3. 最后三个元素逆序: arr = {3, 4, 0, 1, 2}

关键点


  • 因为reverse方法中传入的left,right是数组下标,所以要在数组长度n(位序)的基础上减1

算法实现


c++代码实现- 多次逆序

#include <bits/types/struct_tm.h>
#include <iostream>
#include <vector>
using namespace std;

//将数组[left, right]范围内的元素逆序
void reverse(vector<int> &arr, int left, int right) {
  int tmp; // 中间变量
  while (left < right) {
    tmp = arr[left];
    arr[left++] = arr[right];
    arr[right--] = tmp;
    // left++;
    // right--;
  }
}

// 把数组元素向左移动p个位置
int ArrayToShiftLeft(vector<int> &arr, int p) {
  int n = arr.size();
  if (p <= 0 || p >= n || n <= 1)
    return 0; //非法情况
  reverse(arr, 0, n - 1); //数组整体逆转
  reverse(arr, 0, n - p - 1); //前n-p个元素逆转
  reverse(arr, n - p, n - 1); // 后p个元素逆转
  return 1;
}

int main() {
  //测试以下
  vector<int> arr = {0, 1, 2, 3, 4};
  if (ArrayToShiftLeft(arr, 3)) { //防止非法输入
    //便利打印数组
    for (auto it : arr) {
      cout << "向左平移3为后的数组:" << it;
    }
    return 0;
  }
}

  • 时间复杂度 O(n)O(n) --- 遍历了数组接近2次,其中n为数组长度
  • 空间复杂度 O(1)O(1) --- 没有额外的辅助空间

总结

  • 这题在不考虑最好时间和空间复杂度的情况下,还可以使用辅助数组的方式,快速的解题。