← Back to all recaps

Microsoft OA Real Question Review: Maximum Score Game + Minimum Operations

3 min read

Microsoft OA Question 1

Question 1: Maximum Score Game

Problem Description

A game is played with the following rules:

  • A player starts at cell 0 with a score of 0
  • There are n cells numbered from 0 to n-1, each with an assigned value
  • Cell 0 always has a value of 0
  • In each move, the player can either:
    • Move 1 cell to the right, or
    • Move p cells to the right, where p is a prime number ending in 3 (such as 3, 13, 23, 43, etc.)
  • The player cannot move beyond the last cell
  • When the player lands on a cell, its value is added to the total score
  • The game ends when the player reaches cell n-1

Determine: The maximum possible score to reach the final cell

Solution Approach

Step 1: Preprocess Prime Numbers

First, find all prime numbers ending in 3 that don't exceed n. These primes are: 3, 13, 23, 43, 53, 73, 83, etc.

def get_primes_ending_with_3(max_n):
    """Get all primes <= max_n with last digit 3"""
    primes = []
    
    def is_prime(num):
        if num < 2:
            return False
        if num == 2:
            return True
        if num % 2 == 0:
            return False
        for i in range(3, int(num**0.5) + 1, 2):
            if num % i == 0:
                return False
        return True
    
    for num in range(3, max_n, 10):  # Numbers ending in 3: 3, 13, 23, 33...
        if is_prime(num):
            primes.append(num)
    
    return primes

Step 2: Dynamic Programming Solution

Use a DP array where dp[i] represents the maximum score to reach cell i.

Key Idea:

  • Initialize: dp[0] = 0 (starting point), other positions to negative infinity (unreachable)
  • State transition: For each reachable position i, try all possible moves
    • Move 1 step to i+1
    • Move p steps to i+p (p is a prime ending in 3)
  • Update target positions with the maximum value
def max_score_game(cells, n):
    """
    Calculate maximum cumulative score
    
    Args:
        cells: Array of cell values
        n: Total number of cells
    
    Returns:
        Maximum score to reach the final cell
    """
    # Preprocess primes
    primes = get_primes_ending_with_3(n)
    
    # DP initialization
    dp = [-float('inf')] * n
    dp[0] = cells[0]  # Starting cell value is 0
    
    # State transition
    for i in range(n):
        if dp[i] == -float('inf'):
            continue  # Skip unreachable positions
        
        # Try moving 1 step
        if i + 1 < n:
            dp[i + 1] = max(dp[i + 1], dp[i] + cells[i + 1])
        
        # Try moving p steps (p is a prime ending in 3)
        for p in primes:
            if i + p < n:
                dp[i + p] = max(dp[i + p], dp[i] + cells[i + p])
            else:
                break  # Subsequent primes are larger, no need to continue
    
    return dp[n - 1]

Step 3: Example Walkthrough

Given: cells = [0, -10, -20, -30, 50], n = 5

  • Start: dp[0] = 0
  • From 0:
    • Move 1 step to 1: dp[1] = 0 + (-10) = -10
    • Move 3 steps to 3: dp[3] = 0 + (-30) = -30
  • From 1 (dp[1] = -10):
    • Move 1 step to 2: dp[2] = -10 + (-20) = -30
    • Move 3 steps to 4: dp[4] = -10 + 50 = 40 ✓
  • From 2 (dp[2] = -30):
    • Move 1 step to 3: dp[3] = max(-30, -30 + (-30)) = -30
    • Move 3 steps to 5: Out of bounds
  • From 3 (dp[3] = -30):
    • Move 1 step to 4: dp[4] = max(40, -30 + 50) = 40

Final Answer: 40

Time Complexity Analysis

  • Preprocess primes: O(n log log n) (Sieve method)
  • DP traversal: O(n × k), where k is the count of primes ending in 3 (usually small)
  • Total: O(n log log n)

Common Pitfalls

Pitfall 1: Forgetting to initialize unreachable positions to negative infinity ✅ Solution: Clearly distinguish between reachable and unreachable states

Pitfall 2: Incomplete prime preprocessing, missing some primes ✅ Solution: Use sieve method or verify each number to ensure all primes ending in 3 are found

