一、题目描述
给你一个整数数组 nums
,数组中共有 n
个整数。132 模式的子序列 由三个整数 nums[i]
、nums[j]
和 nums[k]
组成,并同时满足:i < j < k
和 nums[i] < nums[k] < nums[j]
。
如果 nums
中存在 132 模式的子序列 ,返回 true
;否则,返回 false
。
示例 1:
输入:nums = [1,2,3,4] 输出:false 解释:序列中不存在 132 模式的子序列。
示例 2:
输入:nums = [3,1,4,2] 输出:true 解释:序列中有 1 个 132 模式的子序列: [1, 4, 2] 。
示例 3:
输入:nums = [-1,3,2,0] 输出:true 解释:序列中有 3 个 132 模式的的子序列:[-1, 3, 2]、[-1, 3, 0] 和 [-1, 2, 0] 。
提示:
n == nums.length
1 <= n <= 2 * 10^5
-10^9 <= nums[i] <= 10^9
二、解题思路
要解决这个问题,我们可以使用一个单调栈来帮助我们找到满足132模式的子序列。以下是解题思路:
- 从后向前遍历数组,维护一个单调递减栈,栈中存储的是数组元素的索引。
- 使用一个变量
third
来记录当前遍历到的元素作为nums[k]
时,所有可能的nums[i]
中的最大值。 - 当遍历到一个元素
nums[j]
时,如果third
不为空且nums[j] > third
,则说明找到了一个满足条件的子序列,返回true
。 - 如果当前元素
nums[j]
小于栈顶元素对应的值,则将栈顶元素弹出,并更新third
为弹出的元素值,因为此时弹出的元素可以作为nums[k]
,而nums[j]
可以作为nums[j]
,我们记录下nums[k]
中的最大值作为third
。 - 将当前元素的索引压入栈中。
- 如果遍历完数组仍未找到满足条件的子序列,则返回
false
。
三、具体代码
class Solution {public boolean find132pattern(int[] nums) {if (nums == null || nums.length < 3) {return false;}// 单调栈,存储的是元素的索引Stack<Integer> stack = new Stack<>();// third变量记录所有可能的nums[i]中的最大值int third = Integer.MIN_VALUE;// 从后向前遍历数组for (int i = nums.length - 1; i >= 0; i--) {// 如果当前元素小于third,说明找到了132模式if (nums[i] < third) {return true;}// 当栈不为空且当前元素大于栈顶元素时,更新thirdwhile (!stack.isEmpty() && nums[i] > nums[stack.peek()]) {third = nums[stack.pop()];}// 将当前元素的索引压入栈中stack.push(i);}// 如果遍历完数组仍未找到满足条件的子序列,则返回falsereturn false;}
}
四、时间复杂度和空间复杂度
1. 时间复杂度
- 遍历数组:我们使用了一个for循环来遍历数组中的每个元素,这个操作的时间复杂度是O(n),其中n是数组的长度。
- 栈操作:在每次遍历中,每个元素最多只会被压入栈一次,并且最多也只会被弹出一次。因此,整个数组遍历过程中,每个元素最多只会经过栈两次(一次入栈,一次出栈),这意味着栈相关的操作的总时间复杂度也是O(n)。
由于这两个操作是顺序执行的(遍历数组和栈操作是同时进行的),所以总的时间复杂度是O(n)。
2. 空间复杂度
- 栈空间:在最坏的情况下,如果数组是单调递增的,那么所有元素都会被压入栈中。因此,栈的空间复杂度是O(n),其中n是数组的长度。
- 辅助空间:除了栈之外,我们只使用了一个额外的变量
third
来存储中间值,这个变量占用的空间是常数级的,即O(1)。
因此,总的空间复杂度是O(n),由栈的大小决定。
五、总结知识点
-
数组遍历:
- 使用for循环从后向前遍历数组,这是为了能够利用栈来维护一个单调递减的序列。
-
栈(Stack)的使用:
- 使用Java的
Stack
类来存储数组元素的索引,栈在这里用于维护一个单调递减的序列,帮助我们找到可能的nums[k]
。
- 使用Java的
-
条件判断:
- 使用
if
语句来判断是否找到了132模式的子序列。 - 使用
while
循环来处理栈中元素,当栈不为空且当前元素大于栈顶元素时,更新third
变量。
- 使用
-
最小值初始化:
- 使用
Integer.MIN_VALUE
来初始化third
变量,确保在比较时能够正确地更新third
为更大的值。
- 使用
-
栈的基本操作:
push()
:将元素压入栈中。pop()
:从栈中弹出元素。peek()
:查看栈顶元素而不弹出。
-
返回值:
- 方法返回一个布尔值,表示是否找到了132模式的子序列。
-
边界条件检查:
- 在方法开始时检查输入数组是否为空或长度小于3,因为至少需要3个元素才能形成132模式。
-
整数比较:
- 在代码中多次进行了整数比较,这是基本的编程操作。
-
逻辑推理:
- 整个算法的设计基于对132模式的理解,以及如何通过栈来维护一个潜在的有效序列,这是算法的核心。
以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。