data_array

Stream Analyzer

question_mark

psychology_alt The Problem

"Reading an infinite stream of characters (e.g., G, X, A, C, X...), find the 2nd character that has not repeated so far."

Current Answer
—

Stream Controls

Manually add characters or generate a stream.

Input Stream

Count: 0
Waiting for input...

queue_music Non-Repeating List

Ordered by arrival time. Only chars with count == 1 are here.
Empty...

bar_chart Frequency Map

No data yet...
solution.js

class StreamAnalyzer {
  constructor() {
    // Stores frequency of each char
    this.counts = {}; 
    // Stores chars that appeared exactly once, in order
    this.nonRepeating = []; 
  }

  processChar(char) {
    // 1. Update frequency
    this.counts[char] = (this.counts[char] || 0) + 1;

    // 2. Manage the non-repeating list
    if (this.counts[char] === 1) {
      // First appearance: Add to list
      this.nonRepeating.push(char);
    } else {
      // Repeated: Remove from unique list if present
      // (Note: using .filter is O(N), Linked List is O(1))
      this.nonRepeating = this.nonRepeating
        .filter(c => c !== char);
    }
  }

  getKthNonRepeating(k) {
    // k is 1-based index
    if (k > this.nonRepeating.length) {
       return null;
    }
    return this.nonRepeating[k - 1];
  }
}

How it works

To solve this efficiently, we need to maintain two pieces of information as the stream flows in:

  • Counts (Hash Map): Tracks how many times we've seen every character. This allows O(1) lookups to check if a character is new or a repeat.
  • Order (List/Queue): Maintains the sequence of characters that are currently unique.
Optimization Note: In the code above, we use a simple JavaScript Array and .filter() to remove repeating characters. This is O(N) where N is the number of unique characters. For a massive production system, you would use a Doubly Linked List combined with a HashMap pointing to the list nodes. This would allow O(1) removal of nodes when a character repeats.