New 21 Game: A Clean & Simple Visual Guide
Topics
Found this article helpful? Share it with others!
Found this article helpful? Share it with others!
Continue reading more helpful content from linked-list
Learn the optimal O(n) time and O(1) space solution for LeetCode 234: Palindrome Linked List using the Two-Pointer technique.
Read moreMaster LeetCode 203: Remove Linked List Elements. Learn how the Dummy Node technique effortlessly handles edge cases with our interactive visualizer and code guides.
Read moreLearn how to efficiently remove duplicates from a sorted linked list with interactive visualizations, clean code implementations, and real-world analogies.
Read moreThe "New 21 Game" sounds like a casino problem, but it is entirely mathematical. Alice is drawing numbers completely at random from a range of $1$ to maxPts. She starts at $0$ and will fiercely keep drawing numbers until her total points reach or exceed a target threshold, k.
Your goal is to figure out the exact probability that when she finally stops, her total score is less than or equal to n.
n = 21, k = 17, maxPts = 10 -> Output: 0.73278A standard Dynamic Programming approach would calculate the probability of landing on score i by looking backward at all the ways to get there: adding up the probabilities of i - 1, i - 2, all the way to i - maxPts, and dividing by maxPts.
However, because n and maxPts can go up to $10,000$, a nested loop ($O(N \times \text{maxPts})$) will instantly result in a Time Limit Exceeded (TLE) error.
To avoid the nested loop, we must use a Sliding Window. Instead of recalculating the sum of the previous maxPts probabilities every single time, we maintain a running total called Wsum.
Use the visualizer below to see exactly how Wsum slides forward, dropping old values and picking up new ones.
Let's use a real-world analogy: A conveyor belt of probabilities.
Imagine you are standing at the end of a conveyor belt that holds exactly maxPts buckets.
Wsum), divided by the number of dice sides (maxPts).This mechanism allows us to calculate the probability of every single state in strictly $O(1)$ time, turning our nested loop into a lightning-fast single pass.
Here is the production-ready logic applying the sliding window optimization.
[!NOTE]
We handle two edge cases right at the top. Ifk === 0(she stops instantly) orn >= k + maxPts(even if she draws the maximum possible number on her last turn, she can't exceedn), the probability is a guaranteed1.0.
function new21Game(n: number, k: number, maxPts: number): number {
// Edge cases where she is guaranteed to win
if (k === 0 || n >= k + maxPts) return 1.0;
const dp = new Float64Array(n + 1);
dp[0] = 1.0;
let Wsum = 1.0;
let probability = 0.0;
for (let i = 1; i <= n; i++) {
// Calculate the current probability using the sliding window
dp[i] = Wsum / maxPts;
// If she can still draw, add current probability to the window
if (i < k) {
Wsum += dp[i];
} else {
// If she stops, this probability goes directly into our final answer
probability += dp[i];
}
// Slide the window: remove the oldest probability if it was added
if (i - maxPts >= 0 && i - maxPts < k) {
Wsum -= dp[i - maxPts];
}
}
return probability;
}
class Solution:
def new21Game(self, n: int, k: int, maxPts: int) -> float:
if k == 0 or n >= k + maxPts:
return 1.0
dp = [0.0] * (n + 1)
dp[0] = 1.0
Wsum = 1.0
probability = 0.0
for i in range(1, n + 1):
dp[i] = Wsum / maxPts
if i < k:
Wsum += dp[i]
else:
probability += dp[i]
if i - maxPts >= 0 and i - maxPts < k:
Wsum -= dp[i - maxPts]
return probability
class Solution {
public double new21Game(int n, int k, int maxPts) {
if (k == 0 || n >= k + maxPts) {
return 1.0;
}
double[] dp = new double[n + 1];
dp[0] = 1.0;
double Wsum = 1.0;
double probability = 0.0;
for (int i = 1; i <= n; i++) {
dp[i] = Wsum / maxPts;
if (i < k) {
Wsum += dp[i];
} else {
probability += dp[i];
}
if (i - maxPts >= 0 && i - maxPts < k) {
Wsum -= dp[i - maxPts];
}
}
return probability;
}
}
Wsum (adding one value, subtracting one value) takes strictly constant $O(1)$ time.dp of size n + 1 to store the probability of reaching every possible score.Stay sharp for coding assessments and final exams! Use our free academic tools, including the GPA to Percentage Calculator, to check your academic stats and keep your records in order.