我一直弄错这个问题。使用JavaScript计数位

发布于 2025-02-10 05:42:16 字数 587 浏览 4 评论 0原文

这是一个问题。 给定一个整数n,返回一个长度为n + 1的数组and and and n + 1,以便对于每个i(0< = i< = n),ans [i]是i的二进制表示中的1个数字。

”以下。 如果输入为2,则预期输出应为[0,1,1],但我一直得到[0,2,2]。这是为什么???

var countBits = function(n) {
    //n=3. [0,1,2,3]
    var arr=[0];
     for (var i=1; i<=n; i++){
         var sum = 0;
         var value = i;
         while(value != 0){
             sum += value%2;
             value /= 2;
         }
         arr.push(sum);
     }
    return arr;
};

console.log(countBits(3));

This is the question.
Given an integer n, return an array ans of length n + 1 such that for each i (0 <= i <= n), ans[i] is the number of 1's in the binary representation of i.

https://leetcode.com/problems/counting-bits/

And this is my solution below.
If the input is 2, expected output should be [0,1,1] but I keep getting [0,2,2]. Why is that???

var countBits = function(n) {
    //n=3. [0,1,2,3]
    var arr=[0];
     for (var i=1; i<=n; i++){
         var sum = 0;
         var value = i;
         while(value != 0){
             sum += value%2;
             value /= 2;
         }
         arr.push(sum);
     }
    return arr;
};

console.log(countBits(3));

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

度的依靠╰つ 2025-02-17 05:42:16

您正在做太多工作。

假设b是与i中第一个位相对应的2的最大功率。显然,ii -b相比,其二进制表示中的一个1恰好具有一个。但是,由于您正在按顺序生成计数,因此您已经确定了i -b中有多少1

唯一的技巧是如何找出b是什么。为此,我们使用另一种迭代技术:当您列出编号时,bi时完全更改成为b :

const countBits = function(n) {
    let arr = [0], bit = 1;
    for (let i = 1; i <= n; i++){
        if (i == bit + bit) bit += bit;
        arr.push(arr[i - bit] + 1);
    }
    return arr;
};

console.log(countBits(20));

该技术通常称为“动态编程”。从本质上讲,它采用递归定义并计算自下而上:它不是从所需的参数开始并递归到基本情况下,而是从基数开始,然后计算每个中间值,直到达到目标直到达到目标。在这种情况下,需要所有中间值,使我们不必考虑如何仅计算最小数量的中间值所需的中间值。

You're doing way too much work.

Suppose b is the largest power of 2 corresponding to the first bit in i. Evidently, i has exactly one more 1 in its binary representation than does i - b. But since you're generating the counts in order, you've already worked out how many 1s there are in i - b.

The only trick is how to figure out what b is. And to do that, we use another iterative technique: as you list numbers, b changes exactly at the moment that i becomes twice the previous value of b:

const countBits = function(n) {
    let arr = [0], bit = 1;
    for (let i = 1; i <= n; i++){
        if (i == bit + bit) bit += bit;
        arr.push(arr[i - bit] + 1);
    }
    return arr;
};

console.log(countBits(20));

This technique is usually called "dynamic programming". In essence, it takes a recursive definition and computes it bottom-up: instead of starting at the desired argument and recursing down to the base case, it starts at the base and then computes each intermediate value which will be needed until it reaches the target. In this case, all intermediate values are needed, saving us from having to think about how to compute only the minimum number of intermediate values necessary.

小ぇ时光︴ 2025-02-17 05:42:16

这样想:如果您知道一个数字x中有多少个,那么您立即知道x*2(相同)中有多少个(相同)和x*2+1(另一个)。由于您是按顺序处理数字,因此您只需将两个派生的计数推到结果并跳至下一个数字:

let b = [0, 1]

for (let i = 1; i <= N / 2; i++) {
    b.push(b[i])
    b.push(b[i] + 1)
}

由于我们一次将两个数字推到两个数字,因此,即使是n,结果都将是一次性的,您必须弹出之后的最后一个数字。

Think of it this way: if you know how many ones are there in a number X, then you immediately know how many ones are there in X*2 (the same) and X*2+1 (one more). Since you're processing numbers in order, you can just push both derived counts to the result and skip to the next number:

let b = [0, 1]

