BackmediumArraysMicrosoft

Galactic Signal Patterns Solution

Problem Statement

Given an integer array nums, determine the maximum possible length of a subsequence whose consecutive elements strictly alternate between a rise and a fall. Formally, for a subsequence a1,a2,…,ak (k≥2) either a1<a2>a3<… or a1>a2<a3>…. The first relation may be either increase or decrease. Elements may be removed but the original order must be preserved. Return the length of the longest such subsequence; if no alternating pair exists, the answer is 1 (any single element).

Example 1
Input
[1,5,4]
Output
3

Explanation: 1<5 creates an increase, 5>4 creates a decrease, so the whole array forms a valid alternating subsequence of length 3.

Example 2
Input
[10,20,30,40]
Output
2

Explanation: All numbers are strictly increasing, therefore any two adjacent elements form the longest alternating subsequence; length 2.

Example 3
Input
[3,3,3,2,5,1,7]
Output
5

Explanation: Ignore the equal leading 3s. Choose 3>2<5>1<7 which alternates rise‑fall‑rise‑fall, giving length 5.

Constraints

  • 1 <= nums.length <= 100000
  • -1000000000 <= nums[i] <= 1000000000
  • Time complexity O(n) required
  • Space complexity O(1) or O(n) acceptable
Live Compiler1 Free Run Available
Loading Editor...
Test Cases & Output
Click "Run" to test your 1 free compile trial!

🚀 Practice this problem

Run code, get AI hints & track streak

Sign Up Free

Galactic Signal Patterns — Problem Statement & Solution Guide

ArraysMediumIdentifying patterns in arrays
TimeO(n)
|
SpaceO(1)

Problem Description

Given an integer array nums, determine the maximum possible length of a subsequence whose consecutive elements strictly alternate between a rise and a fall. Formally, for a subsequence a1,a2,…,ak (k≥2) either a1<a2>a3<… or a1>a2<a3>…. The first relation may be either increase or decrease. Elements may be removed but the original order must be preserved. Return the length of the longest such subsequence; if no alternating pair exists, the answer is 1 (any single element).

DSA Pattern Breakdown

DSA Pattern Breakdown

"Galactic Signal Patterns"

medium

WHY DOES IT MATTER?

Alternating patterns appear in signal processing, stock price analysis, and load‑balancing spikes; mastering wiggle logic equips engineers to detect and react to volatility efficiently.

OPTIMIZATION CHALLENGE

Realizing that only the sign of the most recent difference influences future choices collapses a quadratic DP into two scalar variables, cutting both time and memory dramatically.

REAL-WORLD CONNECTION

Think of a distributed system where request latency alternates between high and low due to load bursts; the longest alternating latency pattern helps predict when the system will swing back to a stable state.

During an interview, compute up and down on the fly, ignore equal adjacent values, and return 1 + number of sign changes – a one‑pass solution that impresses with its simplicity.

COMPLEXITY AT A GLANCE

⏱ Time:O(n)
💾 Space:O(1)

Core Theory — Why This Approach?

The problem asks for the longest subsequence that alternates strictly between increasing and decreasing – commonly known as the wiggle subsequence. A naive DP that examines every pair of indices leads to O(n^2) time because for each element you would need to consider extending all previously computed alternating sequences, which quickly becomes infeasible for n up to 10^5 or more. The optimal paradigm leverages the observation that only the sign of the last difference matters: if the last step was an upward move, the next step must be downward, and vice‑versa. By maintaining two counters – up[i] (length of longest wiggle ending at i with a rise) and down[i] (ending with a fall) – we can update them in O(1) per element, collapsing the DP to a linear greedy scan. This reduces both time and space to O(n) and O(1) respectively, because the counters depend solely on the previous element’s direction, not the whole history.

Interview Questions on This Problem

Q1How would you modify the wiggle subsequence algorithm to also return one possible longest subsequence, not just its length?

Track predecessor indices for up and down states while scanning; after the scan, backtrack from the state (up or down) that gave the maximum length, reconstructing the subsequence in reverse.

Q2Can the wiggle subsequence problem be solved using a segment tree or BIT for faster queries on arbitrary sub‑arrays?

Yes, by storing for each position the best up/down lengths in a segment tree keyed by value, you can answer range‑restricted wiggle queries in O(log n), but the plain global version remains O(n) with the greedy method.

Q3Why does the greedy approach work for this problem while many other longest‑subsequence problems require DP?

Because the optimal substructure depends only on the last direction, not on the exact values; any longer wiggle that ends with the same direction can be replaced by the one with the larger length without affecting future extensions, guaranteeing greedy optimality.

Examples

Example 1

Input

[1,5,4]

Output

3

Explanation: 1<5 creates an increase, 5>4 creates a decrease, so the whole array forms a valid alternating subsequence of length 3.

Example 2

Input

[10,20,30,40]

Output

2

Explanation: All numbers are strictly increasing, therefore any two adjacent elements form the longest alternating subsequence; length 2.

Example 3

Input

[3,3,3,2,5,1,7]

Output

5

Explanation: Ignore the equal leading 3s. Choose 3>2<5>1<7 which alternates rise‑fall‑rise‑fall, giving length 5.

Constraints

  • 1 <= nums.length <= 100000
  • -1000000000 <= nums[i] <= 1000000000
  • Time complexity O(n) required
  • Space complexity O(1) or O(n) acceptable

Optimal Approach & Strategy

Maintain two length counters (up and down) while scanning; update them based on the sign of the current difference, yielding O(n) time and O(1) space.

Brute Force Approach

Try every possible subsequence, checking if it alternates, and keep the maximum length – exponential time.

Verified Code Solutions

JavaScript Solution
Time: O(n)
const fs = require('fs');
const data = fs.readFileSync(0,'utf8').trim().split(/\s+/).map(Number);
let idx = 0;
const n = data[idx++] || 0;
const nums = data.slice(idx, idx + n);
function longestAlternatingSubsequence(nums) {
    if(nums.length===0) return 0;
    let up = 1, down = 1;
    for(let i=1;i<nums.length;i++){
        if(nums[i] > nums[i-1]) up = down + 1;
        else if(nums[i] < nums[i-1]) down = up + 1;
    }
    return Math.max(up, down);
}
console.log(longestAlternatingSubsequence(nums));

Asked in Top Tech Interviews

Microsoft

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.