给定两个数组,一个保存min 值,另一个保存每个索引的max 值,您可以定义一个简单的递归函数来导出每个可能的递增序列,每个位置的起始值都是最大值当前min 值和之前选择的值加1。
这里有一些 Java 代码来说明:
static void incSeq(int[] min, int[] max, int[] res, int pos, int prev)
{
if(pos == min.length)
{
System.out.println("seq: " + Arrays.toString(res));
return;
}
for(int j = Math.max(prev+1, min[pos]); j <= max[pos]; j++)
{
res[pos] = j;
incSeq(min, max, res, pos+1, j);
}
}
但是,如果我们考虑如下输入:
min = {1, 1, 1, 1}
max = {100, 100, 100, 5}
我们可以看到,我们的函数将做很多无用的工作,遍历前三个位置的值,这些值不会是递增序列的一部分。
我们可以通过认识到我们需要考虑的位置i 的最大值比位置i+1 的最大值小一来解决这个问题。如果我们从最后一个位置开始并使用此规则向后工作,我们可以将上面的 max 数组更新为:
max = {2, 3, 4, 5}
这意味着我们的递归函数的工作量会少很多。
这是完整的代码:
public static void main(String[] args)
{
int n = 4;
int[] a = {6,3,4,4};
int[] b = {1,5,1,6};
int[] min = new int[n];
int[] max = new int[n];
System.out.println("a: " + Arrays.toString(a));
System.out.println("b: " + Arrays.toString(b));
for(int i=0; i<n; i++)
{
min[i] = Math.min(a[i], b[i]);
max[i] = Math.max(a[i], b[i]);
}
System.out.println("min: " + Arrays.toString(min));
System.out.println("max: " + Arrays.toString(max));
// cap max values
for(int i=n-1; i>0; i--)
{
max[i-1] = Math.min(max[i-1], max[i]-1);
}
System.out.println("max: " + Arrays.toString(max) + "\n");
incSeq(min, max, new int[n], 0, 0);
}
static void incSeq(int[] min, int[] max, int[] res, int pos, int prev)
{
if(pos == min.length)
{
System.out.println("seq: " + Arrays.toString(res));
return;
}
for(int j = Math.max(prev+1, min[pos]); j <= max[pos]; j++)
{
res[pos] = j;
incSeq(min, max, res, pos+1, j);
}
}
输出:
a: [6, 3, 4, 4]
b: [1, 5, 1, 6]
min: [1, 3, 1, 4]
max: [6, 5, 4, 6]
max: [2, 3, 4, 6]
seq: [1, 3, 4, 5]
seq: [1, 3, 4, 6]
seq: [2, 3, 4, 5]
seq: [2, 3, 4, 6]