📌  相关文章
📜  每个子序列中出现最小的元素(1)

📅  最后修改于: 2023-12-03 14:55:55.470000             🧑  作者: Mango

每个子序列中出现最小的元素

在处理序列时,经常需要找出每个子序列中出现最小的元素。这个问题可以使用一些简单的算法来解决。

算法一:暴力枚举

这种算法是最基本的方法,即对于每个子序列,找出其中最小的元素。时间复杂度是 $O(n^2)$,其中 $n$ 是序列的长度。

代码实现:

def find_min_in_each_subsequence(nums):
    res = []
    for i in range(len(nums)):
        min_num = float('inf')
        for j in range(i, len(nums)):
            min_num = min(min_num, nums[j])
            res.append(min_num)
    return res
算法二:单调栈

这种算法使用了单调栈的思想,维护了一个递减的栈,即栈顶元素是当前栈中最小的元素。当遇到比栈顶元素更小的元素时,就将其入栈,否则将栈顶元素弹出,直到遇到比该元素更小的元素或者栈为空。

时间复杂度是 $O(n)$,其中 $n$ 是序列的长度。

代码实现:

def find_min_in_each_subsequence(nums):
    res = []
    stack = []
    for i in range(len(nums)):
        while stack and stack[-1] > nums[i]:
            stack.pop()
        if not stack:
            res.append(nums[i])
        else:
            res.append(stack[-1])
        stack.append(nums[i])
    return res
算法三:动态规划

这种算法使用了动态规划的思想,维护了一个状态数组 $dp$,其中 $dp[i]$ 表示以 $i$ 为结尾的子序列中的最小值。状态转移方程为 $dp[i] = min(dp[i-1], nums[i])$。

时间复杂度是 $O(n)$,其中 $n$ 是序列的长度。

代码实现:

def find_min_in_each_subsequence(nums):
    dp = [float('inf')] * len(nums)
    dp[0] = nums[0]
    for i in range(1, len(nums)):
        dp[i] = min(dp[i-1], nums[i])
    return dp
算法四:线段树

这种算法使用了线段树的思想,维护了一个线段树,其中每个节点表示该区间内的最小值。为了方便,我们可以将数组看作是一个只有一个元素的区间。对于每个子序列,查询该区间内的最小值即可。

时间复杂度是 $O(n\log n)$,其中 $n$ 是序列的长度。

代码实现:

class SegmentTree:
    def __init__(self, nums):
        self.nums = nums
        self.tree = [float('inf')] * (4 * len(nums))
        self.build(0, 0, len(nums)-1)
        
    def build(self, i, l, r):
        if l == r:
            self.tree[i] = self.nums[l]
            return
        mid = (l + r) // 2
        self.build(2*i+1, l, mid)
        self.build(2*i+2, mid+1, r)
        self.tree[i] = min(self.tree[2*i+1], self.tree[2*i+2])
        
    def query(self, i, l, r, ql, qr):
        if ql > r or qr < l:
            return float('inf')
        if ql <= l and qr >= r:
            return self.tree[i]
        mid = (l + r) // 2
        return min(self.query(2*i+1, l, mid, ql, qr),
                   self.query(2*i+2, mid+1, r, ql, qr))

def find_min_in_each_subsequence(nums):
    st = SegmentTree(nums)
    res = []
    for i in range(len(nums)):
        res.append(st.query(0, 0, len(nums)-1, i, i))
    return res

以上四种算法各有优缺点,具体使用哪种算法取决于实际问题。