Algorithm 从N个整数数组中选择有序三元组的不同方法
给定一个由n个整数组成的数组,我想找到选择有序三元组的方法。例如Algorithm 从N个整数数组中选择有序三元组的不同方法,algorithm,permutation,dynamic-programming,Algorithm,Permutation,Dynamic Programming,给定一个由n个整数组成的数组,我想找到选择有序三元组的方法。例如 A = [1, 2, 1, 1] different ways are (1, 2, 1), (1, 1, 1) and (2, 1, 1) so the answer will be 3. for A = [2, 2, 1, 2, 2] different ways are (1, 2, 2), (2, 1, 2), (2, 2, 1) and (2, 2, 2) so the answer will be 4 in thi
A = [1, 2, 1, 1]
different ways are (1, 2, 1), (1, 1, 1) and (2, 1, 1)
so the answer will be 3.
for A = [2, 2, 1, 2, 2]
different ways are (1, 2, 2), (2, 1, 2), (2, 2, 1) and (2, 2, 2)
so the answer will be 4 in this case
如果所有的数字都是唯一的,那么我提出了一个循环
f(n) = f(n-1) + ((n-1) * (n-2))/2
where f(3) = 1 and f(2) = f(1) = 0
当数字重复时,我遇到了麻烦。这需要在O(n)时间和O(n)空间中解决。大小为idx的数组中唯一有序集的数量的动态规划关系为: DP[集合大小][idx]=DP[集合大小][idx-1]+DP[集合大小-1][idx-1]-DP[集合大小-1][last_idx[A[idx]-1] 因此,要计算idx元素数组中大小LEN的有序唯一集的数量:
- 取可以从idx-1元素数组创建的有序、唯一的大小LEN集的数量
- 添加可通过将元素idx添加到大小LEN-1的有序唯一集的末尾来形成的有序唯一集的数量
- 不要重复计数。减去可通过将元素idx的上一次出现添加到大小LEN-1的有序唯一集的末尾来形成的有序唯一集的数量
static int answer(int[] A) {
// This example is for 0 <= A[i] <= 9. For an array of arbitrary integers, use a proper
// HashMap instead of an array as a HashMap. Alternatively, one could compress the input array
// down to distinct, consecutive numbers. Either way max memory of the last_idx array is O(n).
// This is left as an exercise to the reader.
final int MAX_INT_DIGIT = 10;
final int SUBSEQUENCE_LENGTH = 3;
int n = A.length;
int[][] dp = new int[SUBSEQUENCE_LENGTH][n];
int[] last_idx = new int[MAX_INT_DIGIT];
Arrays.fill(last_idx, -1);
// Init dp[0] which gives the number of distinct sets of length 1 ending at index i
dp[0][0] = 1;
last_idx[A[0]] = 0;
for (int i = 1; i < n; i++) {
if (last_idx[A[i]] == -1) {
dp[0][i] = dp[0][i - 1] + 1;
} else {
dp[0][i] = dp[0][i - 1];
}
last_idx[A[i]] = i;
}
for (int ss_len = 1; ss_len < SUBSEQUENCE_LENGTH; ss_len++) {
Arrays.fill(last_idx, -1);
last_idx[A[0]] = 0;
for (int i = 1; i < n; i++) {
if (last_idx[A[i]] <= 0) {
dp[ss_len][i] = dp[ss_len][i - 1] + dp[ss_len-1][i - 1];
} else {
dp[ss_len][i] = dp[ss_len][i - 1] + dp[ss_len-1][i - 1] - dp[ss_len-1][last_idx[A[i]] - 1];
}
last_idx[A[i]] = (i);
}
}
return dp[SUBSEQUENCE_LENGTH-1][n - 1];
}
静态int应答(int[]A){
//这个例子是针对0的,我相信我有一个部分的解决方案,但对于我的一生,我不知道如何解释中间元素是罪犯的重复项(在线性时间内):(1,X,1),(1,Y,1)
其中X
和Y
相等,但不是同一个元素。对于其他情况,首先向前迭代数组,记录每个值第一次出现的位置。如果元素不是其值的第一次出现,则从总数中减去(arr\u length-curr\u index-1)
(跳过对最后两个元素的迭代)。如果违规元素是第一个元素,则所有这些都将是重复的。接下来,重复该过程,但向后迭代,以记录违规元素是三元组中最后一个元素的重复。现在我想到,元素可能会以这种方式计数两次,因此这是另一个需要解决的问题。第一个示例不也应该重复吗rn 4?您缺少(1,1,2)
@Emil No。三元组的顺序应与数组中的顺序相同。对于任何三元组(a,b,c)a
应位于b
之前,而b
在c
之前,您如何知道这可以在O(n)时间内解决?