给定两个大小分别为 m
和 n
的正序(从小到大)数组 nums1
和 nums2
。请你找出并返回这两个正序数组的 中位数 。
算法的时间复杂度应该为 O(log (m+n))
。
题目分析:
这道题目需要我们在两个有序数组中,查找它们的中位数。中位数是指将一个集合元素按大小排列后,形成的一个数值序列中最中间的那个数。对于偶数个元素的序列,它没有唯一的中间值,而是取最中间的两个元素的算术平均数。
解决方案:
1.将两个有序数组进行切分,使得两个部分的长度差不超过 1。
2.使得切分后两个部分左侧的所有元素都小于右侧的所有元素。
3.根据两个部分左侧的元素个数之和判断中位数应该在哪一部分。
4.如果两个部分长度之和为奇数,则中位数为左侧部分最大的元素;如果长度为偶数,则需要取左侧最大元素和右侧最小元素的平均值作为中位数。
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
# 将较长的数组定义为 nums1
if len(nums1) > len(nums2):
nums1, nums2 = nums2, nums1
m, n = len(nums1), len(nums2)
left, right, half_len = 0, m, (m + n + 1) // 2
while left <= right:
i = (left + right) // 2
j = half_len - i
if i < m and nums2[j-1] > nums1[i]:
# i 偏小,需要右移
left = i + 1
elif i > 0 and nums1[i-1] > nums2[j]:
# i 偏大,需要左移
right = i - 1
else:
# i 长度刚好
if i == 0:
max_of_left = nums2[j-1]
elif j == 0:
max_of_left = nums1[i-1]
else:
max_of_left = max(nums1[i-1], nums2[j-1])
if (m + n) % 2 == 1:
return max_of_left
if i == m:
min_of_right = nums2[j]
elif j == n:
min_of_right = nums1[i]
else:
min_of_right = min(nums1[i], nums2[j])
return (max_of_left + min_of_right) / 2.0
时间复杂度为 O(log(m+n))
KMP解法:
这道题目是一道字符串匹配问题,给出一个字符串和一个模式串,在字符串中查找是否存在符合模式串的子串。
为了解决这个问题,我们也可以采用经典的 KMP 算法来实现。KMP 算法是一个高效的字符串匹配算法,它的核心思想是通过利用已知信息来跳过不必要的匹配,从而达到提高匹配效率的目的。
1.我们首先根据模式串构建 next 数组,其中 next[i] 表示当遇到第 i 个字符不匹配时,下一个匹配位置应该在模式串中的哪个位置上。
2.然后我们使用双指针的方法来进行匹配,将 i 指针指向字符串中待匹配的下一个位置,将 j 指针指向模式串中待匹配的下一个位置。
3.如果当前字符匹配成功,则将 i 和 j 都向一下个位置移动一位;否则,根据 next 数组中已保存的信息,计算 j 指针的下一个位置,继续进行匹配。
4.直到匹配成功或者字符串中的字符已经全部遍历成功为止。
时间复杂度为 O(m + n),其中 m 表示字符串的长度,n 表示模式串的长度。
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
if not needle:
return 0
m, n = len(haystack), len(needle)
next = self.get_next(needle)
i, j = 0, 0
while i < m and j < n:
if j == -1 or haystack[i] == needle[j]:
i += 1
j += 1
else:
j = next[j]
if j == n:
return i - j
return -1
def get_next(self, needle):
n = len(needle)
next = [-1] * n
i, j = 0, -1
while i < n - 1:
if j == -1 or needle[i] == needle[j]:
i += 1
j += 1
next[i] = j
else:
j = next[j]
return next
时间复杂度为 O(m + n),运行时间为 36 ms,内存消耗为 14.7 MB,可以 AC 这道题目。