C语言双指针法实现数组奇偶分离

在编程中,常常会遇到一些简单的数组操作问题,其中之一就是如何将数组中的奇数和偶数分离,奇数排在前面,偶数排在后面。这个问题虽然看起来简单,但如何高效地实现是我们需要思考的问题。

本文将通过C语言来实现这一功能,并且使用双指针法(Two-pointer approach)来优化解决方案。通过这种方法,我们可以在O(n)的时间复杂度内完成数组奇偶分离,而且空间复杂度O(1),即只需要常数空间。

问题分析

给定一个整数数组,我们需要将其中的所有奇数移动到数组的前面,所有偶数移动到数组的后面。要求:

  • 奇数和偶数之间的顺序可以不保持原有顺序。
  • 不允许使用额外的数组空间。

解决思路

为了实现上述功能,我们可以采用双指针法。基本思路是通过两个指针,一个从数组的左端开始,另一个从右端开始,进行交换操作。具体步骤如下:

  1. 左指针:从数组的开头开始,找出第一个偶数。
  2. 右指针:从数组的尾部开始,找出第一个奇数。
  3. 交换:如果左指针指向偶数,右指针指向奇数,就交换这两个数的位置。
  4. 继续移动指针:然后分别移动左指针和右指针,直到两个指针相遇或交错。

通过这种方法,我们可以在一次遍历中完成奇偶分离的任务,时间复杂度为O(n),而空间复杂度仅为O(1),因为我们只用了常数的额外空间。

代码实现

下面是基于双指针法实现的C语言代码:

#include 

void adjustArray(int arr[], int sz) {
    int left = 0;   // 左指针,从数组的头部开始
    int right = sz - 1; // 右指针,从数组的尾部开始

    while (left < right) {
        // 找到左指针指向的是偶数
        while (left < right && arr[left] % 2 != 0) {
            left++;  // 向右移动左指针
        }

        // 找到右指针指向的是奇数
        while (left < right && arr[right] % 2 == 0) {
            right--;  // 向左移动右指针
        }

        // 当左指针指向偶数,右指针指向奇数时,交换它们
        if (left < right) {
            int temp = arr[left];
            arr[left] = arr[right];
            arr[right] = temp;
        }
    }
}

int main() {
    int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    int sz = sizeof(arr) / sizeof(arr[0]);

    // 调整数组中的奇偶顺序
    adjustArray(arr, sz);

    // 输出调整后的数组
    printf("调整后的数组:");
    for (int i = 0; i < sz; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    return 0;
}

代码解析

  1. 双指针初始化:我们定义了两个指针,left 和 right,分别指向数组的开始和末尾。
  2. 左指针移动:当左指针指向一个奇数时,我们不需要做任何操作,直接将指针向右移动,直到找到一个偶数。
  3. 右指针移动:当右指针指向偶数时,我们不需要做任何操作,直接将指针向左移动,直到找到一个奇数。
  4. 交换:当左指针指向偶数且右指针指向奇数时,我们交换它们的位置。
  5. 继续循环:指针继续向内移动,直到它们相遇或交错,表示数组的奇偶分离完成。

示例运行

假设我们有一个包含奇数和偶数的数组:

int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

经过上述算法处理后,数组中的奇数和偶数将被分开,输出可能是:

调整后的数组:1 9 3 5 7 6 4 8 2 10

这里,奇数部分 [1, 9, 3, 5, 7] 被移到了数组的前面,偶数部分 [6, 4, 8, 2, 10] 被移到了后面。

时间与空间复杂度

  1. 时间复杂度:O(n),其中n是数组的长度。我们最多遍历一次数组,因此时间复杂度是线性的。
  2. 空间复杂度:O(1),我们只使用了常数的额外空间(仅用于指针和临时变量),没有使用额外的数组。

这种方法非常高效,尤其适用于需要在空间有限的情况下处理大数组的场景。

总结

通过双指针法,我们可以在O(n)的时间复杂度内完成数组的奇偶分离,并且空间复杂度为O(1),这使得算法非常高效,适用于大规模数据处理。双指针法是一种常用的技巧,在许多数组和链表的操作中都能派上用场。如果你还不熟悉双指针法,建议深入理解并多加练习。

你可能感兴趣的:(c语言,算法,数据结构)