Pitfall 3: Not handling negative cell values correctly ✅ Solution: Initialize DP to negative infinity and handle all values properly


Question 2: Minimum Operations

Microsoft OA Question 2

Problem Description

Given a positive integer n, in each operation you can either:

  • Add 2^i (i ≥ 0), or
  • Subtract 2^i (i ≥ 0)

Determine: The minimum number of operations required to reduce n to 0

Solution Approach

Core Observation: Binary Greedy

The key to this problem is observing the binary representation of n and utilizing the properties of binary carries.

Key Rules:

  • If the current bit is 0, shift right directly (equivalent to dividing by 2)
  • If the current bit is 1, eliminate it by adding or subtracting

Detailed Algorithm

def min_operations(n):
    """
    Calculate minimum operations to reduce n to 0
    
    Args:
        n: Positive integer
    
    Returns:
        Minimum number of operations
    """
    operations = 0
    
    while n > 0:
        # Observe the last two binary digits of n
        last_two_bits = n & 3  # Get last two bits: n % 4
        
        if last_two_bits == 0:
            # 00: Shift right directly
            n >>= 1
        elif last_two_bits == 1:
            # 01: Subtract 1 (becomes 00), then shift right
            n -= 1
            operations += 1
        elif last_two_bits == 2:
            # 10: Shift right directly
            n >>= 1
        else:  # last_two_bits == 3
            # 11: Add 1 (carry over to become 100), then shift right
            n += 1
            operations += 1
        
        operations += 1  # Count the shift operation
    
    return operations

Algorithm Explanation

Why does this work?

Observe the last two binary digits:

  1. 00: Last bit is 0, shift right directly
  2. 01: Last bit is 1, subtract 1 to make it 00, then shift right
  3. 10: Last bit is 0, shift right directly
  4. 11: Both last two bits are 1, adding 1 causes a carry (becomes 100), then shift right

Benefits of this approach:

  • Each operation eliminates at least one bit
  • Carries can merge multiple 1s
  • Greedy strategy guarantees optimality

Example Walkthrough

For n = 5:

n = 5 = 101₂

Step 1: Last two bits are 01
  - Subtract 1: 5 - 1 = 4 = 100₂ (operation 1)
  - Shift right: 4 >> 1 = 2 = 10₂ (operation 2)

Step 2: Last two bits are 10
  - Shift right: 2 >> 1 = 1 = 1₂ (operation 3)

Step 3: Last two bits are 01
  - Subtract 1: 1 - 1 = 0 (operation 4)
  - Shift right: 0 >> 1 = 0 (operation 5)

Total operations: 5

Verification: 5 → 4 → 2 → 1 → 0
            (sub 1) (÷2) (÷2) (sub 1)

Wait, let me reconsider. The problem asks for operations where each operation is adding or subtracting a power of 2.

Reconsidering the Problem

Actually, we need to reconsider: each operation is adding or subtracting a power of 2, and we want the minimum number of such operations.

This is equivalent to representing n using the minimum number of powers of 2.

For example:

  • n = 5 = 4 + 1 = 2² + 2⁰ (2 operations)
  • n = 5 = 8 - 3 = 8 - 2 - 1 = 2³ - 2¹ - 2⁰ (3 operations)

So the optimal is 2 operations.

Improved Algorithm

def min_operations_v2(n):
    """
    Calculate minimum operations to reduce n to 0 (improved version)
    
    Uses the count of 1s in binary representation as the base
    """
    operations = 0
    
    while n > 0:
        last_two_bits = n & 3
        
        if last_two_bits == 0:
            # 00: Shift right
            n >>= 1
        elif last_two_bits == 1:
            # 01: Subtract 1
            n -= 1
            operations += 1
        elif last_two_bits == 2:
            # 10: Shift right
            n >>= 1
        else:  # last_two_bits == 3
            # 11: Add 1 (carry)
            n += 1
            operations += 1
    
    return operations

For n = 5:

5 = 101₂
Last two bits are 01 → Subtract 1 → 4 = 100₂ (operation 1)
Last two bits are 00 → Shift right → 2 = 10₂
Last two bits are 10 → Shift right → 1 = 1₂
Last two bits are 01 → Subtract 1 → 0 (operation 2)

