📌  相关文章
📜  检查是否存在三元组(i,j,k),使得i <j <k时arr [i] <arr [k] <arr [j](1)

📅  最后修改于: 2023-12-03 15:10:54.683000             🧑  作者: Mango

检查是否存在三元组(i,j,k),使得i < j < k时arr[i] < arr[k] < arr[j]

问题描述:给定一个整数数组,编写一个函数来检查数组中是否存在三个元素,使得第一个元素小于第二个元素,并且第二个元素小于第三个元素。

示例 1:

输入: [1,2,3,4,5]
输出: true

示例 2:

输入: [5,4,3,2,1]
输出: false
解题思路

我们从题目给出的条件入手,i<j<k,且arr[i]<arr[k]<arr[j]。

那么我们可以暴力遍历数组,每次选定当前第一个数i,然后在后面寻找一个数k,使得arr[i]<arr[k],然后在[k+1, n-1]之间循环遍历,寻找一个数j,并且arr[k]<arr[j]。

当然,上述方法的时间复杂度极高,我们可以采用优化。

我们依旧从题目给出的条件出发,不妨设当前遍历到的数是j,那么我们需要寻找左边和右边的数满足题目条件。

首先我们考虑遍历到中间的数j时,如何判断左边的数arr[i]是否符合条件?

如果当前的数j比左边的数小,那么我们可以根据arr[k]<arr[j]得到arr[k]也比左边的数小,所以左边的数是不符合题目要求的。

如果当前的数j比左边的数大,那么我们可以保证右边一定存在数arr[k]是比左边的数小的,所以我们只需要判断右边的数是否满足条件即可。

接下来我们考虑找右边的数arr[j],这个时候我们可以倒序遍历数组,并且用一个变量max_k表示我们目前为止遍历到的数中,满足arr[k]<arr[j]且k最大的那个数,如果max_k<arr[j],说明我们已经找到了满足题目条件的三元组,即(i, max_k, j)。

需要注意的是,倒序遍历数组是因为我们需要找max_k中的最大值,这样才能保证找到的三元组中k是最大的。如果是正序遍历,找到的是k最小的满足条件的数,而不是k最大的满足条件的数。

代码实现

Python 代码实现如下:

def find132pattern(nums: List[int]) -> bool:
    n = len(nums)
    if n < 3:   # 数组长度小于3不符合题目要求
        return False
    stack_k = []    # 用栈存储满足arr[k]<arr[j]的数。栈顶元素最小
    max_k = float('-inf')   # 记录目前找到的满足arr[k]<arr[j]且k最大的数
    for i in range(n-1, -1, -1):
        if nums[i] < max_k: # arr[i]<arr[k]<arr[j],返回True
            return True
        while stack_k and nums[i] > stack_k[-1]:
            max_k = stack_k.pop()   # 更新max_k,使得其一直是存储到目前为止最大的满足arr[k]<arr[j]的数
        if nums[i] > max_k: # 如果右边有数比max_k大,说明存在一组满足arr[i]<arr[k]<arr[j]的三元组
            stack_k.append(nums[i]) # 存储当前找到的满足arr[k]<arr[j]的数
    return False   # 找不到,返回False

时间复杂度为O(N),空间复杂度为O(N)。