算法-苹果

版权声明:来一来,看一看,有钱的捧个人场,没钱的你不得捧个人场 https://blog.csdn.net/wait_for_eva/article/details/83687095

问解

m个苹果n个篮,可空可满,不重复,问几何?

def split(apple, basket):
    if apple < 0 or basket <=  0:
        return 0
    if apple == 0 or basket == 1:
        return 1
    if basket > apple:
        return split(apple, apple)
    return split(apple, basket - 1) + split(apple - basket, basket)

基本

  • 可为空,零算元素,(6,0,0)
  • 排列不组合,(1,2,3)=(3,2,1)=(1,3,2)=(2,3,1)=(2,1,3)=(3,1,2)

转换

  • 零转空
    if basket > apple:
        return split(apple, apple)

如果可能为空,就不考虑其他篮子,施行全占政策

split(apple - basket, basket)

因为全占,每个篮子至少一个来填充,然后开始分发

  • 排列转递减
split(apple, basket - 1)

比如有三个篮子,我们可以的分法可以专门填充一个,专门填充两个,三个全部填充。

递减就是反过来看了,逐渐舍弃篮子,放空,然后分发。

split(apple - basket, basket)

没错,还是它。这算是作用最多的一步。

它不仅是作为全占的一员而舍弃基本占用(apple - basket),同时,也负责组合。

回顾一下

    if basket > apple:
        return split(apple, apple)

这一步会自动除去空篮子,然后split(apple - basket, basket)逐级的递减。

保证了大数一直也只能出现在前面:(3,2,1)最后只有这种选择。

  • 递归组合
split(apple, basket - 1) + split(apple - basket, basket)

我觉得最难理解的,就是这了,这是计算机思维和我们思维的差异造成的。

两个部分完全不可分割。

  • 第一部分

第一个部分,表示留空,在已有的基础之上再进行组合

在递归中,留空不断增大,然后反向的追回了我们的先一分二,二分三的思维模式。

  • 第二部分

如果不留空,就只能均分,全占。

不断的舍弃公有部分,让资源递减,减少了所谓的大小排列顺序。

动态

  • 全占

不断的均分,消耗资源,直到源头

  • 留空

留空之后,剩余的继续排列,不断的留空,直到篮子消耗

  • 新逻辑

当已有了(2,2)的情况

均分,就成了(3, 3)

留空,就成了(2, 4)

也就是说,在已经分配的基础之上,所谓留空,是对数据的组合。

切割数据的基本共同点,关注差异

(3, 3) - (2, 2) = (1, 1):不留空

(2, 4) - (2, 2) = (0, 2):留空

有时候想不通,大概就是啥时候进行的组合让我们找不到踪迹。

这种思维,还需要努力学习。

思路

如果一个篮子都不空的话,我需要舍弃apple-basket个苹果来强占。

接下来,我有面临同样的问题,是不是继续强占

一直是这个样子的。

假设0也是一个元素,我们首先全占了所有的篮子。

接下来的还是这个问题,继续全占还是舍弃一两个。

递归的分支,会让我们逐渐的舍弃和尽力的填充,最终遍历所有的可能。

  • 盲点

什么时候开始填充的?这或许就是我们的致命点。

填充了和没填充有区别么?

填充了0个和填充来了100个有区别么?

我们能够轻易舍弃和接收空篮子,却不太能够想象丢弃1苹果的篮子。

0也是元素,丢弃占0的和丢弃占1的都是同一个动作,都是在遍历组合。

所谓的留空,不是简单的不填充篮子,而是是否继续均发

也不过是开启树上的另一条枝干,没有舍弃

太执着于片面,容易看不清全貌,把握不住本质

  • 行动

现在,每个篮子都填充了0个苹果,你要继续填充还是放弃某一个。

现在,每个篮子都填充了1个苹果,你要继续填充还是放弃某一个。

现在,每个篮子都填充了2个苹果,你要继续填充还是放弃某一个。

现在,每个篮子都填充了3个苹果,你要继续填充还是放弃某一个。

没放弃的,还留下着,这是split(apple, basket - 1) + split(apple - basket, basket)中的第二步。

篮子全部占满的一个分支。

总共n个篮子,你要填充 n个篮子?

总共n个篮子,你要填充n-1个篮子?

总共n个篮子,你要填充n-2个篮子?

总共n个篮子,你要填充n-3个篮子?

总共n个篮子,你要填充n-4个篮子?

这是split(apple, basket - 1) + split(apple - basket, basket)中的第一步。

两个方面,最终完成遍历

正如null可以表示空对象,也可以是一个标记,可以是失败,也可以是成功。

0,是空,还是,或者两者都是。

但是,不同的方面,表现一样,本质却不一样,都必须得考虑到,然后去探索到,才能覆盖全面。

猜你喜欢

转载自blog.csdn.net/wait_for_eva/article/details/83687095