本文正在参加「Java主题月 - Java 刷题打卡」,详情查看 活动链接
题目描述
跳水板
你正在使用一堆木板建造跳水板。有两种类型的木板,其中长度较短的木板长度为shorter,长度较长的木板长度为longer。你必须正好使用k块木板。编写一个方法,生成跳水板所有可能的长度。
返回的长度需要从小到大排列。
示例 1:
输入:
shorter = 1
longer = 2
k = 3
输出: [3,4,5,6]
解释:
可以使用 3 次 shorter,得到结果 3;使用 2 次 shorter 和 1 次 longer,得到结果 4 。以此类推,得到最终结果。
提示:
- 0 < shorter <= longer
- 0 <= k <= 100000
思路分析
在面对这样一道题的时候,我们很容易想起递归解法,递归解法的时间复杂度是,同时还有一种解法是记忆化解法,时间复杂度也是,但是看下面的提示,k 的值的最大范围还是挺大的,所以在 leetcode 使用这两种解法时出现超时。所以我们寻求其他解法。
首先考虑边界情况:
如果 k = 0,则不能建造任何跳水板,因此返回空数组。
如果 shorter 和 longer 相等,则建造的跳水板的长度是唯一的,都等于 shorter * k。
然后考虑一般情况,因为是一长一短,因为短木板和长木板是一共使用 k 块,所以一共有 k+1 种情况,每种组合下建造的跳水板长度都是不一样的,一共有 k + 1 中不同的长度,这个很重要,正是因为一长一短,假设 k = 5,一开始 5 个都是 shorter,然后 4 个 shorter,这样 shorter 的个数不断减少,longer 的长度却不断增加,总的长度也是不断递增的。所以一共有 k+1 个不同的长度。同时这样也是升序排列的。
该解法的时间复杂度是,空间复杂度也是。
代码展示
解法一:时间复杂度是,其中 k 是木板数量。短木板和长木板一共使用 k 块,一共有 k+1 种组合,对于每种组合都要计算跳水板的长度。空间复杂度是,除了返回值以外,额外使用的空间复杂度为常数。
//16.11 跳水板 时间复杂度O(n),空间复杂度O(1)
public static int[] divingBoard(int shorter, int longer, int k) {
if (k == 0) {
return new int[]{};
}
if (shorter == longer) {
return new int[]{shorter * k};
}
int[] array = new int[k + 1];
for (int i = 0; i <= k; i++) {
int a = shorter * (k-i) + longer * i;
array[i] = a;
}
return array;
}
总结
解答该类题时很容易想到递归解法,但是同时也要考虑到递归的耗时和深度,因为木板是一长一短,所以总的情况是 k + 1。