for (let i = 1; i <= N / 2; i++) {
    b.push(b[i])
    b.push(b[i] + 1)
}

Since we push two numbers at once, the result will be one-off for even N, you have to pop the last number afterwards.

轻许诺言 2025-02-17 05:42:16

使用flool():

sum += Math.floor(value%2);
value = Math.floor(value/2);

我猜您的算法适用于某些打字语言,整数部门会导致整数

use floor():

sum += Math.floor(value%2);
value = Math.floor(value/2);

I guess your algorithm works for some typed language where integers division results in integers

披肩女神 2025-02-17 05:42:16

这是一种截然不同的方法,使用fold(例如array.prototype.reduce)通常称为展开。在这种情况下,我们从种子阵列开始,对其进行一些操作以产生下一个值,然后再出现,直到我们决定停止。

我们编写一个通用展开,然后将其与回调一起使用,该回调接受我们到目前为止发现的整个数组,以及next and 完成回调,然后选择是否停止(如果我们达到极限)或继续。无论哪种情况,它都称为两个回调之一。

看起来像这样:

const _unfold = (fn, init) =>
  fn (init, (x) => _unfold (fn, [...init, x]), () => init)

// Number of 1's in the binary representation of each integer in [`0 ... n`]
const oneBits = (n) => _unfold (
  (xs, next, done) => xs .length < n ? next (xs .length % 2 + xs [xs .length >> 1]) : done(),
  [0]
)

console .log (oneBits (20))

我有一个 github gist ,其中显示了这种模式的一些示例。

有趣的扩展名是封装阵列到长n位的处理,并使此功能变得微不足道。这不是这种_unfold的唯一用途,但这可能是常见的。看起来像这样:

const _unfold = (fn, init) =>
  fn (init, (x) => _unfold (fn, [...init, x]), () => init)

const unfoldN = (fn, init) => (n) => _unfold (
  (xs, next, done) => xs .length < n ? next (fn (xs)) : done (),
  init
)

const oneBits = unfoldN (
  (xs) => xs .length % 2 + xs [xs .length >> 1], 
  [0]
)

console .log (oneBits (20))

在这里,我们有两个助手功能,可以使OneBits写作非常微不足道。这些帮助者有许多潜在用途。

Here's a very different approach, using the opposite of a fold (such as Array.prototype.reduce) typically called unfold. In this case, we start with a seed array, perform some operation on it to yield the next value, and recur, until we decide to stop.

We write a generic unfold and then use it with a callback which accepts the entire array we've found so far plus next and done callbacks, and then chooses whether to stop (if we've reached our limit) or continue. In either case, it calls one of the two callbacks.

It looks like this:

const _unfold = (fn, init) =>
  fn (init, (x) => _unfold (fn, [...init, x]), () => init)

// Number of 1's in the binary representation of each integer in [`0 ... n`]
const oneBits = (n) => _unfold (
  (xs, next, done) => xs .length < n ? next (xs .length % 2 + xs [xs .length >> 1]) : done(),
  [0]
)

console .log (oneBits (20))

I have a GitHub Gist which shows a few more examples of this pattern.

An interesting possible extension would be to encapsulate the handling of the array-to--length-n bit, and make this function trivial. That's no the only use of such an _unfold, but it's probably a common one. It could look like this:

const _unfold = (fn, init) =>
  fn (init, (x) => _unfold (fn, [...init, x]), () => init)

const unfoldN = (fn, init) => (n) => _unfold (
  (xs, next, done) => xs .length < n ? next (fn (xs)) : done (),
  init
)

const oneBits = unfoldN (
  (xs) => xs .length % 2 + xs [xs .length >> 1], 
  [0]
)

console .log (oneBits (20))

Here we have two helper functions that make oneBits quite trivial to write. And those helpers have many potential uses.

压抑⊿情绪 2025-02-17 05:42:16

我这样做了,与位运算符

function countBits(n) {
    const arr = new Array(n + 1).fill(0);
    for(let i = 0; i <= n; i++){
        arr[i] = arr[i >>> 1] + (i & 1);
    }
    return arr;
};

I've done like this, with bitwise operators

function countBits(n) {
    const arr = new Array(n + 1).fill(0);
    for(let i = 0; i <= n; i++){
        arr[i] = arr[i >>> 1] + (i & 1);
    }
    return arr;
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文