【问题标题】:Converting prime numbers [duplicate]转换素数[重复]
【发布时间】:2011-04-08 21:12:10
【问题描述】:

可能重复:
Help with algorithm problem from SPOJ

遇到了这个面试问题。给定两个 n 位质数,将第一个质数转换为第二个质数,一次改变一个数字。中间数也必须是素数。这需要以最少的步骤完成(检查素数和更改数字被视为步骤)

例如将 1033 转换为 8179 (1033->1733->3733->.......->8179)

【问题讨论】:

  • 是否保证解决方案存在?换句话说,是否选择了两个 n 位素数,以便始终存在形成解的中间素数?
  • 这类问题让我觉得面试官只是想展示他们有多聪明,而不是试图从候选人那里得到有用的东西。
  • @NullUserException 面试官告诉我她可以通过 8 个步骤将 1033 转换为 8179
  • 看到这个 ..spoj.pl/problems/PPATH 你可以搜索资源链接找到解决方案
  • @Manas:“分 8 步将 1033 转换为 8179”。她有没有说这些步骤中有多少是数字变化,有多少是素数检查?问题是数字变化是解决方案的属性,而素数检查是找到该解决方案的算法的属性。我看不出这两者是如何共同测量的。

标签: algorithm primes


【解决方案1】:

这是(一个特例)最短路径问题。您正在寻找两个指定顶点之间的最小路径,通过图中顶点是素数,并且当且仅当它们以基数 10 表示时,它们仅相差一个数字时,顶点才由边连接。所有边都有权重1.

如果对这种特殊情况的特定结构没有更好的想法:对于 4 位数字,使用您最喜欢的寻路算法肯定可以在可忽略不计的时间内完成。

编辑:哎呀,刚刚注意到“检查素数”是一个步骤。

我不再理解这个问题。为了产生链 1033 -> 1733 -> 3733,您必须“检查素数”多少个数字?如果我用筛子找出所有小于 10000 的素数,那么它走了多少“步”?

【讨论】:

    【解决方案2】:

    最好的方法可能是depth-first search with iterative deepening,因为要求的步数最少。初始深度将是两个数字之间不同的位数。

    【讨论】:

      【解决方案3】:

      这可以被认为是一个图形问题。我会尝试以下方式:

      • 生成所有 N 位素数 (P),不包括起始素数 (A) 和结束素数 (B)。
      • 计算从 A 到所有 P 的汉明距离,选择距离为 1 的,将它们设置为 A 的子级。
      • 重复此操作,直到 P 中的所有素数都已放入图中或找到通往 B 的路径。
      • 走从 A 到 B 的最短路径。

      【讨论】:

      • 给出的示例的最短路径实际上超出了素数 A ... B 的范围:1033 -> 1733 -> 3733 -> 3739 -> 3779 -> 8779 -> 8179。所以我认为您的第一步需要是“生成具有指定位数的所有素数”。
      • 好点!固定..谢谢。有一条上船。 :)
      • 如果上述图中没有所有边的汉明距离为1的路径怎么办?
      • @Frederick:那就没有办法了。
      【解决方案4】:

      下雨的星期一晚上的挑战很不错(无论如何,它就在这里!)。这可以使用Dijkstra's algorithm 来完成。第一步是创建一个包含所有 4 位素数的 graph。然后使用 Dijkstra 算法找到开始/结束素数之间的最短路径。这是 Python 中的一个实现:

      #! /usr/bin/python -tt
      
      # run as: findpath start end
      
      import sys
      
      (start, end) = map(int, sys.argv[1:3])
      
      # http://primes.utm.edu/lists/small/10000.txt
      f = open("10000.txt", "r")
      lines = f.readlines()
      f.close
      lines = lines[4:-1] # remove header/footer
      all = "".join(lines) # join lines
      all = all.split()
      all = map(int, all)
      
      # only want the 4-digit primes
      fourdigit = [p for p in all if 1000 <= p and p <= 9999]
      
      # returns digits in a number
      digits = lambda x: map(int, str(x))
      
      # cache of digits for each prime
      digits_for_nums = {}
      
      # returns digits in a number (using cache)
      def digits_for_num(x):
          global digits_for_nums
          if x not in digits_for_nums:
              digits_for_nums[x] = digits(x)
          return digits_for_nums[x]
      
      # returns 1 if digits are same, 0 otherwise
      diff = lambda pair: 1 if pair[0] == pair[1] else 0
      
      # computes number of identical digits in two numbers
      def distance(a, b):
          pair = (a, b)
          pair = map(digits_for_num, pair)
          pair = zip(pair[0], pair[1])
          pair = map(diff, pair)
          same = sum(pair)
          return same
      
      # adjacency list representation of graph of primes
      edges = {}
      
      # construct graph
      for a in fourdigit:
          edges[a] = []
          for b in fourdigit:
              if distance(a, b) == 3:
                  edges[a].append(b)
      
      infinity = sys.maxint
      
      def smallest():
          global dist, Q
          minimum = infinity
          which = None
          for v in Q:
              if dist[v] <= minimum:
                  which = v
                  minimum = dist[v]
          return which
      
      # Dijkstra's algorithm
      dist = {}
      previous = {}
      Q = edges.keys()
      for v in Q:
          dist[v] = infinity
          previous[v] = None
      dist[start] = 0
      while len(Q) > 0:
          u = smallest()
          if dist[u] == infinity:
              break
          Q.remove(u)
          for v in edges[u]:
              alt = dist[u] + 1
              if alt < dist[v]:
                  dist[v] = alt
                  previous[v] = u
      
      # get path between start/end nodes
      num = end
      path = [num]
      while num != start:
          num = previous[num]
          path.insert(0, num)
      print path
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-08-21
        • 2018-05-05
        • 2015-10-24
        • 1970-01-01
        • 2019-02-12
        • 2012-09-27
        • 2019-12-11
        • 1970-01-01
        相关资源
        最近更新 更多