求职 算法题:第 77 题 - 爬楼梯

MmoMartin · 2020年06月14日 · 最后由 槽神 回复于 2020年06月18日 · 763 次阅读

两道算法题:
1、写一个树的中序排序算法。【这道题固定模式,没啥好玩的,自己去熟悉就可以了,没有下面例子题目有趣】

2、是 Leecode 的第 70. 爬楼梯面试题目:
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。

我的解题思路:

from itertools import permutations
def step_all(n):
    total = 0
    """
    :param n: 总台阶,每次只走1或2,组合有多少种

    :return: all
    """
    if n == 1:
        return 1
    elif n == 2:
        return 2
    elif n >= 3:
        if n % 2 == 0:
            step_min = int(n/2)  # 最小的step登顶
            for i in range(step_min+1, n):
                len_i = i  # 长度
                count_two = (step_min - (len_i - step_min))
                count_one = len_i - count_two
                list_step = [2 for x in range(count_two)]
                list_step.extend([1 for y in range(count_one)])
                li_per = list(permutations(list_step))
                count = len(set(li_per))
                total += count
            return total+2
        elif n % 2 == 1:
            total = 0
            step_min = int((n-1) / 2) + 1  # 最小的step登顶,step-min为2的个数 3:2  4:1   5:0
            for i in range(step_min+1, n):
                len_i = i  # 长度
                count_two = (step_min - (len_i-(step_min-1)))
                print(count_two)
                count_one = len_i - count_two
                list_step = [2 for x in range(count_two)]
                list_step.extend([1 for y in range(count_one)])
                li_per = list(permutations(list_step))
                count = len(set(li_per))
                print(count)
                total += count
            print(total)
            step_min_list = [2 for z in range(step_min-1)]
            step_min_list.extend([1 for i in range(1)])
            li_per = list(permutations(step_min_list))
            step_min_list_count = len(set(li_per))
            total = total + step_min_list_count + 1
            return total

上述的代码在 1-15 之间的运行是没问题的,所以便提交到 Leecode,发现报错。
然后便换一种方式了,原理不变,借助数学组合公式并去重得出结果【核心是:对 [1,1,1,2,2,1,1] 类似的数据进行去重组合】

def step_all(n):
    def mutil_sum(start_x, end_x=None):
        sum_total = 1
        if end_x:
            print(end_x)
            for i in range(start_x, start_x - end_x, -1):
                sum_total *= i
            return sum_total
        for i in range(1, start_x + 1):
            sum_total *= i
        return sum_total
    if n == 1:
        return 1
    elif n == 2:
        return 2
    elif n >= 3:
        if n % 2 == 0:
            total = 0
            min_len = int((n / 2))
            count_two = min_len
            count_one = 0
            for i in range(min_len, n):
                print("只需%s次爬上楼顶"%(count_two + count_one))
                print("2的个数:%s" % count_two)
                print("1的个数:%s" % count_one)
                if count_two >= count_one:
                    type_sum = mutil_sum((count_one+count_two), count_two) / mutil_sum(count_two)
                    total += type_sum
                    print("只需%s次爬上楼顶的组合数为:%s"%((count_two + count_one), type_sum))
                else:
                    type_sum = mutil_sum((count_one + count_two), count_one) / mutil_sum(count_one)
                    total += type_sum
                    print("只需%s次爬上楼顶的组合数为:%s" % ((count_two + count_one), type_sum))
                count_two -= 1
                count_one += 2
            print("只需%s次爬上楼顶" % (count_two + count_one))
            print("2的个数:%s" % count_two)
            print("1的个数:%s" % count_one)
            if count_two >= count_one:
                print("%s >= %s"%(count_two,  count_one))
                type_sum = (mutil_sum((count_one+count_two), count_two)) / mutil_sum(count_two)
                total += type_sum
                print("只需%s次爬上楼顶的组合数为:%s" % ((count_two + count_one), type_sum))
            else:
                type_sum = (mutil_sum((count_one+count_two), count_two)) / mutil_sum(count_one)
                total += type_sum
                print("只需%s次爬上楼顶的组合数为:%s" % ((count_two + count_one), type_sum))
            return total
        if n % 2 == 1:
            total = 0
            min_len = int(((n - 1) / 2)) + 1
            count_two = min_len - 1
            count_one = 1
            for i in range(min_len, n):
                print("只需%s次爬上楼顶"%(count_two + count_one))
                print("2的个数:%s" % count_two)
                print("1的个数:%s" % count_one)
                if count_two >= count_one:
                    type_sum = (mutil_sum((count_one+count_two), count_two)) / mutil_sum(count_two)
                    total += type_sum
                    print("只需%s次爬上楼顶的组合数为:%s"%((count_two + count_one), type_sum))
                else:
                    type_sum = (mutil_sum((count_one+count_two), count_one)) / mutil_sum(count_one)
                    total += type_sum
                    print("只需%s次爬上楼顶的组合数为:%s" % ((count_two + count_one), type_sum))
                count_two -= 1
                count_one += 2
            print("只需%s次爬上楼顶" % (count_two + count_one))
            print("2的个数:%s" % count_two)
            print("1的个数:%s" % count_one)
            if count_two >= count_one:
                type_sum = (mutil_sum((count_one+count_two), count_two)) / mutil_sum(count_two)
                total += type_sum
                print("只需%s次爬上楼顶的组合数为:%s" % ((count_two + count_one), type_sum))
            else:
                type_sum = (mutil_sum((count_one+count_two), count_one)) / mutil_sum(count_one)
                total += type_sum
                print("只需%s次爬上楼顶的组合数为:%s" % ((count_two + count_one), type_sum))
            return total

运行结果 OK,代码的执行效率底下,需要进行优化,目前只是能实现功能而已。可惜当时没时间。没去发现规律。不过我觉得这种更好玩,比那种直接写二叉树啥的固定模式好玩。用例子来描述算法,这方式值得提倡。最近学习了动态规划,利用动态规划试下

共收到 6 条回复 时间 点赞

爬楼梯这个题目好多年的经典了

Vince 回复

不知道哦,刚开始学习算法,面试了阿里跟腾讯后,知道自己这块不足,准备段时间再次投递简历

爬楼梯的题不是斐波那契数列吗?一个递归就可以解决呀

kuale 回复

需要应用到组合排序的

Vince 回复

我尽然不知道,我靠,孤陋寡闻了

kuale 回复

动态规划 + 备忘录,递归或者双循环遍历都可以

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