给出一个数字,找出它是否辉煌

时间:2012-08-24 18:34:04

标签: algorithm language-agnostic

这是一个编程难题,如下所示:“如果其子串的所有数字的乘积都具有唯一值,那么这个数字就会很棒。”

示例:263(2,6,3,2 * 6 = 12,6 * 3 = 18)很棒。

但236(2,3, 6 2 * 3 = 6 ,3 * 6 = 18)并不出色。

我们只采用子串,而不是子序列。

我想也许我们可以在这里应用动态编程,因为重复的产品计算?我们还能有什么其他解决方案吗? (这不是一个家庭作业问题。)

5 个答案:

答案 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的具体示例解决方案:

  1. 我们分配一个矩阵, M ,尺寸为4×4。

    enter image description here

  2. 我们首先用 d i 填充对角线 M i,i

    enter image description here

  3. 然后我们逐行进行,并用 d i 填写 M i,j 中号<子> I-1,J

    enter image description here

  4. 结果如

    enter image description here

  5. 为了检查重复项,我们收集产品(2,12,6,84,42,7,252,126,21,3),对它们进行排序(2,3,6,7,12, 21,42,84,126,252),并循环查看两个连续数字是否相等。如果是这样我们返回false,否则为true。

  6. 在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