问题描述:
给出一个整数数nums和一个整数k。划分数组(即移动数组nums中的元素),使得:
- 所有小于k的元素移到左边
- 所有大于等于k的元素移到右边
返回数组划分的位置,即数组中第一个位置i,满足nums[i]大于等于k。
样例:给出数组nums = [3, 2, 2, 1]和 k=2,返回 1。
挑战:要求在原地使用O(n)的时间复杂度来划分数组。
本题最直观的思路是直接排序,然后找出i的位置。但是这种方式的时间复杂度为O(nlogn)。若想降低时间复杂度,此处采用两根指针的方法。规定两根指针start和end分别指向数组的首尾,分别向后,向前遍历。若nums[start] > k且nums[end] < k,则交换这两个数。而最终start的值即为i的位置。本题在边界条件的处理时要尤为仔细。代码如下:
public class Solution {
public int partitionArray(int[] nums, int k) {
int start = 0;
int end = nums.length - 1;
int t = 0;
while (end - start >= 0) {
if (nums[start] >= k) {
if (nums[end] < k) {
t = nums[start];
nums[start] = nums[end];
nums[end] = t;
}
else {
end--;
}
}
else {
start++;
}
}
return start;
}
}
该方式完成了在原地使用O(n)的时间复杂度来划分数组。