📅  最后修改于: 2023-12-03 15:42:11.849000             🧑  作者: Mango
在这个问题中,我们需要设计一个算法来查找数组中第二个最小的元素。具体来说,我们需要实现以下函数:
def second_smallest(arr: List[int]) -> int:
pass
arr
:一个整数数组,长度为 $n$($2 \leq n \leq 10^6$),数组中的元素均为互不相同的整数。assert second_smallest([10, 5, 4, 3, 1]) == 3
assert second_smallest([2, 3, 1, 4]) == 2
assert second_smallest([5, 6, 2, 1, 7, 9]) == 2
我们可以使用类似快排的思路解决这个问题。具体来说,我们可以先选定一个数字为基准,将比它小的数字移动到它左边,比它大的数字移动到它右边。然后根据基准的位置,分别在基准的左侧和右侧进行递归查找,直到找到第二个最小的元素。
具体实现时,我们可以选择数组中的第一个元素为基准,然后使用 partition
函数进行划分。partition
函数将会返回一个整数,表示基准最终所在的位置。如果这个位置满足它左侧恰好有一个元素,那么这个元素就是第二个最小的元素;否则我们需要递归查找。
from typing import List
def second_smallest(arr: List[int]) -> int:
def partition(low: int, high: int) -> int:
pivot = arr[low]
i, j = low + 1, high
while i <= j:
while i <= high and arr[i] < pivot:
i += 1
while j >= low + 1 and arr[j] > pivot:
j -= 1
if i <= j:
arr[i], arr[j] = arr[j], arr[i]
i += 1
j -= 1
arr[low], arr[j] = arr[j], arr[low]
return j
def find(pos: int, low: int, high: int) -> int:
if pos == 1:
return arr[low]
pivot_pos = partition(low, high)
pivot_rank = pivot_pos - low + 1
if pos == pivot_rank:
return arr[pivot_pos]
elif pos < pivot_rank:
return find(pos, low, pivot_pos - 1)
else:
return find(pos - pivot_rank, pivot_pos + 1, high)
return find(2, 0, len(arr) - 1)
由于 partition
函数的调用次数最多为 $O(n)$,因此总的时间复杂度为 $O(n)$。同时在递归调用中并没有额外的空间开销,因此空间复杂度为 $O(1)$。