Taro Logo

Solving Questions With Brainpower

Medium
Meta logo
Meta
Topics:
Dynamic Programming

You are given a 0-indexed 2D integer array questions where questions[i] = [points_i, brainpower_i]. The array describes the questions of an exam, where you have to process the questions in order (i.e., starting from question 0) and make a decision whether to solve or skip each question. Solving question i will earn you points_i points but you will be unable to solve each of the next brainpower_i questions. If you skip question i, you get to make the decision on the next question.

For example, given questions = [[3, 2], [4, 3], [4, 4], [2, 5]]:

  • If question 0 is solved, you will earn 3 points but you will be unable to solve questions 1 and 2.
  • If instead, question 0 is skipped and question 1 is solved, you will earn 4 points but you will be unable to solve questions 2 and 3.

Return the maximum points you can earn for the exam.

Example 1:

Input: questions = [[3,2],[4,3],[4,4],[2,5]] Output: 5 Explanation: The maximum points can be earned by solving questions 0 and 3.

  • Solve question 0: Earn 3 points, will be unable to solve the next 2 questions
  • Unable to solve questions 1 and 2
  • Solve question 3: Earn 2 points

Total points earned: 3 + 2 = 5. There is no other way to earn 5 or more points.

Example 2:

Input: questions = [[1,1],[2,2],[3,3],[4,4],[5,5]] Output: 7 Explanation: The maximum points can be earned by solving questions 1 and 4.

  • Skip question 0
  • Solve question 1: Earn 2 points, will be unable to solve the next 2 questions
  • Unable to solve questions 2 and 3
  • Solve question 4: Earn 5 points

Total points earned: 2 + 5 = 7. There is no other way to earn 7 or more points.

Solution


Naive Solution (Brute Force)

A brute-force solution would involve exploring all possible combinations of solving or skipping questions. This can be done using recursion. For each question, we have two choices: solve it and skip the next brainpower questions, or skip it and move to the next question. We would then return the maximum points earned among all possible combinations.

Code (Python):

def max_points_brute_force(questions):
    def solve(index):
        if index >= len(questions):
            return 0

        # Option 1: Solve the current question
        points, brainpower = questions[index]
        solve_next = solve(index + brainpower + 1)  # Skip brainpower questions
        solve_current = points + solve_next

        # Option 2: Skip the current question
        skip_current = solve(index + 1)

        return max(solve_current, skip_current)

    return solve(0)


# Example usage
questions = [[3, 2], [4, 3], [4, 4], [2, 5]]
print(max_points_brute_force(questions))  # Output: 5

Time Complexity: O(2n), where n is the number of questions. This is because, in the worst case, we explore every possible combination of solving or skipping each question.

Space Complexity: O(n), due to the recursion depth.

This brute force solution will likely exceed the time limit for larger inputs.

Optimal Solution (Dynamic Programming)

We can optimize the solution using dynamic programming. Let dp[i] be the maximum points we can earn starting from question i. We can build dp from the end of the questions array to the beginning. The state transition will be:

dp[i] = max(points[i] + dp[i + brainpower[i] + 1], dp[i + 1])

where points[i] and brainpower[i] are the points and brainpower associated with the i-th question. If i + brainpower[i] + 1 goes beyond the array bounds, we consider it as 0.

Code (Python):

def max_points_dp(questions):
    n = len(questions)
    dp = [0] * (n + 1)

    for i in range(n - 1, -1, -1):
        points, brainpower = questions[i]
        next_question = i + brainpower + 1
        solve_current = points + (dp[next_question] if next_question <= n else 0)
        skip_current = dp[i + 1]
        dp[i] = max(solve_current, skip_current)

    return dp[0]


# Example usage
questions = [[3, 2], [4, 3], [4, 4], [2, 5]]
print(max_points_dp(questions))  # Output: 5

questions = [[1, 1], [2, 2], [3, 3], [4, 4], [5, 5]]
print(max_points_dp(questions)) # Output: 7

Time Complexity: O(n), where n is the number of questions. We iterate through the questions array once.

Space Complexity: O(n), to store the dp array.

Edge Cases

  • Empty Input: If the input questions array is empty, the function should return 0.
  • Large Brainpower: If brainpower is large enough that solving a question takes us past the end of the array, we simply don't add anything for further questions, which is handled correctly by the dp implementation.
  • Single Question: If there is only one question, the answer is simply the point value of that question.