Total operations: 2 ✓

Time Complexity Analysis

  • Loop iterations: O(log n) (at least one bit is eliminated each time)
  • Each iteration: O(1)
  • Total: O(log n)

Common Pitfalls

Pitfall 1: Confusing "operations" with "shift operations" ✅ Solution: Only additions and subtractions count as operations; shifts are free

Pitfall 2: Not utilizing the carry property ✅ Solution: When the last two bits are 11, adding 1 creates a carry that can merge multiple 1s

Pitfall 3: Incorrect greedy strategy ✅ Solution: Observe the last two bits and follow the rules


Interview Strategy

Time Management

Question 1 (Maximum Score Game):

  • Understand problem: 3-5 minutes
  • Design algorithm: 5-7 minutes
  • Code implementation: 10-15 minutes
  • Test and verify: 5 minutes
  • Total: 25-35 minutes

Question 2 (Minimum Operations):

  • Understand problem: 2-3 minutes
  • Analyze binary patterns: 5-8 minutes
  • Code implementation: 8-10 minutes
  • Test and verify: 3-5 minutes
  • Total: 18-26 minutes

On-Site Tips

  1. Question 1:

    • Confirm the definition of primes (ending in 3)
    • Clarify boundary conditions (cannot exceed n-1)
    • Start with simple examples to derive the solution
  2. Question 2:

    • Use several examples to find patterns
    • Observe binary representations
    • Explain why adding or subtracting 1 is optimal

Common Questions

Q: Will the algorithm work if n is very large (close to 2^60)?

A: Yes. Question 2 has O(log n) time complexity, so even n = 2^60 requires only about 60 iterations. Question 1 requires preprocessing primes, but the density of primes ending in 3 is sufficient and won't be a bottleneck.

Q: What if all cell values in Question 1 are negative?

A: You still need to reach the final cell, so choose the path with the smallest total loss. The DP algorithm handles this automatically.

Q: Is there an alternative approach to Question 2?

A: Yes. Question 2 is essentially finding the minimum number of powers of 2 to represent n. You could also use BFS or memoized search, but binary greedy is optimal.


Complete Code Implementation

def get_primes_ending_with_3(max_n):
    """Get all primes <= max_n with last digit 3"""
    primes = []
    
    def is_prime(num):
        if num < 2:
            return False
        if num == 2:
            return True
        if num % 2 == 0:
            return False
        for i in range(3, int(num**0.5) + 1, 2):
            if num % i == 0:
                return False
        return True
    
    for num in range(3, max_n, 10):
        if is_prime(num):
            primes.append(num)
    
    return primes


def max_score_game(cells):
    """Calculate maximum cumulative score"""
    n = len(cells)
    primes = get_primes_ending_with_3(n)
    
    dp = [-float('inf')] * n
    dp[0] = cells[0]
    
    for i in range(n):
        if dp[i] == -float('inf'):
            continue
        
        # Move 1 step
        if i + 1 < n:
            dp[i + 1] = max(dp[i + 1], dp[i] + cells[i + 1])
        
        # Move p steps
        for p in primes:
            if i + p < n:
                dp[i + p] = max(dp[i + p], dp[i] + cells[i + p])
            else:
                break
    
    return dp[n - 1]


def min_operations(n):
    """Calculate minimum operations to reduce n to 0"""
    operations = 0
    
    while n > 0:
        last_two_bits = n & 3
        
        if last_two_bits == 0:
            n >>= 1
        elif last_two_bits == 1:
            n -= 1
            operations += 1
        elif last_two_bits == 2:
            n >>= 1
        else:  # last_two_bits == 3
            n += 1
            operations += 1
    
    return operations


# Test cases
if __name__ == "__main__":
    # Test Question 1
    cells = [0, -10, -20, -30, 50]
    print(f"Maximum score: {max_score_game(cells)}")  # Output: 40
    
    # Test Question 2
    print(f"Minimum operations: {min_operations(5)}")  # Output: 2

🚀 Need Interview Assistance?

oavoservice provides professional OA/VO assistance services to help you quickly pass technical interviews at major tech companies like Microsoft, Amazon, and more.

👉 Contact WeChat: Coding0201


联系方式

Email: [email protected] Telegram: @OAVOProxy