📅  最后修改于: 2023-12-03 15:40:25.145000             🧑  作者: Mango
此程序利用了快速选择算法,可以在 O(n) 的时间复杂度内查找第 k 个最大和连续子数组。
将原数组分为若干个不重叠的子数组,每个子数组的和即为该子数组的值。我们要找到第 k 大的和,因此可以想到使用快速选择算法。
快速选择算法的核心思想与快速排序相似。我们选定一个 pivot(这里可以选择中间的数),将数组分为比 pivot 大的部分和比 pivot 小的部分。
如果 k 大于 pivot 左边的子数组的个数,那么可以在 pivot 右边继续寻找第 k 大的子数组。否则,在 pivot 左边继续寻找。
通过不断递归,在每次递归中,可以将数组分为两部分,一部分是大于 pivot 的子数组,另一部分是小于 pivot 的子数组。如果 k 小于大于 pivot 的子数组的数量,那么在大于 pivot 的子数组中寻找第 k 大;否则,在小于 pivot 的子数组中寻找第 k-pivot左边数组长度-1 大。
当待查找的子数组大小为 1 时,即找到了第 k 大的子数组。
下面的代码实现了上述算法。函数 findKthLargestSubarray
中,变量 pivotIndex
表示当前数组中所选的 pivot,在函数中通过递归更新。变量 greaterCount
表示大于 pivot 值的子数组的数量。
int partition(vector<int>& nums, int left, int right) {
int pivotIndex = left + (right - left) / 2;
int pivot = nums[pivotIndex];
swap(nums[pivotIndex], nums[right]);
int storeIndex = left;
for (int i = left; i < right; i++) {
if (nums[i] > pivot) {
swap(nums[i], nums[storeIndex++]);
}
}
swap(nums[storeIndex], nums[right]);
return storeIndex;
}
int findKthLargestSubarray(vector<int>& nums, int left, int right, int k) {
if (left == right) return nums[left];
int pivotIndex = partition(nums, left, right);
int greaterCount = pivotIndex - left + 1;
if (k == greaterCount) {
return nums[pivotIndex];
} else if (k < greaterCount) {
return findKthLargestSubarray(nums, left, pivotIndex - 1, k);
} else {
return findKthLargestSubarray(nums, pivotIndex + 1, right, k - greaterCount);
}
}
int kthLargestSubarraySum(vector<int>& nums, int k) {
int n = nums.size();
vector<int> sums(n, 0);
sums[0] = nums[0];
for (int i = 1; i < n; i++) {
sums[i] = sums[i-1] + nums[i];
}
int ans = findKthLargestSubarray(sums, 0, n - 1, k);
return ans;
}
将上述代码拷贝到 cpp 文件中,使用以下代码调用函数 kthLargestSubarraySum
即可找到第 k 个最大和连续子数组的和。
vector<int> nums = {1, -2, 3, 4, -5};
int k = 2;
int ans = kthLargestSubarraySum(nums, k); // ans = 6