Facebook Pixel

1550. Three Consecutive Odds

Problem Description

You are given an integer array arr. Your task is to determine whether the array contains three consecutive odd numbers.

The problem asks you to check if there exists any position in the array where three odd numbers appear one after another. If such a sequence exists, return true. Otherwise, return false.

For example:

  • If arr = [2, 6, 4, 1], the answer would be false because there are no three consecutive odd numbers
  • If arr = [1, 2, 34, 3, 4, 5, 7, 23, 12], the answer would be true because the numbers 5, 7, 23 at indices 5, 6, and 7 are three consecutive odd numbers

The solution uses a counter approach where it tracks how many consecutive odd numbers have been encountered. When iterating through the array:

  • If the current number is odd (checked using x & 1), increment the counter
  • If the counter reaches 3, we've found three consecutive odd numbers
  • If the current number is even, reset the counter to 0 since the consecutive sequence is broken
Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

The key insight is that we need to track consecutive odd numbers as we traverse the array. Think of it like keeping a running streak - every time we encounter an odd number, our streak continues and grows. But the moment we hit an even number, the streak breaks and we must start counting from zero again.

Why does this work? Because "consecutive" means the odd numbers must appear right next to each other in the array. If there's even a single even number between them, they're no longer consecutive.

We can check if a number is odd using the bitwise AND operation x & 1. This works because odd numbers always have their least significant bit set to 1 in binary representation, while even numbers have it set to 0. So x & 1 returns 1 for odd numbers and 0 for even numbers.

The counting approach emerges naturally from this observation:

  • Start with a counter at 0
  • Each odd number increments our counter (building the streak)
  • Each even number resets our counter to 0 (breaking the streak)
  • As soon as our counter reaches 3, we know we've found three consecutive odd numbers

This gives us a single-pass solution with O(n) time complexity and O(1) space complexity, as we only need to maintain one counter variable while iterating through the array once.

Solution Approach

We implement the solution using iteration and counting. The approach uses a single variable cnt to track the current count of consecutive odd numbers as we traverse through the array.

Here's how the implementation works step by step:

  1. Initialize the counter: Start with cnt = 0 to track consecutive odd numbers.

  2. Iterate through the array: Process each element x in the array one by one.

  3. Check if the current number is odd: Use the bitwise AND operation x & 1:

    • If x & 1 evaluates to 1 (truthy), the number is odd
    • If x & 1 evaluates to 0 (falsy), the number is even
  4. Update the counter based on parity:

    • If odd: Increment cnt by 1 (cnt += 1)
      • After incrementing, check if cnt == 3
      • If yes, we've found three consecutive odd numbers, so return True
    • If even: Reset cnt to 0 since the consecutive sequence is broken
  5. Final check: If we complete the iteration without finding three consecutive odd numbers, return False.

The algorithm processes each element exactly once, making it efficient with O(n) time complexity where n is the length of the array. The space complexity is O(1) since we only use a single counter variable regardless of the input size.

This pattern of maintaining a counter that resets on certain conditions is common in problems involving consecutive elements or streaks in arrays.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's trace through the algorithm with the array arr = [1, 2, 34, 3, 4, 5, 7, 23, 12].

We'll track our counter cnt as we process each element:

Initial state: cnt = 0

Step 1: Process arr[0] = 1

  • Check: 1 & 1 = 1 (odd number)
  • Action: Increment cnt to 1
  • Check if cnt == 3? No, continue

Step 2: Process arr[1] = 2

  • Check: 2 & 1 = 0 (even number)
  • Action: Reset cnt to 0

Step 3: Process arr[2] = 34

  • Check: 34 & 1 = 0 (even number)
  • Action: Reset cnt to 0 (already 0)

Step 4: Process arr[3] = 3

  • Check: 3 & 1 = 1 (odd number)
  • Action: Increment cnt to 1
  • Check if cnt == 3? No, continue

Step 5: Process arr[4] = 4

  • Check: 4 & 1 = 0 (even number)
  • Action: Reset cnt to 0

Step 6: Process arr[5] = 5

  • Check: 5 & 1 = 1 (odd number)
  • Action: Increment cnt to 1
  • Check if cnt == 3? No, continue

Step 7: Process arr[6] = 7

  • Check: 7 & 1 = 1 (odd number)
  • Action: Increment cnt to 2
  • Check if cnt == 3? No, continue

