Shortest Impossible Sequence of Rolls
HARDDescription
You are given an integer array rolls of length n and an integer k. You roll a k sided dice numbered from 1 to k, n times, where the result of the ith roll is rolls[i].
Return the length of the shortest sequence of rolls so that there's no such subsequence in rolls.
A sequence of rolls of length len is the result of rolling a k sided dice len times.
Example 1:
Input: rolls = [4,2,1,2,3,3,2,4,1], k = 4 Output: 3 Explanation: Every sequence of rolls of length 1, [1], [2], [3], [4], can be taken from rolls. Every sequence of rolls of length 2, [1, 1], [1, 2], ..., [4, 4], can be taken from rolls. The sequence [1, 4, 2] cannot be taken from rolls, so we return 3. Note that there are other sequences that cannot be taken from rolls.
Example 2:
Input: rolls = [1,1,2,2], k = 2 Output: 2 Explanation: Every sequence of rolls of length 1, [1], [2], can be taken from rolls. The sequence [2, 1] cannot be taken from rolls, so we return 2. Note that there are other sequences that cannot be taken from rolls but [2, 1] is the shortest.
Example 3:
Input: rolls = [1,1,3,2,2,2,3,3], k = 4 Output: 1 Explanation: The sequence [4] cannot be taken from rolls, so we return 1. Note that there are other sequences that cannot be taken from rolls but [4] is the shortest.
Constraints:
n == rolls.length1 <= n <= 1051 <= rolls[i] <= k <= 105
Approaches
Checkout 2 different approaches to solve Shortest Impossible Sequence of Rolls. Click on different approaches to view the approach and algorithm in detail.
Dynamic Programming by Counting Subsequences
This approach uses dynamic programming to count the number of distinct subsequences for each possible length. We iterate through lengths L = 1, 2, 3, ... and for each length, we calculate how many unique subsequences of that length can be formed from the rolls array. The first length L for which this count is less than the total number of possible sequences of that length (k^L) is the answer.
Algorithm
- We are looking for the smallest length
Lsuch that the number of distinct subsequences ofrollsof lengthLis less thank^L. - We can iterate
Lfrom 1 upwards. - For each
L, we calculate the total number of distinct subsequences of lengthLthat can be formed from therollsarray. - Let
dp[i][j]be the number of distinct subsequences of lengthjin the prefixrolls[0...i-1]. - The recurrence relation is:
dp[i][j] = dp[i-1][j] + (dp[i-1][j-1] - dp[p][j-1]), wherepis the index of the previous occurrence of the elementrolls[i-1]. This formula counts subsequences not usingrolls[i-1](dp[i-1][j]) and those formed by appendingrolls[i-1]to shorter subsequences, avoiding double counting. - We can optimize space by noticing that computing the column for length
Lonly requires the column for lengthL-1. So we can use two arrays, one for the previous length and one for the current length. - For each
L, we computedp[n][L]. Ifdp[n][L] < k^L, we have found our answer, and we returnL. - We must handle potential overflow when calculating
k^L.
Let dp[i][j] be the number of distinct subsequences of length j that can be formed using the prefix of the rolls array of length i (i.e., rolls[0...i-1]). Our goal is to find the smallest j such that dp[n][j] < k^j.
The recurrence relation for dp[i][j] is derived by considering the element rolls[i-1]:
- Subsequences of length
jinrolls[0...i-1]that do not includerolls[i-1]are the same as subsequences of lengthjinrolls[0...i-2]. Their count isdp[i-1][j]. - Subsequences of length
jinrolls[0...i-1]that do includerolls[i-1]as their last element are formed by taking any distinct subsequence of lengthj-1fromrolls[0...i-2]and appendingrolls[i-1]. The number of such new subsequences isdp[i-1][j-1]. However, this might lead to double counting ifrolls[i-1]has appeared before. If the previous occurrence ofrolls[i-1]was at indexp-1, then any subsequence of lengthj-1fromrolls[0...p-2]extended withrolls[i-1]has already been counted. We must subtract these, which amounts todp[p-1][j-1].
So, the full recurrence is: dp[i][j] = dp[i-1][j] + dp[i-1][j-1] - dp[p-1][j-1], where p is the 1-based index of the previous occurrence of rolls[i-1].
We can optimize the space from O(n*ans) to O(n) by using only two arrays to store the DP results for the current and previous lengths.
import java.util.Arrays;
class Solution {
public int shortestImpossibleSequenceOfRolls(int[] rolls, int k) {
int n = rolls.length;
// dp for length len-1. Initially for len=0, there's 1 empty subsequence.
long[] prevDp = new long[n + 1];
Arrays.fill(prevDp, 1);
for (int len = 1; len <= n + 1; len++) {
long kPowLen = 1;
// Calculate k^len with overflow check
for (int i = 0; i < len; i++) {
if (kPowLen > Long.MAX_VALUE / k) {
kPowLen = Long.MAX_VALUE; // Represents a very large number
break;
}
kPowLen *= k;
}
long[] currDp = new long[n + 1]; // dp for length len
int[] last = new int[k + 1]; // Stores last seen 1-based index of a roll value
for (int i = 1; i <= n; i++) {
// Number of subsequences of length 'len' in rolls[0...i-2]
currDp[i] = currDp[i - 1];
// New subsequences formed by appending rolls[i-1]
long toAdd = prevDp[i - 1];
int rollValue = rolls[i - 1];
if (last[rollValue] > 0) {
// Subtract subsequences that would be duplicates
toAdd -= prevDp[last[rollValue] - 1];
}
currDp[i] += toAdd;
}
if (currDp[n] < kPowLen) {
return len;
}
prevDp = currDp;
}
return n + 1; // Should not be reached given problem constraints
}
}
Complexity Analysis
Pros and Cons
- It is a systematic approach that correctly solves the problem.
- The logic is based on a standard DP technique for counting distinct subsequences.
- The time complexity is dependent on the answer, which can be large in some cases, leading to a Time Limit Exceeded error on certain test cases.
- The implementation is more complex than the greedy approach, involving careful handling of DP states and potential numerical overflows.
Code Solutions
Checking out 3 solutions in different languages for Shortest Impossible Sequence of Rolls. Click on different languages to view the code.
class Solution { public int shortestSequence ( int [] rolls , int k ) { Set < Integer > s = new HashSet <>(); int ans = 1 ; for ( int v : rolls ) { s . add ( v ); if ( s . size () == k ) { s . clear (); ++ ans ; } } return ans ; } }Video Solution
Watch the video walkthrough for Shortest Impossible Sequence of Rolls
Similar Questions
5 related questions you might find useful
Patterns:
Data Structures:
Subscribe to Scale Engineer newsletter
Learn about System Design, Software Engineering, and interview experiences every week.
No spam, unsubscribe at any time.