这是一个编程难题,如下所示:“如果其子串的所有数字的乘积都具有唯一值,那么这个数字就会很棒。”
示例:263(2,6,3,2 * 6 = 12,6 * 3 = 18)很棒。
但236(2,3, 6 , 2 * 3 = 6 ,3 * 6 = 18)并不出色。
我们只采用子串,而不是子序列。
我想也许我们可以在这里应用动态编程,因为重复的产品计算?我们还能有什么其他解决方案吗? (这不是一个家庭作业问题。)
答案 0 :(得分:7)
以下是使用动态编程解决问题的一种方法:
假设我们将数字 d 0 d 1 ... d N 作为输入。
想法是创建一个表,其中单元格( i , j )存储产品 d i ·d < sub> i + 1 ·...·d j 。这可以有效地完成,因为( i , j )的单元格可以通过乘以( i -1, j ) d i 。
由于 i (起始索引)必须小于或等于 j (结束索引),我们将专注于表格的左下角三角形
生成表格后,我们会检查重复的条目。
以下是输入2673的具体示例解决方案:
我们分配一个矩阵, M ,尺寸为4×4。
我们首先用 d i 填充对角线 M i,i :
然后我们逐行进行,并用 d i 填写 M i,j >·中号<子> I-1,J 子> 的
结果如
为了检查重复项,我们收集产品(2,12,6,84,42,7,252,126,21,3),对它们进行排序(2,3,6,7,12, 21,42,84,126,252),并循环查看两个连续数字是否相等。如果是这样我们返回false,否则为true。
在Java代码中:
这是一个有效的DP解决方案,O(n 2 )。
public static boolean isColorful(int num) {
// Some initialization
String str = "" + num;
int[] digits = new int[str.length()];
for (int i = 0; i < str.length(); i++)
digits[i] = str.charAt(i) - '0';
int[][] dpmatrix = new int[str.length()][str.length()];
// Fill in diagonal: O(N)
for (int i = 0; i < digits.length; i++)
dpmatrix[i][i] = digits[i];
// Fill in lower left triangle: O(N^2)
for (int i = 0; i < str.length(); i++)
for (int j = 0; j < i; j++)
dpmatrix[i][j] = digits[i] * dpmatrix[i-1][j];
// Check for dups: O(N^2)
int[] nums = new int[digits.length * (digits.length+1) / 2];
for (int i = 0, j = 0; i < digits.length; i++, j += i)
System.arraycopy(dpmatrix[i], 0, nums, j, i+1);
Arrays.sort(nums);
for (int i = 0; i < nums.length - 1; i++)
if (nums[i] == nums[i+1])
return false;
return true;
}
对于感兴趣的读者,我可以在这里推荐一些类似的问题/答案:
答案 1 :(得分:3)
使用动态编程可能是要走的路: 而不是计算所有O(n ^ 2)个子串,然后使用~n乘法命令来计算它们中的每一个,将先前caclulation的结果存储在矩阵M中,其中M(i,j)是子串的结果。长度j,从位置i开始。
(即,如果你的数字是123456789,那么M(1,5)是5 !,而M(1,6)是6 !,只需要将M(1,5)乘以6 - 常数工作)
这将改善从n(n ^ 3)到n位数到O(n ^ 2)的运行时间。
答案 2 :(得分:3)
动态编程解决方案实际上不是必需的,因为没有数字的明亮数字(如果任何数字出现不止一次,数字不是很好)。
Here是每个精彩数字的列表。总共有57,281个。
即使不使用动态编程,这个文件在我的电脑上生成的时间还不到一秒钟。)
答案 3 :(得分:0)
如果我们不将该数字视为一个大字符串,则哈希可以提供帮助;
int brill(int A) {
map<long long int,bool> m;
vector<int> arr(10,0);
int i=0;
while(A){
arr[i++]=A%10;
A/=10;
}
for(int j=0;j<i;j++){
long long int temp=1;
for(int k=j;k>=0;k--){
temp*=arr[k];
if(m.find(temp)!=m.end()){
return 0;
}
else{
m[temp]=true;
}
}
}
return 1;
}
答案 4 :(得分:0)
n是包含数字的字符串。
由于数字在失败状态之前不能大于8位,因此其为O(1)。
function isBrill(n) {
var set = {};
set[parseInt(n.charAt(0))] = true;
for(var i=0; i < n.length - 1; i++) {
var a = parseInt(n.charAt(i));
var b = parseInt(n.charAt(i+1));
if(set[b] === true) { return false; }
set[b] = true;
if(set[a * b] === true) { return false; }
set[a * b] = true;
}
return true;
}
isBrill("263"); // true
isBrill("236"); // false