Step 8: Process arr[7] = 23

  • Check: 23 & 1 = 1 (odd number)
  • Action: Increment cnt to 3
  • Check if cnt == 3? Yes! Return True

We found three consecutive odd numbers (5, 7, 23) at indices 5, 6, and 7, so the function returns True.

Solution Implementation

1class Solution:
2    def threeConsecutiveOdds(self, arr: List[int]) -> bool:
3        """
4        Check if there exist three consecutive odd numbers in the array.
5      
6        Args:
7            arr: List of integers to check
8          
9        Returns:
10            True if three consecutive odd numbers exist, False otherwise
11        """
12        # Counter to track consecutive odd numbers
13        consecutive_odd_count = 0
14      
15        # Iterate through each element in the array
16        for number in arr:
17            # Check if the current number is odd using bitwise AND
18            # (odd numbers have LSB = 1, even numbers have LSB = 0)
19            if number & 1:
20                # Increment counter for consecutive odd numbers
21                consecutive_odd_count += 1
22              
23                # If we found 3 consecutive odd numbers, return True
24                if consecutive_odd_count == 3:
25                    return True
26            else:
27                # Reset counter when we encounter an even number
28                consecutive_odd_count = 0
29      
30        # No three consecutive odd numbers found
31        return False
32
1class Solution {
2    /**
3     * Checks if there are three consecutive odd numbers in the array.
4     * 
5     * @param arr The input integer array
6     * @return true if three consecutive odd numbers exist, false otherwise
7     */
8    public boolean threeConsecutiveOdds(int[] arr) {
9        // Counter to track consecutive odd numbers
10        int consecutiveOddCount = 0;
11      
12        // Iterate through each element in the array
13        for (int currentNumber : arr) {
14            // Check if the current number is odd
15            if (currentNumber % 2 == 1) {
16                // Increment the consecutive odd counter
17                consecutiveOddCount++;
18              
19                // If we've found 3 consecutive odds, return true
20                if (consecutiveOddCount == 3) {
21                    return true;
22                }
23            } else {
24                // Reset counter when an even number is encountered
25                consecutiveOddCount = 0;
26            }
27        }
28      
29        // No three consecutive odd numbers found
30        return false;
31    }
32}
33
1class Solution {
2public:
3    bool threeConsecutiveOdds(vector<int>& arr) {
4        // Counter to track consecutive odd numbers
5        int consecutiveOddCount = 0;
6      
7        // Iterate through each element in the array
8        for (int num : arr) {
9            // Check if current number is odd using bitwise AND
10            if (num & 1) {
11                // Increment counter for odd numbers
12                consecutiveOddCount++;
13              
14                // Check if we found three consecutive odds
15                if (consecutiveOddCount == 3) {
16                    return true;
17                }
18            } else {
19                // Reset counter when an even number is encountered
20                consecutiveOddCount = 0;
21            }
22        }
23      
24        // No three consecutive odd numbers found
25        return false;
26    }
27};
28
1/**
2 * Checks if there are three consecutive odd numbers in the array
3 * @param arr - The input array of numbers
4 * @returns true if there are three consecutive odd numbers, false otherwise
5 */
6function threeConsecutiveOdds(arr: number[]): boolean {
7    // Counter to track consecutive odd numbers
8    let consecutiveOddCount: number = 0;
9  
10    // Iterate through each element in the array
11    for (const currentNumber of arr) {
12        // Check if the current number is odd using bitwise AND operation
13        // (odd numbers have their least significant bit set to 1)
14        if (currentNumber & 1) {
15            // Increment the counter for consecutive odd numbers
16            consecutiveOddCount++;
17          
18            // If we've found 3 consecutive odd numbers, return true
19            if (consecutiveOddCount === 3) {
20                return true;
21            }
22        } else {
23            // Reset the counter if we encounter an even number
24            consecutiveOddCount = 0;
25        }
26    }
27  
28    // No three consecutive odd numbers found
29    return false;
30}
31

Time and Space Complexity

The time complexity is O(n), where n is the length of the array arr. The algorithm iterates through the array exactly once, checking each element to determine if it's odd (using the bitwise AND operation x & 1) and maintaining a counter. Each operation within the loop takes constant time O(1), so the overall time complexity is linear with respect to the input size.

