Bird
Raised Fist0
Interview Prepdp-advanced-trees-bitmaskhardGoogle

Count Ways to Assign Unique Cap

Choose your preparation mode4 modes available
📋
Problem

Imagine a party where each guest wants a unique cap from a collection, but each guest has preferences on which caps they like. How many ways can you assign caps so that everyone gets a unique cap they like?

Given n persons and 100 caps numbered 1 to 100. Each person has a list of caps they like. Find the number of ways to assign caps to persons such that each person gets exactly one cap they like and no two persons get the same cap. Return the count modulo 10^9+7.

1 ≤ n ≤ 10Each person likes at least one capCaps are numbered from 1 to 100
Edge cases: All persons like the same single cap → output 0Each person likes a unique cap → output 1One person likes all caps, others like none → output 0
</>
IDE
def count_ways(person_caps: list[list[int]]) -> int:public int countWays(List<List<Integer>> personCaps)int countWays(const vector<vector<int>>& personCaps)function countWays(personCaps)
def count_ways(person_caps):
    # Write your solution here
    pass
class Solution {
    public int countWays(List<List<Integer>> personCaps) {
        // Write your solution here
        return 0;
    }
}
#include <vector>
using namespace std;

int countWays(const vector<vector<int>>& personCaps) {
    // Write your solution here
    return 0;
}
function countWays(personCaps) {
    // Write your solution here
}
Coming soon
0/9
Common Bugs to Avoid
Wrong: 0Not counting any assignments due to missing memoization or incorrect base case.✅ Add base case returning 1 when all persons assigned and memoize intermediate results.
Wrong: 1Greedy approach assigning first available cap only, missing other permutations.✅ Use full bitmask DP exploring all cap assignments recursively with memoization.
Wrong: Incorrect positive number when unique assignment impossibleNot enforcing unique cap assignment, allowing multiple persons to share same cap.✅ Check bitmask to ensure cap not already assigned before assigning to a person.
Wrong: Timeout or no outputBrute force recursion without memoization causing exponential blowup.✅ Implement memoization or bottom-up DP to prune repeated states.
✓
Test Cases
t1_01basic
Input{"person_caps":[[5,100],[1,5,100],[1,2]]}
Expected4

Possible assignments: (P0->5, P1->1, P2->2), (P0->5, P1->100, P2->1), (P0->100, P1->5, P2->1), (P0->100, P1->1, P2->2).

t1_02basic
Input{"person_caps":[[1,2],[2,3],[3,4]]}
Expected3

Assignments: (P0->1, P1->2, P2->3), (P0->1, P1->3, P2->4), (P0->2, P1->3, P2->4).

t2_01edge
Input{"person_caps":[]}
Expected1

No persons means one valid assignment (empty assignment).

t2_02edge
Input{"person_caps":[[42]]}
Expected1

Single person with one cap liked has exactly one assignment.

t2_03edge
Input{"person_caps":[[1],[1],[1]]}
Expected0

All persons like the same single cap; only one cap available, so no unique assignments possible.

t3_01corner
Input{"person_caps":[[1,2],[1,2],[1,2]]}
Expected0

Three persons all like only caps 1 and 2; only two caps available, so no unique assignment for all three.

t3_02corner
Input{"person_caps":[[1,2,3],[1,2,3],[1,2,3]]}
Expected6

All persons like caps 1, 2, 3; total unique assignments are permutations of 3 caps to 3 persons = 3! = 6.

t3_03corner
Input{"person_caps":[[1,2,3,4],[2,3,4],[3,4]]}
Expected4

Assignments: (P0->1, P1->2, P2->3), (P0->1, P1->3, P2->4), (P0->2, P1->3, P2->4), (P0->3, P1->2, P2->4).

t4_01performance
Input{"_description":"n=10 at constraint boundary - executor generates this input with overlapping caps"}
⏱ Performance - must finish in 2000ms

n=10 persons with overlapping caps; O(100 * 2^n * n) DP expected to run within 2 seconds.

Practice

(1/5)
1. Consider the following iterative postorder traversal code snippet for computing the maximum path sum in a binary tree. Given the tree: 1 / \ 2 3 What is the final value of max_sum after the algorithm completes?
easy
A. 4
B. 6
C. 5
D. 3

Solution

  1. Step 1: Trace gains for leaf nodes

    Node 2 and Node 3 are leaves, so gains[2] = 2, gains[3] = 3, max_sum updated to max(-inf, 2) = 2, then max(2,3) = 3.
  2. Step 2: Compute gains for root node 1

    left_gain = max(gains[2],0) = 2, right_gain = max(gains[3],0) = 3, price_newpath = 1 + 2 + 3 = 6, max_sum updated to max(3,6) = 6.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Sum of path 2 -> 1 -> 3 is 6 [OK]
