Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Move from brute-force thinking to an efficient approach using array strategy.
You are given an integer array nums with distinct elements.
A subarray nums[l...r] of nums is called a bowl if:
r - l + 1 >= 3.min(nums[l], nums[r]) > max(nums[l + 1], ..., nums[r - 1]).Return the number of bowl subarrays in nums.
Example 1:
Input: nums = [2,5,3,1,4]
Output: 2
Explanation:
The bowl subarrays are [3, 1, 4] and [5, 3, 1, 4].
[3, 1, 4] is a bowl because min(3, 4) = 3 > max(1) = 1.[5, 3, 1, 4] is a bowl because min(5, 4) = 4 > max(3, 1) = 3.Example 2:
Input: nums = [5,1,2,3,4]
Output: 3
Explanation:
The bowl subarrays are [5, 1, 2], [5, 1, 2, 3] and [5, 1, 2, 3, 4].
Example 3:
Input: nums = [1000000000,999999999,999999998]
Output: 0
Explanation:
No subarray is a bowl.
Constraints:
3 <= nums.length <= 1051 <= nums[i] <= 109nums consists of distinct elements.Problem summary: You are given an integer array nums with distinct elements. A subarray nums[l...r] of nums is called a bowl if: The subarray has length at least 3. That is, r - l + 1 >= 3. The minimum of its two ends is strictly greater than the maximum of all elements in between. That is, min(nums[l], nums[r]) > max(nums[l + 1], ..., nums[r - 1]). Return the number of bowl subarrays in nums.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array · Stack
[2,5,3,1,4]
[5,1,2,3,4]
[1000000000,999999999,999999998]
Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #3676: Count Bowl Subarrays
// Auto-generated Java example from go.
class Solution {
public void exampleSolution() {
}
}
// Reference (go):
// // Accepted solution for LeetCode #3676: Count Bowl Subarrays
// package main
//
// // https://space.bilibili.com/206214
// func bowlSubarrays1(nums []int) (ans int64) {
// st := []int{}
// for i, x := range nums {
// for len(st) > 0 && nums[st[len(st)-1]] < x {
// // j=st[len(st)-1] 右侧严格大于 nums[j] 的数的下标是 i
// if i-st[len(st)-1] > 1 { // 子数组的长度至少为 3
// ans++
// }
// st = st[:len(st)-1]
// }
// // i 左侧大于等于 nums[i] 的数的下标是 st[len(st)-1]
// if len(st) > 0 && i-st[len(st)-1] > 1 { // 子数组的长度至少为 3
// ans++
// }
// st = append(st, i)
// }
// return
// }
//
// func bowlSubarrays(nums []int) (ans int64) {
// st := nums[:0]
// for _, x := range nums {
// for len(st) > 0 && st[len(st)-1] < x {
// st = st[:len(st)-1]
// if len(st) > 0 {
// ans++
// }
// }
// st = append(st, x)
// }
// return
// }
// Accepted solution for LeetCode #3676: Count Bowl Subarrays
package main
// https://space.bilibili.com/206214
func bowlSubarrays1(nums []int) (ans int64) {
st := []int{}
for i, x := range nums {
for len(st) > 0 && nums[st[len(st)-1]] < x {
// j=st[len(st)-1] 右侧严格大于 nums[j] 的数的下标是 i
if i-st[len(st)-1] > 1 { // 子数组的长度至少为 3
ans++
}
st = st[:len(st)-1]
}
// i 左侧大于等于 nums[i] 的数的下标是 st[len(st)-1]
if len(st) > 0 && i-st[len(st)-1] > 1 { // 子数组的长度至少为 3
ans++
}
st = append(st, i)
}
return
}
func bowlSubarrays(nums []int) (ans int64) {
st := nums[:0]
for _, x := range nums {
for len(st) > 0 && st[len(st)-1] < x {
st = st[:len(st)-1]
if len(st) > 0 {
ans++
}
}
st = append(st, x)
}
return
}
# Accepted solution for LeetCode #3676: Count Bowl Subarrays
# Time: O(n)
# Space: O(n)
# mono stack
class Solution(object):
def bowlSubarrays(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
result = 0
stk = []
for i in xrange(len(nums)):
while stk and nums[stk[-1]] < nums[i]:
stk.pop()
if stk:
result += 1
stk.append(i)
return result
// Accepted solution for LeetCode #3676: Count Bowl Subarrays
// Rust example auto-generated from go reference.
// Replace the signature and local types with the exact LeetCode harness for this problem.
impl Solution {
pub fn rust_example() {
// Port the logic from the reference block below.
}
}
// Reference (go):
// // Accepted solution for LeetCode #3676: Count Bowl Subarrays
// package main
//
// // https://space.bilibili.com/206214
// func bowlSubarrays1(nums []int) (ans int64) {
// st := []int{}
// for i, x := range nums {
// for len(st) > 0 && nums[st[len(st)-1]] < x {
// // j=st[len(st)-1] 右侧严格大于 nums[j] 的数的下标是 i
// if i-st[len(st)-1] > 1 { // 子数组的长度至少为 3
// ans++
// }
// st = st[:len(st)-1]
// }
// // i 左侧大于等于 nums[i] 的数的下标是 st[len(st)-1]
// if len(st) > 0 && i-st[len(st)-1] > 1 { // 子数组的长度至少为 3
// ans++
// }
// st = append(st, i)
// }
// return
// }
//
// func bowlSubarrays(nums []int) (ans int64) {
// st := nums[:0]
// for _, x := range nums {
// for len(st) > 0 && st[len(st)-1] < x {
// st = st[:len(st)-1]
// if len(st) > 0 {
// ans++
// }
// }
// st = append(st, x)
// }
// return
// }
// Accepted solution for LeetCode #3676: Count Bowl Subarrays
// Auto-generated TypeScript example from go.
function exampleSolution(): void {
}
// Reference (go):
// // Accepted solution for LeetCode #3676: Count Bowl Subarrays
// package main
//
// // https://space.bilibili.com/206214
// func bowlSubarrays1(nums []int) (ans int64) {
// st := []int{}
// for i, x := range nums {
// for len(st) > 0 && nums[st[len(st)-1]] < x {
// // j=st[len(st)-1] 右侧严格大于 nums[j] 的数的下标是 i
// if i-st[len(st)-1] > 1 { // 子数组的长度至少为 3
// ans++
// }
// st = st[:len(st)-1]
// }
// // i 左侧大于等于 nums[i] 的数的下标是 st[len(st)-1]
// if len(st) > 0 && i-st[len(st)-1] > 1 { // 子数组的长度至少为 3
// ans++
// }
// st = append(st, i)
// }
// return
// }
//
// func bowlSubarrays(nums []int) (ans int64) {
// st := nums[:0]
// for _, x := range nums {
// for len(st) > 0 && st[len(st)-1] < x {
// st = st[:len(st)-1]
// if len(st) > 0 {
// ans++
// }
// }
// st = append(st, x)
// }
// return
// }
Use this to step through a reusable interview workflow for this problem.
For each element, scan left (or right) to find the next greater/smaller element. The inner scan can visit up to n elements per outer iteration, giving O(n²) total comparisons. No extra space needed beyond loop variables.
Each element is pushed onto the stack at most once and popped at most once, giving 2n total operations = O(n). The stack itself holds at most n elements in the worst case. The key insight: amortized O(1) per element despite the inner while-loop.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Wrong move: Pushing without popping stale elements invalidates next-greater/next-smaller logic.
Usually fails on: Indices point to blocked elements and outputs shift.
Fix: Pop while invariant is violated before pushing current element.