【问题标题】:How to reduce time to find the n-th place from consecutive digits number for less than 1 second如何减少从连续数字中找到第 n 位的时间少于 1 秒
【发布时间】:2015-08-31 00:14:08
【问题描述】:

我在关注编程测试,有这样的问题

从这个连续的数字:

123456789101112131415161718192021....

例如第 10 位是 1 第 11 位是 0 等等

  • 第 1,000,000 位是什么?

  • 第 1,000,000,000 个数字是多少?

  • 第 1,000,000,000,000 位是什么?

您的解决方案的运行时间应低于 1 秒。

我已经得到了答案,但仍然超过 1 秒。我尝试使用多项式。

那么,我怎样才能减少从上面的数字中找到第 n 位的时间呢?

这是我的答案,(PHP):

function digit_pol ($n) {

  $counter = 1;
  $digit_arr = array();

  for ($i = 1; $i <= $n; $i++) {

    for ($j = 0; $j < strlen($i); $j++) {

      // If array more than 100, always shift (limit array length to 11)
      if($i > 10) {
        array_shift($digit_arr);
      }

      // Fill array
      $digit_arr[$counter] = substr($i, $j, 1);

      // Found
      if($counter == $n) {
        return $digit_arr[$counter];
      }

      $counter++;
    }

  }

}

/**
 * TESTING
 */

$find_place = 1000000;

$result = digit_pol($find_place);

echo "Digit of " . $find_place . "th is <b>" . $result . "</b>";

【问题讨论】:

  • 0到9(含)之间会有多少位? 10到99(含)之间有多少位? 100 到 999 之间有多少?
  • 顺便说一句,我的英语不好。但我希望我能清楚地解释目标。 @aioobe,您的意思是“如何使用我的代码?”这完全是我测试过的代码。您可以对其进行测试,只需复制并保存即可。第 1,000,000 个数字仍然超过 1 秒。
  • 你的问题是什么?
  • 我会尝试消除使用字符串并根据数学计算它。我会尝试计算在搜索到的地方或周围打印的数字 x。在第一个循环中,我将增加 n 并计算 10^n 和 10^(n+1) 之间有多少个数字,以及所有这些数字的字符串有多长。这样我就会很快接近。在第二个循环中,有必要找到其余的数字。最后你知道搜索到的数字在数字y中的位置x,这很容易计算。
  • @ajiyakin,你误解了我的意思。我对 PHP 不是很熟悉,但是如果我用伪代码或 Java 生成答案,这对你还有帮助吗?

标签: php algorithm digits


【解决方案1】:

重要的是要意识到迈出大步很容易:

1 digit numbers: 123456789           -   9 * 1 digit
2 digit numbers: 101112...9899       -  90 * 2 digits
3 digit numbers: 100101102...998999  - 900 * 3 digits
4 digit numbers: ...

现在您可以执行递归解决方案,一次跳过 9×10k×k 个数字,直到到达基数n 在当前幅度的数字范围内的情况。

当您知道要查看的特定范围时,很容易找到nth 数字。首先将n 除以每个数字的长度。这会将数字偏移量变成数字偏移量。现在将 10k 添加到其中以获取要查看的实际数字。此时需要在给定数字中找到特定数字。

以n = 1234为例:

  • n &gt; 9,所以它不在个位数范围内:
    • 跳过一位数范围(即n -= 9)并继续处理两位数...
  • n &gt; 90 * 2 所以也不在两位数范围内
    • 跳过 2 位数范围(即n -= 90*2)并继续使用 3 位数号码...
  • 现在是n &lt; 900 * 3,所以我们正在寻找100101102... 序列中的一个数字
  • 由于此序列中的每个数字都是 3 位长,我们可以通过 100 + n / 3 找到要查找的特定数字。在这种情况下,这等于 448。
  • 我们现在只需计算n % 3(在这种情况下等于1)来找到要选择的数字。因此,最终结果是4。

这里有一个 Java 解决方案:

public static char nthDigit(int n, int digitsInFirstNum) {
    int magnitude = (int) Math.pow(10, digitsInFirstNum - 1);
    int digitsInMagnitude = 9 * magnitude * digitsInFirstNum;

    if (n < digitsInMagnitude) {
        int number = magnitude + n / digitsInFirstNum;
        int digitPos = n % digitsInFirstNum;
        return String.valueOf(number).charAt(digitPos);
    }

    return nthDigit(n - digitsInMagnitude, digitsInFirstNum + 1);
}

public static char nthDigit(int n) {
    return nthDigit(n, 1);
}

【讨论】:

  • 我认为你的解决方案是正确的,但是为什么你使用递归而不是简单的循环呢?
  • 这正是我思考问题的方式。它也可以作为循环实现。
猜你喜欢
  • 2019-10-17
  • 1970-01-01
  • 1970-01-01
  • 2017-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-09
  • 2016-09-28
相关资源
最近更新 更多