旋转数组

本文深入探讨了数组元素向右移动k个位置的问题,通过实例展示了不同步骤下的数组变化,介绍了如何利用逆置操作实现高效数组旋转,同时强调了原地算法和空间复杂度O(1)的要求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

给定一个数组,将数组中的元素向右移动 个位置,其中 是非负数。

示例 1:

输入: [1,2,3,4,5,6,7]k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右旋转 1 步: [7,1,2,3,4,5,6]
向右旋转 2 步: [6,7,1,2,3,4,5]
向右旋转 3 步: [5,6,7,1,2,3,4]

示例 2:

输入: [-1,-100,3,99]k = 2
输出: [3,99,-1,-100]
解释: 
向右旋转 1 步: [99,-1,-100,3]
向右旋转 2 步: [3,99,-1,-100]

说明:

  • 尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。
  • 要求使用空间复杂度为 O(1) 的 原地 算法。

分析:

    设字符串为“abcdefg",往右移动两位,最后的结果为"fgabcde"

    第一步:逆置最后两位,结果为"abcdegf"

    第二步:逆置前面的几位,结果为“edcbagf"

    第三步:逆置全部字符串,结果为"fgabcde"

    完成

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
//         
        reverse(nums,0,nums.size()-k-1);
        reverse(nums,nums.size()-k,nums.size()-1);
        reverse(nums,0, nums.size()-1);        
    }
    
//     逆置从Nums[begin]到nums[end]的数组
    void reverse(vector<int>& nums,int begin, int end){
        while(begin <= end){
            int temp = nums[begin];
            nums[begin] = nums[end];
            nums[end] = temp;
            begin ++;
            end --;
        }
    }
};

 

### 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、付费专栏及课程。

余额充值