Longest Consecutive Temperature Trend — Problem Statement & Solution Guide

ArraysMediumMixed
TimeO(n·m·log n)
|
SpaceO(m·n)

Quick Answer & Algorithm Key Takeaway

Master coding challenges related to Arrays and solve the Longest Consecutive Temperature Trend problem optimally.

TopicArrays
PatternMixed
TimeO(n·m·log n)
SpaceO(m·n)

Problem Description

Given an integer array temperatures and a pattern string pattern composed only of the characters ‘A’ (for a strictly increasing step) and ‘D’ (for a strictly decreasing step), determine the maximum possible length of a subsequence of temperatures such that for every pair of consecutive elements in the subsequence the relation (increase or decrease) matches the corresponding character of pattern in a cyclic manner. Formally, if the chosen subsequence is b₀,b₁,…,bₖ₋₁, then for each i (0 ≤ i < k‑1) we require: • pattern[i % m] = ‘A’ ⇒ bᵢ < bᵢ₊₁ • pattern[i % m] = ‘D’ ⇒ bᵢ > bᵢ₊₁ where m is the length of pattern. Return the greatest possible k. The subsequence need not be contiguous, but the original order of elements must be preserved.

DSA Pattern Breakdown

DSA Pattern Breakdown

"Longest Consecutive Temperature Trend"

medium

WHY DOES IT MATTER?

The alternating increase/decrease pattern captures many real‑world signal analyses (e.g., stock price swings, temperature cycles) and tests a candidate’s ability to blend classic LIS techniques with modular state handling, a skill frequently required in performance‑critical code paths.

OPTIMIZATION CHALLENGE

The key insight is to replace the O(n) scan for the best predecessor with a range‑maximum query over the compressed value space, turning the quadratic DP into logarithmic time per element by exploiting the monotonic nature of ‘A’ and ‘D’ relations.

REAL-WORLD CONNECTION

Think of a distributed monitoring system that must trigger alerts only when metrics follow a predefined up‑down rhythm—detecting such patterns efficiently is analogous to the algorithm, where each node maintains a summary (Fenwick tree) of recent observations to decide quickly whether the rhythm continues.

When coding, first compress temperatures, then allocate an array of Fenwick trees sized m; update the tree for the current pattern index after computing its DP value, and always query the tree of the previous index using the appropriate direction (less‑than for ‘A’, greater‑than for ‘D’).

COMPLEXITY AT A GLANCE

⏱ Time:O(n·m·log n)
💾 Space:O(m·n)

Core Theory — Why This Approach?

The problem is a constrained longest subsequence variant where each adjacent pair must obey a prescribed increase ('A') or decrease ('D') direction given by a cyclic pattern. A naïve solution enumerates every subsequence, leading to exponential time, or uses O(n²) DP that checks all previous elements for each position and pattern index, which quickly blows up for n up to 10⁵. The optimal paradigm treats each pattern position as an independent state and transforms the DP recurrence into range‑maximum queries over the value domain. By compressing temperature values and maintaining a Fenwick (or segment) tree per pattern index, we can retrieve the best subsequence length that ends with a smaller value for an 'A' step or a larger value for a 'D' step in O(log n) time. This reduces the overall complexity to O(n·m·log n) where m=|pattern|, and with small m it is effectively O(n log n).

Interview Questions on This Problem

Q1How would you modify the solution if the pattern string could contain a wildcard '?' that matches either increase or decrease?

Treat '?' as both possibilities: during DP update, query both the ‘A’‑tree (max over smaller values) and the ‘D’‑tree (max over larger values) for the same pattern index, take the larger result, and update both trees for the next index accordingly.

Q2What is the time‑space trade‑off when you replace Fenwick trees with a balanced BST for each pattern state?

A BST offers O(log n) queries and updates like a Fenwick tree but incurs higher constant factors and extra pointer overhead; however it can handle dynamic value ranges without compression, at the cost of O(m·n) memory for node objects versus O(m·n) compressed arrays in the BIT approach.

Q3Explain how you would extend the algorithm to handle a pattern that is not cyclic but must be matched exactly once in the subsequence (i.e., pattern length ≤ subsequence length‑1).

Create DP states for each pattern position without wrapping; when the last pattern character is used, further extensions are prohibited, so the answer is the maximum DP value among states that have consumed the entire pattern. The same BIT technique applies, but you stop updates after the final index.

Examples

Example 1

Input

6
10 20 15 25 20 30
AD

Output

6

Explanation: Select the whole array as the subsequence: 10→20 (A), 20→15 (D), 15→25 (A), 25→20 (D), 20→30 (A). All five adjacent relations follow the cyclic pattern ADAD…, giving a subsequence length of 6.

Example 2

Input

5
5 4 3 2 1
A

Output

1

Explanation: Pattern ‘A’ demands every step to be strictly increasing. The array is strictly decreasing, so no two elements can satisfy the condition. Any single element forms a valid subsequence of length 1, which is maximal.

Example 3

Input

7
1 3 2 4 3 5 4
ADA

Output

4

Explanation: One optimal subsequence is 1, 3, 2, 4. Relations: 1→3 (A), 3→2 (D), 2→4 (A) – exactly matching the first three characters of the pattern. Adding any later element would require the next relation to be ‘D’ (pattern repeats), but the remaining numbers are larger, breaking the rule. Hence the maximum length is 4.

Constraints

  • 1 <= temperatures.length <= 100000
  • -10^9 <= temperatures[i] <= 10^9
  • 1 <= pattern.length <= 10
  • pattern consists only of characters 'A' and 'D'

Optimal Approach & Strategy

Use DP with a Fenwick tree per pattern index to answer “best length ending with a smaller/larger value” in logarithmic time, achieving O(n log n).

Brute Force Approach

Enumerate every subsequence, check if it respects the pattern, and keep the longest – exponential time.

Code Solutions

JavaScript Solution
Time: O(n·m·log n)
const fs = require('fs');
const input = fs.readFileSync(0,'utf8').trim().split(/\s+/);
let idx=0;
function longestConsecutiveTemperatureTrend(temps, pattern){
    const n = temps.length;
    const m = pattern.length;
    if(n===0) return 0;
    // dp[i][k] = longest length ending at i where next expected pattern index is k
    const dp = Array.from({length:n},()=>Array(m).fill(1));
    let ans = 1;
    for(let i=0;i<n;i++){
        for(let j=0;j<i;j++){
            let rel = 0;
            if(temps[i] > temps[j]) rel = 'A';
            else if(temps[i] < temps[j]) rel = 'D';
            else continue;
            for(let k=0;k<m;k++){
                if(rel===pattern[k]){
                    const next = (k+1)%m;
                    dp[i][next] = Math.max(dp[i][next], dp[j][k]+1);
                    ans = Math.max(ans, dp[i][next]);
                }
            }
        }
    }
    return ans;
}
let n = parseInt(input[idx++]);
let temps = [];
for(let i=0;i<n;i++) temps.push(parseInt(input[idx++]));
let pattern = input[idx++] || '';
console.log(longestConsecutiveTemperatureTrend(temps, pattern).toString());

Asked in Top Tech Interviews

Uber

Solve in Interative Editor

Ready to test your code? Open our built-in compiler, run custom test suites, and see detailed complexity analysis reports instantly.