5.20 寻找第k个最小数

This commit is contained in:
zhangsan 2025-05-21 15:10:26 +08:00
parent 353b7c0267
commit 71799259b9
3 changed files with 111 additions and 2 deletions

View File

@ -1,7 +1,5 @@
package array; package array;
import java.util.ArrayDeque;
import java.util.Deque;
/** /**
* 题目 918. 环形子数组的最大和 (maxSubarraySumCircular) * 题目 918. 环形子数组的最大和 (maxSubarraySumCircular)

View File

@ -0,0 +1,64 @@
package binary_search;
/**
* 题目 4. 寻找两个正序数组的中位数 (findMedianSortedArrays)
* 描述给定两个大小分别为 m n 的正序从小到大数组 nums1 nums2请你找出并返回这两个正序数组的 中位数
*
* 算法的时间复杂度应该为 O(log (m+n))
*
示例 1
输入nums1 = [1,3], nums2 = [2]
输出2.00000
解释合并数组 = [1,2,3] 中位数 2
*
* 链接https://leetcode.cn/problems/median-of-two-sorted-arrays/
*/
//不会
public class FindMedianSortedArrays {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int m = nums1.length, n = nums2.length;
int total = m + n;
if (total % 2 == 1) {
// 奇数长度直接取第 (total+1)/2
return getKth(nums1, 0, nums2, 0, (total + 1) / 2);
} else {
// 偶数长度取第 total/2 total/2+1 两个数的平均
double left = getKth(nums1, 0, nums2, 0, total / 2);
double right= getKth(nums1, 0, nums2, 0, total / 2 + 1);
return (left + right) / 2.0;
}
}
// 返回 nums1[start1...] nums2[start2...] k 小的数
private double getKth(int[] nums1, int start1, int[] nums2, int start2, int k) {
// 如果 nums1 已经耗尽直接从 nums2 里取
if (start1 >= nums1.length) {
return nums2[start2 + k - 1];
}
// 如果 nums2 耗尽
if (start2 >= nums2.length) {
return nums1[start1 + k - 1];
}
// 如果 k == 1取两数组当前头部较小者
if (k == 1) {
return Math.min(nums1[start1], nums2[start2]);
}
// 各自看 k/2 位置的元素如果超出边界则视作 +
int midVal1 = (start1 + k/2 - 1 < nums1.length)
? nums1[start1 + k/2 - 1]
: Integer.MAX_VALUE;
int midVal2 = (start2 + k/2 - 1 < nums2.length)
? nums2[start2 + k/2 - 1]
: Integer.MAX_VALUE;
// 抛弃较小者及其前面 k/2 个元素
if (midVal1 < midVal2) {
// 抛弃 nums1[start1 ... start1 + k/2 - 1]
return getKth(nums1, start1 + k/2, nums2, start2, k - k/2);
} else {
// 抛弃 nums2[start2 ... start2 + k/2 - 1]
return getKth(nums1, start1, nums2, start2 + k/2, k - k/2);
}
}
}

View File

@ -0,0 +1,47 @@
package binary_search;
/**
* 题目 162. 寻找峰值 (findPeakElement)
* 描述峰值元素是指其值严格大于左右相邻值的元素
* 给你一个整数数组 nums找到峰值元素并返回其索引数组可能包含多个峰值在这种情况下返回 任何一个峰值 所在位置即可
* 你可以假设 nums[-1] = nums[n] = -
* 你必须实现时间复杂度为 O(log n) 的算法来解决此问题
*
示例 1
输入nums = [1,2,3,1]
输出2
解释3 是峰值元素你的函数应该返回其索引 2
*
* 链接https://leetcode.cn/problems/find-peak-element/
*/
public class FindPeakElement {
public int findPeakElement1(int[] nums) {
int pre=Integer.MIN_VALUE;
for (int i = 0; i < nums.length-1; i++) {
int cur=nums[i];
int next=nums[i+1];
if(pre<cur&&cur>next)
return i;
pre=cur;
}
if(nums[nums.length-1]>pre)
return nums.length-1;
else return 0;
}
//二分查找 Ologn
public int findPeakElement(int[] nums) {
int l = 0, r = nums.length - 1;
while (l < r) {
int mid = l + (r - l) / 2;
// 如果右侧更就在右半区继续寻找
if (nums[mid] < nums[mid + 1]) {
l = mid + 1;
} else {
// 否则峰值在左半区包括 mid 自身
r = mid;
}
}
// l == r即为峰值下标
return l;
}
}