【学习现场】如何求取第一万零一个丑数?

640?wx_fmt=png

小史是一个应届生,虽然学的是电子专业,但是自己业余时间每天都会坚持学习编程、计算机、互联网等相关方面的知识,特别是算法的训练。

今天小史又在研究一道算法题了。

【学习现场】

640?wx_fmt=jpeg

今天小史又在研究一种特殊的数字。

只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。 习惯上我们把1当做是第一个丑数。

题目:第10001个丑数是多少?

题目要求:请编程计算出结果,如果数字过大,给出它对100007取模之后的结果。

小史拿到题目后略微思考,很快有了思路,开始写代码了。读者们,你能比小史更快吗?


学习现场的玩法:

1)计算机编程解决题目,答案在公众号后台进行回复,回复格式为解答+答案,如答案为2,则回复解答2

2)回答正确后,会出现提示,同时有一个交流群的二维码,可进入“场粉交流群”,群内都是算法爱好者和互联网从业人士

3)注意,每道题都有有效期,有效期过后题目作废,只能等待下一道题了

4)学习现场是小史平时练习的题目,下一道题公布的时候,同时会公布上一道题小史的解法供大家参考,也欢迎大家将自己的解法进行留言

5)希望大家玩得开心


上期回顾:

小史解答:

1、考虑几种情况,起手右括号,怎么都不合法,例如:)(())(

2、前面括号抵消之后剩下起手右括号,还是不合法,例如:()())(

3、剩下的只要左右括号总个数相同,都是合法情况

4、有点像“栈”的过程,入栈出栈

5、我们可以用递归来实现代码,每一次都是添加左括号或者添加右括号的过程,注意递归函数的理解,看代码

CountBracketPair.java

/**
 * @author xiaoshi on 2018/12/23.
 */
public class CountBracketPair {

    private int count(int total, int left, int right) {
        // 如果左括号用完,剩下只能填右括号,记录这种方法
        if(left == total) {
            return 1;
        }
        // 添加一个左括号,左括号在任何时候都能添加
        int leftCount = count(total, left + 1, right);
        // 添加一个右括号,注意右括号只有在比左括号少的情况下才能添加,否则就不合法
        int rightCount = 0;
        if(left > right) {
            rightCount = count(total, left, right + 1);
        }
        // 两种情况数量相加
        return leftCount + rightCount;
    }

    // total代表总共多少对括号
    public int countPair(int total) {

        // left和right表示已经使用的左括号和右括号,初始为0
        int left = 0, right = 0;

        // 递归计算结果
        return count(total, left, right);

    }

}

(友情提示:可左右滑动)

Main.java

/**
 * @author xiaoshi on 2018/12/23.
 */
public class Main {

    public static void main(String[] args) {

        CountBracketPair countBracketPair = new CountBracketPair();

        System.out.println(countBracketPair.countPair(12));
        System.out.println(countBracketPair.countPair(12) % 100007);

    }

}

(友情提示:可左右滑动)

运行结果:

208012
7998

(友情提示:可左右滑动)

网友解答:

1、都说二流的程序员用算法,一流的程序员用数学

2、这道题其实是经典的“卡特兰数”问题,关于什么是卡特兰数,大家可以自行google

3、卡特兰数有一个通项公式,利用它可以直接计算结果

4、卡特兰数可以解决很多问题,如矩阵连乘括号化、出栈次序、凸多边形三角形划分等,值得研究

看代码,本代码由网友离子云大神提供,python版本:

#!/usr/bin/python3
# -*- coding: utf-8 -*-  
def simple_catalan(n):
  result = 1
  # 注意range是闭区间
  for numerator in range(n+1,2*n+1):
    result *= numerator
  for denominator in range(1,n+1+1):
    result //= denominator
  return result

if __name__ == '__main__':
  print(simple_catalan(12)%100007)

(友情提示:可左右滑动)

运行结果:

7998

(友情提示:可左右滑动)


学习现场是互联网侦察继面试现场后推出的一个姊妹现场,旨在帮助读者进行算法题的训练,同时提供学习交流群,希望对大家的学习和算法提高有所帮助。

640?wx_fmt=jpeg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值