问解
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
,是空,还是数
,或者两者都是。但是,不同的方面,表现一样,本质却不一样,都必须得考虑到,然后去探索到,才能覆盖全面。