31. 数组划分

描述

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

注意事项

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

挑战

使用 O(n) 的时间复杂度在数组上进行划分。

思路

值得注意的地方是在快速排序算法的各种应用中,下面四个连续判断条件要一致,此算法left不能等于right,在快排中分割值是在数组中挑的,本题中数组元素可能都小于k,可能出现left等于right且在边界点仍满足条件,left++越界的情形
比如数组[7,7,9,8,6,6,8,7,9,8,6,6],k = 10

代码

public class Solution {
    /*
     * @param nums: The integer array you should partition
     * @param k: An integer
     * @return: The index after partition
     */
    public int partitionArray(int[] nums, int k) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        
        int left = 0, right = nums.length - 1;
        
        while (left < right) {
            while (left < right && nums[left] < k) {
                left++;
            }
            while (left < right && nums[right] >= k) {
                right--;
            }
            if (left < right) {
                int temp = nums[left];
                nums[left] = nums[right];
                nums[right] = temp;
                left++;
                right--;
            }
        } 
        // left = right 情况单独判断,本题之所以在上面的 while 循环中把 = 去掉,
        // 是由于题目要求返回数组中第一个位置 i 满足 nums[i] 大于等于 k 
        // 上述代码已经完成了基本的 partition 功能,但分割点 left = right 处值和 k 的大小关系要特判下
        // 此处还可能出现 left 和 right 由于 ++ -- 操作后刚好错开的情形,但下面代码也可以返回正确结果
        if (nums[left] >= k) {
            return left;
        }
        return left + 1;
    }
}

你可能感兴趣的:(31. 数组划分)