旋转数组

1. 问题描述

  从右侧旋转一个n个元素的数组,旋转k位。例如: n=7,k=3 arr=[1,2,3,4,5,6,7] 旋转成为 arr=[5,6,7,1,2,3,4]


2. 方法与思路

  其实这个问题类似于字符串逆置问题中的句子逆置。比如“hello world”逆置成”world hello”。解决这种问题的O(1)空间复杂的算法通常是先逆置单词,后逆置整个句子。
  针对这个问题,思路一样。第一次逆置前半段[4,3,2,1,5,6,7],第二次逆置后半段[4,3,2,1,7,6,5],最后整个逆置[5,6,7,1,2,3,4]。


注意:如果k大于数组的长度,则需要 k=k%arr.len ,因为数组在旋转一圈后还是等于原来的数组。


  
  主要过程如下:

  I. for i:0arr.sizek1
      逆置
  II. for i:(arr.sizek)arr.size1
      逆置
  III. for i:0arr.size1
      逆置

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        int i,j;

        k = k%nums.size();

        for(i = 0,j = nums.size() - k -1; i < j; i ++,j--)
            swap(nums[i],nums[j]);
        for(i = nums.size()-k,j = nums.size()-1; i < j; i++,j--)
            swap(nums[i],nums[j]);

        for(i = 0,j = nums.size()-1; i < j; i++,j--)
            swap(nums[i],nums[j]);
    }
};
### C语言实现旋转数组的功能 在C语言中,可以通过多种方式实现数组旋转操作。以下提供两种常见的方法:一种基于反转法[^1],另一种基于逐位右移法[^2]。 --- #### 方法一:反转法 该方法的核心思想是通过对数组的部分区域进行三次反转来达到旋转的效果。具体骤如下: 1. 反转数组的前 `numSize - k` 个元素。 2. 反转数组的后 `k` 个元素。 3. 最后再整体反转整个数组。 以下是具体的代码实现: ```c #include <stdio.h> // 定义反转函数 void reverse(int *a, int left, int right) { while (left < right) { // 当左指针小于右指针时继续交换 int tmp = a[left]; a[left] = a[right]; a[right] = tmp; left++; right--; } } int main() { int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; int numSize = sizeof(arr) / sizeof(arr[0]); // 计算数组长度 int k; printf("请输入需要旋转的次数:"); scanf("%d", &k); // 用户输入旋转次数 // 确保k不超过数组长度 k %= numSize; // 第一:反转前 numSize - k 个元素 reverse(arr, 0, numSize - k - 1); // 第二:反转后 k 个元素 reverse(arr, numSize - k, numSize - 1); // 第三:反转整个数组 reverse(arr, 0, numSize - 1); // 打印结果 for (int i = 0; i < numSize; i++) { printf("%d ", arr[i]); } return 0; } ``` 这种方法的时间复杂度为 O(n),因为每一都只涉及线性的操作。 --- #### 方法二:逐位右移法 该方法通过将数组中的每个元素向右移动 `k` 次的方式实现旋转。每次移动时,最后一个元素会被移到第一个位置。 以下是具体的代码实现: ```c #include <stdio.h> #define N 10 // 打印数组函数 void PrintArray(int ar[], int n) { for (int i = 0; i < n; ++i) { printf("%d ", ar[i]); } printf("\n"); } // 实现右旋数组函数 void RightRotateArray(int ar[], int n, int k) { for (int i = 0; i < k; ++i) { // 循环执行k次右移 int temp = ar[n - 1]; // 存储最后一个元素 for (int j = n - 1; j > 0; --j) { // 将每个元素向前移动一位 ar[j] = ar[j - 1]; } ar[0] = temp; // 把存储的最后一个元素放到第一位 } } int main() { int ar[N] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // 初始化数组 int k; printf("请输入需要旋转的次数:"); scanf("%d", &k); // 用户输入旋转次数 // 调用右旋函数 RightRotateArray(ar, N, k); // 打印旋转后的数组 PrintArray(ar, N); return 0; } ``` 此方法较为直观,但时间复杂度较高,为 O(k \* n)。 --- #### 性能对比 - **反转法**适用于大规模数据场景,因为它只需遍历数组几次即可完成操作,时间复杂度较低。 - **逐位右移法**适合小规模数据或教学演示用途,但由于其嵌套循环结构,在大数据量下表现较差。 --- #### 寻找旋转数组中的最小值(扩展内容) 如果需要在一个已知被旋转过的有序数组中快速找到最小值,可以使用二分查找的方法[^3]。这种技术特别适用于处理大型数据集,能够显著提高效率。 以下是二分查找实现的一个例子: ```c #include <stdio.h> // 查找旋转数组中的最小值 int findMinInRotatedArray(int arr[], int low, int high) { if (high < low) return arr[0]; // 边界情况 if (high == low) return arr[low]; int mid = low + (high - low) / 2; if (mid < high && arr[mid + 1] < arr[mid]) { return arr[mid + 1]; } if (mid > low && arr[mid] < arr[mid - 1]) { return arr[mid]; } if (arr[high] > arr[mid]) { return findMinInRotatedArray(arr, low, mid - 1); } else { return findMinInRotatedArray(arr, mid + 1, high); } } int main() { int arr[] = {4, 5, 6, 7, 0, 1, 2}; int n = sizeof(arr) / sizeof(arr[0]); int minValue = findMinInRotatedArray(arr, 0, n - 1); printf("旋转数组中的最小值是:%d\n", minValue); return 0; } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值