class Solution {
public:
bool find132pattern(vector<int>& nums) {
}
};
456. 132 模式
给你一个整数数组 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 * 105
-109 <= nums[i] <= 109
原站题解
javascript 解法, 执行用时: 80 ms, 内存消耗: 52.5 MB, 提交时间: 2023-09-24 19:04:48
/** * @param {number[]} nums * @return {boolean} */ var find132pattern = function(nums) { const n = nums.length; const candidate_k = [nums[n - 1]]; let max_k = -Number.MAX_SAFE_INTEGER; for (let i = n - 2; i >= 0; --i) { if (nums[i] < max_k) { return true; } while (candidate_k.length && nums[i] > candidate_k[candidate_k.length - 1]) { max_k = candidate_k[candidate_k.length - 1]; candidate_k.pop(); } if (nums[i] > max_k) { candidate_k.push(nums[i]); } } return false; };
cpp 解法, 执行用时: 76 ms, 内存消耗: 47.8 MB, 提交时间: 2023-09-24 19:04:35
class Solution { public: bool find132pattern(vector<int>& nums) { int n = nums.size(); stack<int> candidate_k; candidate_k.push(nums[n - 1]); int max_k = INT_MIN; for (int i = n - 2; i >= 0; --i) { if (nums[i] < max_k) { return true; } while (!candidate_k.empty() && nums[i] > candidate_k.top()) { max_k = candidate_k.top(); candidate_k.pop(); } if (nums[i] > max_k) { candidate_k.push(nums[i]); } } return false; } };
java 解法, 执行用时: 11 ms, 内存消耗: 61.5 MB, 提交时间: 2023-09-24 19:04:14
class Solution { // 枚举3 public boolean find132pattern3(int[] nums) { int n = nums.length; if (n < 3) { return false; } // 左侧最小值 int leftMin = nums[0]; // 右侧所有元素 TreeMap<Integer, Integer> rightAll = new TreeMap<Integer, Integer>(); for (int k = 2; k < n; ++k) { rightAll.put(nums[k], rightAll.getOrDefault(nums[k], 0) + 1); } for (int j = 1; j < n - 1; ++j) { if (leftMin < nums[j]) { Integer next = rightAll.ceilingKey(leftMin + 1); if (next != null && next < nums[j]) { return true; } } leftMin = Math.min(leftMin, nums[j]); rightAll.put(nums[j + 1], rightAll.get(nums[j + 1]) - 1); if (rightAll.get(nums[j + 1]) == 0) { rightAll.remove(nums[j + 1]); } } return false; } // 枚举1 public boolean find132pattern(int[] nums) { int n = nums.length; Deque<Integer> candidateK = new LinkedList<Integer>(); candidateK.push(nums[n - 1]); int maxK = Integer.MIN_VALUE; for (int i = n - 2; i >= 0; --i) { if (nums[i] < maxK) { return true; } while (!candidateK.isEmpty() && nums[i] > candidateK.peek()) { maxK = candidateK.pop(); } if (nums[i] > maxK) { candidateK.push(nums[i]); } } return false; } // 枚举2 public boolean find132pattern2(int[] nums) { int n = nums.length; List<Integer> candidateI = new ArrayList<Integer>(); candidateI.add(nums[0]); List<Integer> candidateJ = new ArrayList<Integer>(); candidateJ.add(nums[0]); for (int k = 1; k < n; ++k) { int idxI = binarySearchFirst(candidateI, nums[k]); int idxJ = binarySearchLast(candidateJ, nums[k]); if (idxI >= 0 && idxJ >= 0) { if (idxI <= idxJ) { return true; } } if (nums[k] < candidateI.get(candidateI.size() - 1)) { candidateI.add(nums[k]); candidateJ.add(nums[k]); } else if (nums[k] > candidateJ.get(candidateJ.size() - 1)) { int lastI = candidateI.get(candidateI.size() - 1); while (!candidateJ.isEmpty() && nums[k] > candidateJ.get(candidateJ.size() - 1)) { candidateI.remove(candidateI.size() - 1); candidateJ.remove(candidateJ.size() - 1); } candidateI.add(lastI); candidateJ.add(nums[k]); } } return false; } public int binarySearchFirst(List<Integer> candidate, int target) { int low = 0, high = candidate.size() - 1; if (candidate.get(high) >= target) { return -1; } while (low < high) { int mid = (high - low) / 2 + low; int num = candidate.get(mid); if (num >= target) { low = mid + 1; } else { high = mid; } } return low; } public int binarySearchLast(List<Integer> candidate, int target) { int low = 0, high = candidate.size() - 1; if (candidate.get(low) <= target) { return -1; } while (low < high) { int mid = (high - low + 1) / 2 + low; int num = candidate.get(mid); if (num <= target) { high = mid - 1; } else { low = mid; } } return low; } }
python3 解法, 执行用时: 96 ms, 内存消耗: 33.8 MB, 提交时间: 2023-09-24 19:02:58
class Solution: # 枚举3 def find132pattern3(self, nums: List[int]) -> bool: n = len(nums) if n < 3: return False # 左侧最小值 left_min = nums[0] # 右侧所有元素 right_all = SortedList(nums[2:]) for j in range(1, n - 1): if left_min < nums[j]: index = right_all.bisect_right(left_min) if index < len(right_all) and right_all[index] < nums[j]: return True left_min = min(left_min, nums[j]) right_all.remove(nums[j + 1]) return False # 枚举2 def find132pattern2(self, nums: List[int]) -> bool: candidate_i, candidate_j = [-nums[0]], [-nums[0]] for v in nums[1:]: idx_i = bisect.bisect_right(candidate_i, -v) idx_j = bisect.bisect_left(candidate_j, -v) if idx_i < idx_j: return True if v < -candidate_i[-1]: candidate_i.append(-v) candidate_j.append(-v) elif v > -candidate_j[-1]: last_i = -candidate_i[-1] while candidate_j and v > -candidate_j[-1]: candidate_i.pop() candidate_j.pop() candidate_i.append(-last_i) candidate_j.append(-v) return False # 枚举1 def find132pattern(self, nums: List[int]) -> bool: n = len(nums) candidate_k = [nums[n - 1]] max_k = float("-inf") for i in range(n - 2, -1, -1): if nums[i] < max_k: return True while candidate_k and nums[i] > candidate_k[-1]: max_k = candidate_k[-1] candidate_k.pop() if nums[i] > max_k: candidate_k.append(nums[i]) return False
golang 解法, 执行用时: 68 ms, 内存消耗: 11.7 MB, 提交时间: 2023-09-24 19:01:39
// 枚举1 func find132pattern(nums []int) bool { n := len(nums) candidateK := []int{nums[n-1]} maxK := math.MinInt64 for i := n - 2; i >= 0; i-- { if nums[i] < maxK { return true } for len(candidateK) > 0 && nums[i] > candidateK[len(candidateK)-1] { maxK = candidateK[len(candidateK)-1] candidateK = candidateK[:len(candidateK)-1] } if nums[i] > maxK { candidateK = append(candidateK, nums[i]) } } return false } // 枚举2 func find132pattern2(nums []int) bool { candidateI, candidateJ := []int{-nums[0]}, []int{-nums[0]} for _, v := range nums[1:] { idxI := sort.SearchInts(candidateI, 1-v) idxJ := sort.SearchInts(candidateJ, -v) if idxI < idxJ { return true } if v < -candidateI[len(candidateI)-1] { candidateI = append(candidateI, -v) candidateJ = append(candidateJ, -v) } else if v > -candidateJ[len(candidateJ)-1] { lastI := -candidateI[len(candidateI)-1] for len(candidateJ) > 0 && v > -candidateJ[len(candidateJ)-1] { candidateI = candidateI[:len(candidateI)-1] candidateJ = candidateJ[:len(candidateJ)-1] } candidateI = append(candidateI, -lastI) candidateJ = append(candidateJ, -v) } } return false }
golang 解法, 执行用时: 136 ms, 内存消耗: 17.4 MB, 提交时间: 2023-09-24 19:00:52
import "math/rand" type node struct { ch [2]*node priority int val int cnt int } func (o *node) cmp(b int) int { switch { case b < o.val: return 0 case b > o.val: return 1 default: return -1 } } func (o *node) rotate(d int) *node { x := o.ch[d^1] o.ch[d^1] = x.ch[d] x.ch[d] = o return x } type treap struct { root *node } func (t *treap) _put(o *node, val int) *node { if o == nil { return &node{priority: rand.Int(), val: val, cnt: 1} } if d := o.cmp(val); d >= 0 { o.ch[d] = t._put(o.ch[d], val) if o.ch[d].priority > o.priority { o = o.rotate(d ^ 1) } } else { o.cnt++ } return o } func (t *treap) put(val int) { t.root = t._put(t.root, val) } func (t *treap) _delete(o *node, val int) *node { if o == nil { return nil } if d := o.cmp(val); d >= 0 { o.ch[d] = t._delete(o.ch[d], val) return o } if o.cnt > 1 { o.cnt-- return o } if o.ch[1] == nil { return o.ch[0] } if o.ch[0] == nil { return o.ch[1] } d := 0 if o.ch[0].priority > o.ch[1].priority { d = 1 } o = o.rotate(d) o.ch[d] = t._delete(o.ch[d], val) return o } func (t *treap) delete(val int) { t.root = t._delete(t.root, val) } func (t *treap) upperBound(val int) (ub *node) { for o := t.root; o != nil; { if o.cmp(val) == 0 { ub = o o = o.ch[0] } else { o = o.ch[1] } } return } func find132pattern(nums []int) bool { n := len(nums) if n < 3 { return false } leftMin := nums[0] rights := &treap{} for _, v := range nums[2:] { rights.put(v) } for j := 1; j < n-1; j++ { if nums[j] > leftMin { ub := rights.upperBound(leftMin) if ub != nil && ub.val < nums[j] { return true } } else { leftMin = nums[j] } rights.delete(nums[j+1]) } return false }