基础1: partition
Partition Array
Given an array nums
of integers and an int k
, partition the array (i.e move the elements in "nums") such that:
- All elements < k are moved to the left
- All elements >= k are moved to the right
Return the partitioning index, i.e the first index inums[i] >= k.
Example
If nums = [3,2,2,1]
and k=2
, a valid answer is 1
.
如果控制条件是 i < j 的话, 那么在如下情况下会出错
[7,7,9,8,6,6,8,7,9,8,6,6], 10
因为所有数字都小于10,那么i index 应该一直递增到超过j
所以应该为 i <= j
我的代码:
public class Solution { /** *@param nums: The integer array you should partition *@param k: As description *return: The index after partition */ public int partitionArray(int[] nums, int k) { //write your code here int i = 0, j = nums.length - 1; while (i <= j) { if (nums[i] < k && nums[j] < k) { i++; } else if (nums[i] < k && nums[j] >= k) { i++; j--; } else if (nums[i] >= k && nums[j] >= k) { j--; } else if (nums[i] >= k && nums[j] < k) { int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; i++; j--; } } return i; } }
其实当左边index的值比k小的时候 i可以一直递增
右边index的值比k大的时候 j可以一直递减
那么当两遍都违背的时候,做一次sawp
简洁到飞起来= =
public class Solution { /** *@param nums: The integer array you should partition *@param k: As description *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--; } } return left; } }
partitionArray
----------------------------------------分割线-------------------------------
Kth Largest Element in an Array
Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.
For example,
Given [3,2,1,5,6,4]
and k = 2, return 5.
这种算法的均摊复杂度是o(n)
T(n) = T(n/2) + o(n)
= T(n/4) + 0(n/2)+o(n)
=...
平均的时间复杂度是o(nlogn), 不理想的情况就是每次partition只排除掉1个点,那么时间复杂度会退化到o(n^2)
注意几个细节:
1. helper函数是int,递归返回最后的结果,一直返回到最外面一层
2. 这里的partition和前面partition array不同, 以left节点做为pivot,然后从右边开始走,把第一个不符合的放在左边,然后左边开始走,把不符合的放在右边。最后把pivot放回去新的left节点的位置
3. 找第k个大的点 转化为找第length - k + 1的小的点
public class Solution { public int findKthLargest(int[] nums, int k) { if (nums == null || nums.length == 0) { return -1; } return helper (nums, nums.length - k + 1, 0, nums.length - 1); //length - k + 1 convert the kth large to k‘th small one } private int helper(int[] nums, int k, int start, int end) { if (start == end) { return nums[start]; } int pos = partition(nums, start, end); if (pos + 1 == k) { return nums[pos]; } else if (pos + 1 > k) { return helper (nums, k, start, pos - 1); } else { /*这个地方为什么是return 下一层递归的结果,因为需要的结果在下层/下下层递归中得到, 把这个值返回来交给最上面的一层*/ return helper (nums, k, pos + 1, end); } } public int partition(int[] nums, int l, int r) { // 初始化左右指针和pivot int left = l, right = r; int pivot = nums[left]; // 进行partition while (left < right) { while (left < right && nums[right] >= pivot) { right--; } nums[left] = nums[right]; while (left < right && nums[left] <= pivot) { left++; } nums[right] = nums[left]; } // 返还pivot点到数组里面 nums[left] = pivot; return left; } }