【问题标题】:Ugly Number - Mathematical intuition for dp丑数 - dp 的数学直觉
【发布时间】:2019-08-21 17:39:59
【问题描述】:

我正在尝试找到“丑陋”的数字,它是一系列唯一素因数为 [2,3,5] 的数字。

我找到了动态编程解决方案,并想了解它的工作原理以及逻辑背后的数学直觉。

  1. 算法是为 2、3 和 5 的倍数保留三个不同的计数器变量。假设 i2、i3 和 i5。

  2. 声明丑数组并将0索引初始化为1,因为第一个丑数是1。

  3. 初始化 i2=i3=i4=0;

  4. ugly[i] = min(ugly[i2]*2,丑陋[i3]*3,丑陋[i5]*5) 并增加 i2 或 i3 或 i5 所选择的索引。

试运行:

ugly = |1|

  i2=0;
  i3=0;
  i5=0;

ugly[1] = min(ugly[0]*2, ugly[0]*3, ugly[0]*5) = 2

---------------------------------------------------

ugly = |1|2|

  i2=1;
  i3=0;
  i5=0;

ugly[2] = min(ugly[1]*2, ugly[0]*3, ugly[0]*5) = 3

---------------------------------------------------

ugly = |1|2|3|

  i2=1;
  i3=1;
  i5=0;

ugly[3] = min(ugly[1]*2, ugly[1]*3, ugly[0]*5) = 4

---------------------------------------------------

ugly = |1|2|3|4|

  i2=2;
  i3=1;
  i5=0;

ugly[4] = min(ugly[2]*2, ugly[1]*3, ugly[0]*5) = 5

---------------------------------------------------

ugly = |1|2|3|4|5|

  i2=2;
  i3=1;
  i5=1;

ugly[4] = min(ugly[2]*2, ugly[1]*3, ugly[0]*5) = 6

---------------------------------------------------

ugly = |1|2|3|4|5|6|

我迷失了如何从 2 的索引中形成 6。谁能简单解释一下?

【问题讨论】:

    标签: algorithm


    【解决方案1】:

    每个“丑”数(1 除外)都可以通过将较小的丑数乘以 2、3 或 5 来形成。

    假设目前发现的丑数是 [1,2,3,4,5]。根据该列表,我们可以生成三个丑数序列:

    乘以 2,可能的丑数是 [2,4,6,8,10]
    乘以 3,可能的丑数是 [3,6,9,12,15]
    乘以 5,可能的丑数是 [5,10,15,20,25]

    但是列表中已经有 2、3、4 和 5,所以我们不关心小于或等于 5 的值。让我们用 - 标记这些条目以表示我们不关心关心他们

    乘以 2,可能的丑数是 [-,-,6,8,10]
    乘以 3,可能的丑数是 [-,6,9,12,15]
    乘以 5,可能的丑数是 [-,10,15,20,25]

    而事实上,我们真正关心的是每个序列中最小的

    乘以2,大于5的最小数是6
    乘以3,大于5的最小数是6
    乘以5,大于5的最小数是10

    在丑数列表中添加 6 后,每个序列都有一个附加元素:

    乘以 2,可能的丑数是 [-,-,-,8,10,12]
    乘以 3,可能的丑数是 [-,-,9,12,15,18]
    乘以 5,可能的丑数是 [-,10,15,20,25,30]

    但是每个序列中有用的元素是:

    乘以2,大于6的最小数是8
    乘以3,大于6的最小数是9
    乘以5,大于6的最小数是10

    因此,您可以看到该算法正在创建三个丑陋数字序列。每个序列都是通过将所有现有的丑数乘以三个因子之一形成的。

    但我们只关心每个序列中的最小数(大于目前发现的最大丑数)。

    所以索引 i2、i3 和 i5 是对应序列的索引。当您使用序列中的数字时,您会更新索引以指向该序列中的下一个数字。

    【讨论】:

      【解决方案2】:

      直觉如下:

      • 任何丑数都可以写成2、3或5与另一个(更小的)丑数之间的乘积。

      考虑到这一点,问题中提到的解决方案会跟踪 i2i3i5,即到目前为止生成的最小丑数,分别乘以 2、3 和 5 会导致一个尚未生成的数字。这些产品中最小的是尚未生成的最小丑数。

      换一种说法,我认为问题中的以下陈述可能会引起一些混乱:

      算法是为a保留三个不同的计数器变量 2、3 和 5 的倍数。假设 i2、i3 和 i5。

      请注意,例如,丑 [i2] 不一定是 2 的倍数。它只是 2 * 丑 [i2] 大于丑 [i] 的最小丑数(已知的最大丑数)远)。


      关于下一步如何生成数字6,过程如下:

      ugly = |1|2|3|4|5
      
        i2 = 2;
        i3 = 1;
        i5 = 1;
      
      ugly[5] = min(ugly[2]*2, ugly[1]*3, ugly[1]*5) = min(3*2, 2*3, 2*5) = 6
      
      ---------------------------------------------------
      
      ugly = |1|2|3|4|5|6
      
        i2 = 3
        i3 = 2
        i5 = 1
      

      注意这里 i2i3 都需要在生成数字 6 后递增,因为 i2*2 和 i3*3 都产生了相同的 next最小的丑数。

      【讨论】:

      • 找到 6 作为一个丑数,它的表现很丑[2] *2。这是 3*2 = 6 。我无法想象映射到数组的索引计数是如何工作的?
      • 如果 i2=2 ,为什么我必须看到丑陋[2] 的价值才能获得下一个倍数?
      • @Sumeet 因为丑[2] 是最小的丑数,当它乘以 2 时,会得到一个大于最后生成的丑数(丑 [4] == 5 )。例如,如果我们将丑陋[1] * 2 相乘,那么我们将得到值 4(已经生成)。另一方面,如果我们要相乘,例如,丑陋[3] * 2,我们将得到值 8(它大于必要的值,它不能是序列中的下一个)。这就是为什么 i2 == 2 表明我们应该精确地尝试丑 [i2] * 2,作为一个尚未生成的小候选丑数。
      猜你喜欢
      • 2018-06-11
      • 1970-01-01
      • 2020-09-07
      • 1970-01-01
      • 1970-01-01
      • 2011-06-03
      • 1970-01-01
      • 2014-02-24
      相关资源
      最近更新 更多