Ruby 求高效算法

michael_roshen · 2014年05月28日 · 最后由 5swords 回复于 2014年06月01日 · 2573 次阅读

统计出从 0-n 之间 1 的个数,如 n=13,f(0..13)=>6,0 到 13 有 6 个数带有 1,要求不能用字符串方式计算,只能用数学方式。

def f(range)  
  range.inject do |sum, n|  
    while n > 0  
      sum += 1 if n % 10 == 1  
      n = n / 10  
    end  
    sum  
  end  
end  

有一道面试题,某次一面试官觉得不够高效,百思不得其解,求高效算法

个人非常恶心这种面试题,都是捡大公司剩下的..

#1 楼 @saiga 扫噶,死了一片脑细胞

我觉得还是自己创业好了,前期来说 CRUD 够用了,不会遇到这些变态的需求。等项目做起来,有性能问题了,再收集这些变态的题目招点人,呵呵

这些算法题还是挺欢乐的,一定要保持对算法的兴趣哟。 这到题目我的思路是这样的: 我觉得你也不会看。。

先分组,1-9 做组 1 10 - 19 组 2 ...... 100 - 199 组 3

满租的情况 对于没一组,1 开头的有一个公式,非 1 开头的又有一个公式。。。

不满租的情况 组内所有数除以 10,记 1 知道可以填满某个租,用公式计算。 余下的重复这个过程,知道为个位数。

应该是可以。。。

#4 楼 @Peter 你是那个 Peter 吗,哈哈

#5 楼 @waksana 我很感兴趣啊,讲个通俗易懂,又不是提高效率的,太绕的,出 bug 都找不出来

#7 楼 @michael_roshen 我估计你找的是那个做视频的 @happypeter

#9 楼 @Peter 还真是重名的,我还以为是换了头像

irb(main):009:0> sum = 0 irb(main):016:0> [1..13].each do |e| irb(main):017:1 (e.to_s).gsub(/[1]/) {|s| sum +=1} irb(main):018:1> end => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] irb(main):019:0> sum => 6

把 13 换成 n 就可以了。

#11 楼 @ucooling 要求不能用字符串方式计算,只能用数学方式。 to_s 和 gsub 应该不合格啊

#12 楼 @leozwa 奥,没注意不能用字符串方法,这种题目其实挺烦人的,基本上用数学方法要不就是用一些很老土的方法实现,时间复杂度和空间复杂度都很高,要不就是用一些方法的基本上平时不怎么会用的到的调用方式。

#13 楼 @ucooling
是啊 打着编程的幌子考数学底子...

#9 楼 @Peter 我来了,不过题我也不太会做,抱歉!

16 楼 已删除

0 到 13 有 6 个数带有 1

这句话有问题,是 5 个数带有 1,但是 1 的出现总数是 6 次。猜是 1 的出现总数。

这题是要找规律,如 0..99,1 在个位上出现了 10 次,在 10 位上出现了 10 次。那 0..13 在个位上出现 2 次,10 位上 4 次。如 0..256,1 在个位上出现 26*1 次,在 10 位上出现 3*10 次,在 100 位出现 1*100 次。如 0..1111,1 在个位上出现 112 次,在 10 位上出现 11*10+2 次,在百位上出现 1*100+12 次,在千位上出现 112 次,共 448 次。

先做个字符版的 f 做验证,再做个 g 来完成。

def f(range)
  range.to_a.map(&:to_s).join.count('1')
end

def g(range)
  n = range.last
  m = nil
  sum = 0
  x = 1
  while (n > 0) do
    m = n % 10
    n = n / 10
    sum += n*x
    if m > 1
      sum += x
    elsif m > 0
      sum += range.last % x + 1
    end
    x = x * 10
  end
  sum
end

class String
  def to_range
    t = self.split('..')
    (t.first.to_i)..(t.last.to_i)
  end
end

puts "f: #{f(ARGV[0].to_range)}, g: #{g(ARGV[0].to_range)}"

结果是 ruby a.rb 0..13 f: 6, g: 6 ruby a.rb 0..99 f: 20, g: 20 ruby a.rb 0..256 f: 156, g: 156 ruby a.rb 0..1111 f: 448, g: 448

需要 登录 后方可回复, 如果你还没有账号请 注册新账号