目录
小明从糖果盒中随意抓一把糖果,每次小明会取出一半的糖果分给同学们。
当糖果不能平均分配时,小明可以选择从糖果盒中(假设盒中糖果足够)取出一个糖果或放回一个糖果。
小明最少需要多少次(取出、放回和平均分配均记一次),能将手中糖果分至只剩一颗。
抓取的糖果数(<10000000000):15
最少分至一颗糖果的次数:5
输入
- 15
输出
- 5
输入
- 3
输出
- 2
输入
- 6
输出
- 4
假设给定数为n,首先判定n是否为2^m,m为整数
这里如何让n变为2^m呢?比如n=6,它有两种选择
- /* JavaScript Node ACM模式 控制台输入获取 */
- const readline = require("readline");
-
- const rl = readline.createInterface({
- input: process.stdin,
- output: process.stdout,
- });
-
- rl.on("line", (line) => {
- console.log(distribute(line));
- });
-
- /* 分糖果 */
- function distribute(count) {
- if (count === 0) {
- return 0;
- }
-
- // 取count底数为2的幂
- const pow = Math.log2(count);
- // 如果幂是整数,表示可以直接平均分配,所以此时幂就是总次数
- if (Number.isInteger(pow)) {
- return pow;
- }
-
- // 如果幂不是整数,则表示无法直接平分,所以分别获取幂的ceil值和floor值
- const ceil_pow = Math.ceil(pow);
- const floor_pow = Math.floor(pow);
-
- const ceil_count = Math.pow(2, ceil_pow);
- const floor_count = Math.pow(2, floor_pow);
-
- // ceil_diff表示要取出多少次糖果,floor_diff表示要放回多少次糖果
- const ceil_diff = Math.abs(ceil_count - count);
- const floor_diff = Math.abs(floor_count - count);
-
- return Math.min(ceil_pow + ceil_diff, floor_pow + floor_diff);
- }
- /* JavaScript Node ACM模式 控制台输入获取 */
- const readline = require("readline");
-
- const rl = readline.createInterface({
- input: process.stdin,
- output: process.stdout,
- });
-
- rl.on("line", (line) => {
- console.log(distribute(line));
- });
-
- /* 分糖果 */
- function distribute(inputCount) {
- inputCount = parseInt(inputCount);
- if (inputCount === 0) return 0;
-
- let k = inputCount - 1;
- k |= k >>> 1;
- k |= k >>> 2;
- k |= k >>> 4;
- k |= k >>> 8;
- k |= k >>> 16;
- let max = k + 1;
- let min = max / 2;
- let n = inputCount - min > max - inputCount ? max : min;
- let count = Math.min(inputCount - min, max - inputCount);
- while (n != 1) {
- n = n / 2;
- count++;
- }
- return count;
- }
上面这个算法采用了位运算,速度要比基于Math方法运算快40%左右。
下面这段代码的作用是获取inputCount的最近的2^m,比如inputCount=6,则下面代码的max值最终为8。
let k = inputCount - 1;
k |= k >>> 1;
k |= k >>> 2;
k |= k >>> 4;
k |= k >>> 8;
k |= k >>> 16;let max = k + 1;
等价于上一个算法中ceil_count ,
const pow = Math.log2(count);
const ceil_pow = Math.ceil(pow);
const ceil_count = Math.pow(2, ceil_pow);
后面的逻辑就差不多了。