From 71799259b948cafc2e6a48207daafc32b5bc2b23 Mon Sep 17 00:00:00 2001 From: zhangsan <646228430@qq.com> Date: Wed, 21 May 2025 15:10:26 +0800 Subject: [PATCH] =?UTF-8?q?5.20=20=E5=AF=BB=E6=89=BE=E7=AC=ACk=E4=B8=AA?= =?UTF-8?q?=E6=9C=80=E5=B0=8F=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/array/MaxSubarraySumCircular.java | 2 - .../binary_search/FindMedianSortedArrays.java | 64 +++++++++++++++++++ .../java/binary_search/FindPeakElement.java | 47 ++++++++++++++ 3 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 src/main/java/binary_search/FindMedianSortedArrays.java create mode 100644 src/main/java/binary_search/FindPeakElement.java diff --git a/src/main/java/array/MaxSubarraySumCircular.java b/src/main/java/array/MaxSubarraySumCircular.java index aab964d..d9ddf1b 100644 --- a/src/main/java/array/MaxSubarraySumCircular.java +++ b/src/main/java/array/MaxSubarraySumCircular.java @@ -1,7 +1,5 @@ package array; -import java.util.ArrayDeque; -import java.util.Deque; /** * 题目: 918. 环形子数组的最大和 (maxSubarraySumCircular) diff --git a/src/main/java/binary_search/FindMedianSortedArrays.java b/src/main/java/binary_search/FindMedianSortedArrays.java new file mode 100644 index 0000000..9788c72 --- /dev/null +++ b/src/main/java/binary_search/FindMedianSortedArrays.java @@ -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); + } + } +} diff --git a/src/main/java/binary_search/FindPeakElement.java b/src/main/java/binary_search/FindPeakElement.java new file mode 100644 index 0000000..cdec134 --- /dev/null +++ b/src/main/java/binary_search/FindPeakElement.java @@ -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(prenext) + 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; + } +}