📅  最后修改于: 2023-12-03 15:10:54.683000             🧑  作者: Mango
问题描述:给定一个整数数组,编写一个函数来检查数组中是否存在三个元素,使得第一个元素小于第二个元素,并且第二个元素小于第三个元素。
示例 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)。