这种“电话词”算法的Big-O复杂度是多少?

时间:2012-04-18 22:08:32

标签: ruby algorithm loops

这不是家庭作业,只是我在网上发现的一个看起来很有趣的面试问题。

所以我首先看了一下这个:Telephone Words problem - 但它似乎措辞不力/引起了一些争议。我的问题几乎是一样的,除了我的问题更多的是它背后的时间复杂性。

当您输入10位数的电话号码时,您希望列出所有可能的单词。所以这就是我所做的:`

def main(telephone_string)
  hsh = {1 => "1", 2 => ["a","b","c"], 3 => ["d","e","f"], 4 => ["g","h","i"], 
         5 => ["j","k","l"], 6 => ["m","n","o"], 7 => ["p","q","r","s"], 
         8 => ["t","u","v"], 9 => ["w","x","y","z"], 0 => "0" }
  telephone_array = telephone_string.split("-")
  three_number_string = telephone_array[1]
  four_number_string = telephone_array[2]
  string = ""
  result_array = []
  hsh[three_number_string[0].to_i].each do |letter|
    hsh[three_number_string[1].to_i].each do |second_letter|
      string = letter + second_letter
      hsh[three_number_string[2].to_i].each do |third_letter|
        new_string = string + third_letter
        result_array << new_string
      end
    end 
  end

  second_string = ""
  second_result = []
  hsh[four_number_string[0].to_i].each do |letter|
    hsh[four_number_string[1].to_i].each do |second_letter|
      second_string = letter + second_letter
      hsh[four_number_string[2].to_i].each do |third_letter|
        new_string = second_string + third_letter
        hsh[four_number_string[3].to_i].each do |fourth_letter|
          last_string = new_string + fourth_letter
          second_result << last_string
        end
      end
   end
end
  puts result_array.inspect
  puts second_result.inspect
end

首先,这是我在几分钟内一起攻击的内容,没有进行任何重构。所以我为凌乱的代码道歉,我刚刚开始学习Ruby 6周前,所以请耐心等待我!

所以终于到我的问题:我想知道这种方法的时间复杂性是多少。我的猜测是它会是O(n ^ 4),因为第二个循环(对于四个字母的单词)嵌套了四次。虽然我不是很积极。所以我想知道这是否正确,以及是否有更好的方法来解决这个问题。

2 个答案:

答案 0 :(得分:0)

这实际上是一个恒定时间算法,所以O(1)(或更明确,O(4 ^ 3 + 4 ^ 4))

这是一个恒定时间算法的原因是,对于电话号码中的每个数字,您将迭代一个固定数字(最多4个)可能的字母,这是事先已知的(这就是为什么你可以放{{ 1}}静态地进入你的方法)。

一种可能的优化方法是在您知道当前前缀没有单词时停止搜索。例如,如果3位数字是“234”,你可以忽略所有以“bd”开头的字符串(有一些bd-words,比如“bdellid”,但没有三字母,至少在我的的/ usr /共享/字典/字)。

答案 1 :(得分:-1)

从原来的措辞来看,我认为这是要求所有可能性,而不是作为输出的可能性数量。

不幸的是,如果您需要返回每个组合,则无法将复杂性降低到指定键所确定的范围之下。

如果它只是数字,它可能是恒定的时间。但是,要将它们全部打印出来,最终结果在很大程度上取决于假设:

1)假设你要检查的所有单词都是由字母组成的,你只需要检查2到9中的8个键。如果这不正确,只需在下面的函数中输出8。 / p>

2)假设所有键的布局与此处设置完全一样(没有octothorpes或星号),空数组的内容在最后一个单词中不占用空间。

{
  1 => [],
  2 => ["a", "b", "c"],
  3 => ["d", "e", "f"],
  4 => ["g", "h", "i"], 
  5 => ["j", "k", "l"],
  6 => ["m", "n", "o"],
  7 => ["p", "q", "r", "s"],
  8 => ["t", "u", "v"],
  9 => ["w", "x", "y", "z"],
  0 => []
}

在每个阶段,您只需检查下一步的可能性数量,并将每个可能的选择附加到字符串的末尾。如果你这样做,那么,最小时间(基本上)是恒定时间(0,如果数字由全1和0组成)。然而,函数将是O(4 ^ n),其中n在10处达到最大值。如果它们每次达到7或9,则最大可能的组合数将是4 ^ 10。

至于你的代码,我会建议一个循环,带有一些基本的嵌套循环。这是Ruby中的代码,虽然我还没有运行它,所以可能存在语法错误。

def get_words(number_string)
  hsh = {"2" => ["a", "b", "c"], 
         "3" => ["d", "e", "f"], 
         "4" => ["g", "h", "i"], 
         "5" => ["j", "k", "l"], 
         "6" => ["m", "n", "o"], 
         "7" => ["p", "q", "r", "s"], 
         "8" => ["t", "u", "v"], 
         "9" => ["w", "x", "y", "z"]}

  possible_array =  hsh.keys
  number_array = number_string.split("").reject{|x| possible_array.include?(x)}

  if number_array.length > 0
    array = hsh[number_array[0]]
  end

  unless number_array[1,-1].nil?
        number_array.each do |digit|
            new_array = Array.new()
            array.each do |combo|
                hsh[digit].each do |new|
                new_array = new_array + [combo + new]
            end
        end
        array = new_array
    end
    new_array
end