题目: 一种杯子,若在第N层被摔破,则在任何比N高的楼层均会破;若在第M层不破,则在任何比M低的楼层均不会破。给你两个这样的杯子,让你在100层高的楼层中测试,要求用最少的测试次数找出恰巧会使杯子破碎的楼层。
解题思路:
1个杯子尝试的次数假设为n, 则可能尝试有1次, 2次, 3次,...,n次, 但,要求最少的测试次数(楼层不可能重复), 所以尝试总数还应该是这次大于等于100, 上次计算得出的尝试总数小于100
即1+2+3+...+n >= 100
简化公式: 1/2n(n+1) >= 100
求得n的最小整数为14
function bei({n}) {
let currentNum = 0
if(n == 1) return {n:1}
if(n > 1 && n <= 100) {
const obj = bei({n: n - 1})
if(typeof obj === 'object') {
const pre = obj.n; // 上次尝试总数
currentNum = n + pre // 此次尝试总数
if(currentNum >= 100 && pre < 100) {
console.log(n, pre, currentNum)// 14 91 105
print(n)
return
}
return {n:currentNum, parts: n}
}
}
}
function print(minNum) {
console.log(minNum) // 14
}
bei({n:100})
优化: 除了最小值, 其他可能的区间:
var arr = []
function bei2({ n, step }) {
let currentNum = 0
const end = n + step - 1
if (end) {
arr.push([n, end])
if (n >= 100) {
return
}
const start = end
const end2 = start + step - 1
if (start > end2) return
return end + 1 >= 100 ? arr.push([100]) : bei2({ n: end + 1, step: step - 1 })
}
// 计算第一个最小测试区间, 后面的区间数字间隔逐渐变小
while (n >= 1 && n <= 100) {
currentNum += n // 此次尝试总数
if (currentNum >= 100) {
arr.push([1, n])
print(n)
return bei2({ n: n + 1, step: n - 1 })
}
n++
}
}
bei2({ n: 1 })
console.log(arr)
// 一种杯子,若在第N层被摔破,则在任何比N高的楼层均会破,若在第M层不破,则在任何比M低的楼层均会破,给你两个这样的杯子,让你在100层高的楼层中测试,要求用最少的测试次数找出恰巧会使杯子破碎的楼层。
// 第一个杯子可能的投掷楼层分别为:14,27,39,50,60,69,77,84,90,95,99,100
// 14 + 13 => 27
// 27 + 12 = 39
// 39 + 11 => 50
// 50 + 10 => 60
// 60 + 9 => 69
// 69 + 8 => 77
// 77 + 7 => 84
// 84 + 6 => 90
// 90 + 5 => 95
// 95 + 4 => 99
// 最大100
当我们用14时,我们可以得出范围为1~14, 15~27, 28~39... 96~99, 100
参考地址: 100层楼两个杯子找杯子碎的临界点-CSDN博客