Hint: Sum path through root includes both children gains [OK]
Common Mistakes:
  • Forgetting to add both children
  • Using only max child gain
  • Off-by-one in stack processing
2. Consider the following Python code implementing the optimized LIS algorithm. What is the value of the variable tails after processing the input [3, 1, 2]?
easy
A. [1, 2, 3]
B. [1, 2]
C. [1, 3]
D. [3, 1, 2]

Solution

  1. Step 1: Process num=3

    tails is empty, bisect_left returns 0, append 3 -> tails = [3]
  2. Step 2: Process num=1

    bisect_left(tails,1) returns 0, replace tails[0] with 1 -> tails = [1]
  3. Step 3: Process num=2

    bisect_left(tails,2) returns 1 (end of tails), append 2 -> tails = [1, 2]
  4. Final Answer:

    Option B -> Option B
  5. Quick Check:

    tails always sorted and minimal last elements [OK]
Hint: tails stores smallest possible ends of subsequences [OK]
Common Mistakes:
  • Appending instead of replacing in tails
  • Misunderstanding bisect_left index
  • Confusing tails with actual subsequence
3. What is the time complexity of the iterative postorder traversal solution for the Binary Tree Maximum Path Sum problem, assuming the tree has n nodes?
medium
A. O(n) for traversal but O(n) extra space for the stack and gains dictionary
B. O(n log n) due to repeated stack operations and subtree recomputations
C. O(n^2) because for each node, the algorithm recomputes gains from all descendants
D. O(n) because each node is visited once and gains are computed in constant time per node

Solution

  1. Step 1: Identify traversal cost

    The iterative postorder traversal visits each node exactly once, pushing and popping it from the stack once.
  2. Step 2: Analyze per-node computation

    At each node, gains are computed using stored values from children in O(1) time, no recomputation of subtrees.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Linear traversal with constant work per node -> O(n) time [OK]
Hint: Each node processed once, no repeated subtree work [OK]
Common Mistakes:
  • Confusing recursion stack with repeated work
  • Assuming recomputation of subtree gains
  • Ignoring constant time per node
4. Suppose the problem is modified so that elements can be reused multiple times in subsequences (i.e., subsequences are multisets, not strictly increasing indices). Which change to the DP approach correctly counts all arithmetic subsequences under this new constraint?
hard
A. Keep the same DP but allow j to be equal to i to reuse elements
B. Use a DP that counts subsequences by difference without restricting j < i, allowing repeated indices
C. Modify DP to consider all pairs (i, j) with i ≤ j and update counts accordingly
D. Switch to a combinatorial formula since DP no longer applies

Solution

  1. Step 1: Understand reuse means indices can repeat or be equal

    Original DP requires j < i to ensure strictly increasing indices; reuse breaks this.
  2. Step 2: Modify DP loops to allow i ≤ j and update counts accordingly

    Allowing i ≤ j and updating dp[i][diff] with dp[j][diff] + 1 counts subsequences with repeated elements correctly.
  3. Step 3: Reject naive reuse of original DP or combinatorial formulas

    Original DP with j < i fails; combinatorial formulas are not straightforward here.
  4. Final Answer:

    Option C -> Option C
  5. Quick Check:

    Allowing i ≤ j and updating counts handles reuse correctly [OK]
Hint: Reuse requires relaxing j < i to i ≤ j in DP loops [OK]
Common Mistakes:
  • Trying to reuse original DP without index relaxation
  • Assuming combinatorial formula suffices
  • Allowing j = i without updating counts properly
5. Suppose the problem changes: now you can reuse elements multiple times to form the longest strictly increasing subsequence. Which modification to the optimized LIS algorithm is correct?
hard
A. The optimized binary search approach cannot be directly adapted; use a DP with memoization considering reuse
B. Modify the DP to consider repeated elements by changing comparison from '>' to '>=' in recursion
C. Use the same binary search approach but allow replacing tails with equal or greater elements (use bisect_right)
D. Sort the array and count the longest consecutive increasing sequence allowing duplicates

Solution

  1. Step 1: Understand reuse impact

    Allowing reuse breaks the strictly increasing subsequence definition and the binary search tails logic.
  2. Step 2: Evaluate algorithm suitability

    The optimized binary search approach relies on unique progression; reuse requires state tracking, best handled by DP with memoization.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Reuse requires more complex DP, not simple binary search [OK]
Hint: Reuse breaks tails logic; DP with memo needed [OK]
Common Mistakes:
  • Trying to fix with bisect_right only
  • Changing comparison operators without DP
  • Assuming sorting solves reuse problem
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard