75 数组划分(Partition Array)

1 题目

题目:数组划分(Partition Array)
描述:给出一个整数数组 nums 和一个整数 k。划分数组(即移动数组 nums 中的元素),使得:所有小于k的元素移到左边、所有大于等于k的元素移到右边,返回数组划分的位置,即数组中第一个位置 i,满足 nums[i] 大于等于 k。

  1. 你应该真正的划分数组 nums,而不仅仅只是计算比 k 小的整数数,如果数组 nums 中的所有元素都比 k 小,则返回 nums.length。

lintcode题号——31,难度——medium

样例1:

输入:
nums = []
k = 9
输出:0
解释:空数组,输出0

样例2:

输入:
nums = [3,2,2,1]
k = 2
输出:1
解释:真实的数组为[1,2,2,3].所以返回 1

2 解决方案

2.1 思路

  使用对向双指针的方式,两个指针分别从头尾开始向中间走,两个指针配合,左指针寻找左区间中不符合条件的元素,右指针寻找右区间中符合条件的元素,交换两者,不断将符合条件的元素交换入左区间,直到所有符合条件的元素都到左边即可。

2.2 时间复杂度

  时间复杂度为O(n)。

2.3 空间复杂度

  空间复杂度为O(1)。

3 源码

细节:

  1. 使用对向双指针的方式。
  2. 边界判断需要单独对left指向的值进行判断,结果可能在right,也可能在right右边,所以不能在nums.at(left)<k时直接返回right。

C++版本:

/**
* @param nums: The integer array you should partition
* @param k: An integer
* @return: The index after partition
*/
int partitionArray(vector<int> &nums, int k) {
    // write your code here
    int result = 0;
    if (nums.empty())
    {
        return result;
    }

    int left = 0;
    int right = nums.size() - 1;
    while (left < right) // 与快排不同,快排为left<=right
    {
        if (nums.at(left) < k)
        {
            left++;
            continue;
        }
        
        if (nums.at(right) >= k)
        {
            right--;
            continue;
        }

        if (left < right)
        {
            swap(nums.at(left++), nums.at(right--));
        }
    }

    if (nums.at(left) < k)
    {
        return left + 1; // 使用right的话,无法处理k大于所有数组元素的情况
    }

    return left;        
}

猜你喜欢

转载自blog.csdn.net/SeeDoubleU/article/details/124642255
75