我刚从书中看到这个有趣的问题,我无法找到答案。
我有一个给定的数字X和一个目标数字Y,任务是找到X的所有数字的这种排列,使它最接近Y. 数字是数组的形式。没有给出数组大小限制。
实施例
Given number X = 1212
Target number Y = 1500
Answer = 1221
Here, abs(1500-1221) is smallest among all permutations of X.
Given number X = 1212
Target number Y = 1900
Answer = 2112
Here, abs(1900-2112) is smallest among all permutations of X.
Given number X = 1029
Target number Y = 2000
Answer = 2019
Here, abs(2000-2019) is smallest among all permutations of X.
我能找到的解决方案之一是生成给定数字的所有排列,并在每个阶段计算差异。但这很慢。
我试图找到贪婪的方法,在那里我将迭代目标数Y的所有索引,并且在每个索引处我将把给定数字X的那个数字放在abs(Y [i] - X [i] ])是最小的。但是在很多情况下都失败了。
我正在考虑使用DP方法,但无法提出任何方法。
任何导致答案的人都会有所帮助。
编辑 - 为我的贪婪方法添加伪代码
for each index i in [0,Y]:
min_index = 0;
for each index j in [1, X.length]:
if abs(X[j] - Y[i]) < abs(X[min_index] - Y[i]):
min_val = j
print X[min_index]
remove min_index from X
Example X = 1212 and Y = 1900.
step 1 - output 1 and remove index 0 from X.
step 2 - output 2 and remove index 1 from X.
step 3 - output 1 and remove index 2 from X.
step 2 - output 1 and remove index 3 from X.
answer = 1212 which is wrong (correct answer is 2112).
So fails for this test case and lots more.
答案 0 :(得分:1)
Beam search可能是一种方法。我们的想法是构建从最大到最小数字的数字,并用零填充其余数字。您可以为每个步骤中的每个数字构建最近和最接近的第二个数字,并丢弃所有比前三个更差的数字。 (实际上你最多只需要两个光束。如果光束中两个条目的距离相等,则只需要三个情况。)在计算过程中构造的数字A
和{{1永远不应该相等(除了B
只包含相同数字的特殊情况。)
以下是第二个例子的光束。 X
表示最佳光束,没有*
表示两者同样好:
*
这是第一个例子:
2000* -> 2100* -> 2112*
2200 -> 2211
1000 -> 1200
1100
第三个例子需要第二步的光束尺寸为3,因为第二个最佳光束1900和2100到2000的距离是100:
1000 -> 1200* -> 1221*
1100 -> 1122
2000 -> 2100
2200
注意:我已加入所有示例中的3.和4.步骤。
数字1000 -> 1900 -> 1901
1100
2000* -> 2000* -> 2019*
2100 2109
和X = 1992
是一个有趣的例子
Y = 2000
因为最好的光束在计算过程中会发生变化。
我写了一个小的python程序用于演示:
1000 -> 1900 -> 1992*
1200
2000* -> 2100 -> 2199
2900
代码不是最优的,但是这个算法最多有多项式运行时间, O ( n ²l n ),这个估计非常慷慨。
答案 1 :(得分:1)
所以,问题可以看作如下:
从最大有效数字开始,对于每个索引,有三种情况:
当前数字将小于所需数字,因此对于其余数字,我们尝试创建可能的最大数字=&gt;对于其余的数字,我们按降序对它们进行排序,即如果我们有0,2,7,5左 - >&gt;我们将创建7520
当前数字将大于所需数字,因此对于其余数字,我们尝试创建尽可能小的数字=&gt;对于其余的数字,我们按升序对它们进行排序,即如果我们有0,2,7,5左 - >&gt;我们将创建0275
如果当前数字等于所需数字,我们会将其附加到prefix
并尝试在下一次迭代中找到更好的匹配。
的伪代码:
int prefix, result;
for each index i from 0 to Y.length() {
int larger = prefix + smallestDigitLargerThan(Y(i)) + OtherDigitInAscendingOrder;
int smaller = prefix + largestDigitSmallerThan(Y(i)) + OtherDigitInDescendingOrder;
update result based on larger and smaller;
if there is no digit equals to Y(i)
break;
else {
remove Y(i) in X
prefix = prefix*10 + Y(i)
}
}
}
if prefix == Y {
//We have a full match
return prefix;
}
return result;
例如
X = 1029
Y = 2000
At index 0 -> Y(0) = 2,
int smaller = 0 (prefix) + 1(largest digit that is less than 2) + 920 (other digit in descending order) = 1920
int larger = 0 (prefix) + 9(smallest digit that is greater than 2) + 012 (other digit in ascending order) = 9012
int result = 1920
int prefix = 2
At index 1 -> Y(1) = 0,
int smaller = //Not exist
int larger = 2 + 1 + 09 = 2109
int result = 1920
int prefix = 20
At index 2 -> Y(2) = 0,
int smaller = //Not exist
int larger = 20 + 1 + 9 = 2019
int result = 2019
//Break as there is no digit match Y(2) = 0 from X
其他例子:
X = 1212
Y = 1500
At index 0 -> Y(0) = 1,
int smaller = //Not exist
int larger = 0 + 2 + 112 = 2112
int result = 2112
int prefix = 1
At index 1 -> Y(1) = 5,
int smaller = 1 + 2 + 21 = 1221
int larger = //Not exist
int result = 1221
//Break from here as there is no digit match Y(1) = 5 in X