The space complexity is O(1). The algorithm only uses a single integer variable cnt to keep track of consecutive odd numbers, regardless of the input array size. No additional data structures are created that scale with the input, making the space usage constant.

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Incorrectly checking for odd numbers

A common mistake is using the wrong condition to check if a number is odd. Some developers might write:

  • if number % 2 == 1 - This fails for negative odd numbers (e.g., -3 % 2 returns -1 in Python, not 1)
  • if number / 2 != number // 2 - This uses floating-point division which can be inefficient

Solution: Use either number & 1 (bitwise AND) or number % 2 != 0 which work correctly for both positive and negative numbers.

2. Not resetting the counter properly

Developers might forget to reset the counter when encountering an even number, leading to incorrect counting of non-consecutive odd numbers:

# Incorrect - counts any three odd numbers, not consecutive ones
count = 0
for num in arr:
    if num & 1:
        count += 1
    if count == 3:
        return True
return False

Solution: Always reset the counter to 0 when an even number is encountered to ensure we're only counting consecutive odd numbers.

3. Off-by-one errors in counter logic

Some might check for the wrong count value or increment at the wrong time:

# Incorrect - returns True after finding only 2 consecutive odds
if consecutive_odd_count >= 2:
    return True

Solution: Ensure the counter is checked against exactly 3, and the check happens after incrementing.

4. Using sliding window when not needed

Overcomplicating with a sliding window approach:

# Unnecessarily complex
for i in range(len(arr) - 2):
    if arr[i] & 1 and arr[i+1] & 1 and arr[i+2] & 1:
        return True

While this works, it requires boundary checking and is less elegant.

Solution: The simple counter approach is cleaner and handles all edge cases naturally without explicit boundary checks.

Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

What's the output of running the following function using input [30, 20, 10, 100, 33, 12]?

1def fun(arr: List[int]) -> List[int]:
2    import heapq
3    heapq.heapify(arr)
4    res = []
5    for i in range(3):
6        res.append(heapq.heappop(arr))
7    return res
8
1public static int[] fun(int[] arr) {
2    int[] res = new int[3];
3    PriorityQueue<Integer> heap = new PriorityQueue<>();
4    for (int i = 0; i < arr.length; i++) {
5        heap.add(arr[i]);
6    }
7    for (int i = 0; i < 3; i++) {
8        res[i] = heap.poll();
9    }
10    return res;
11}
12
1class HeapItem {
2    constructor(item, priority = item) {
3        this.item = item;
4        this.priority = priority;
5    }
6}
7
8class MinHeap {
9    constructor() {
10        this.heap = [];
11    }
12
13    push(node) {
14        // insert the new node at the end of the heap array
15        this.heap.push(node);
16        // find the correct position for the new node
17        this.bubble_up();
18    }
19
20    bubble_up() {
21        let index = this.heap.length - 1;
22
23        while (index > 0) {
24            const element = this.heap[index];
25            const parentIndex = Math.floor((index - 1) / 2);
26            const parent = this.heap[parentIndex];
27
28            if (parent.priority <= element.priority) break;
29            // if the parent is bigger than the child then swap the parent and child
30            this.heap[index] = parent;
31            this.heap[parentIndex] = element;
32            index = parentIndex;
33        }
34    }
35
36    pop() {
37        const min = this.heap[0];
38        this.heap[0] = this.heap[this.size() - 1];
39        this.heap.pop();
40        this.bubble_down();
41        return min;
42    }
43
44    bubble_down() {
45        let index = 0;
46        let min = index;
47        const n = this.heap.length;
48
49        while (index < n) {
50            const left = 2 * index + 1;
51            const right = left + 1;
52
53            if (left < n && this.heap[left].priority < this.heap[min].priority) {
54                min = left;
55            }
56            if (right < n && this.heap[right].priority < this.heap[min].priority) {
57                min = right;
58            }
59            if (min === index) break;
60            [this.heap[min], this.heap[index]] = [this.heap[index], this.heap[min]];
61            index = min;
62        }
63    }
64
65    peek() {
66        return this.heap[0];
67    }
68
69    size() {
70        return this.heap.length;
71    }
72}
73
74function fun(arr) {
75    const heap = new MinHeap();
76    for (const x of arr) {
77        heap.push(new HeapItem(x));
78    }
79    const res = [];
80    for (let i = 0; i < 3; i++) {
81        res.push(heap.pop().item);
82    }
83    return res;
84}
85

Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More