Nth Number Having At Most K Set Bits

Last Updated : 1 Aug, 2026

Given two integers n and k, find the nth non-negative integer whose binary representation contains at most k set bits (1s). The numbers are considered in increasing order starting from 0.

Note: It is guaranteed that the answer exists and fits in a signed 64-bit integer.

Examples:

Input: n = 5, k = 1
Output: 8
Explanation: The non-negative integers whose binary representation contains at most 1 set bit, in increasing order, are:
0 = (0)2
1 = (1)2
2 = (10)2
4 = (100)2
8 = (1000)2
The 5th number in this sequence is 8.

Input: n = 6, k = 2
Output: 5
Explanation: The non-negative integers whose binary representation contains at most 2 set bits, in increasing order, are:
0 = (0)2
1 = (1)2
2 = (10)2
3 = (11)2
4 = (100)2
5 = (101)2
The 6th number in this sequence is 5.

[Naive Approach] Generate Numbers Sequentially and Count Set Bits

The idea is to generate non-negative integers one by one starting from 0 and count the number of set bits in each number. Whenever a number contains at most k set bits, include it in the sequence. Continue this process until the nth valid number is found.

Working of Approach:

  • Start with the number 0.
  • For each number, count the number of set bits in its binary representation.
  • If the count of set bits is at most k, increment the count of valid numbers found.
  • Continue generating the next integer until the nth valid number is reached.
  • Return the current number as the answer.
C++
#include <iostream>
using namespace std;

// Returns the number of set bits in num.
int countSetBits(int num) {
    int cnt = 0;

    while (num > 0) {
        cnt += num & 1;
        num >>= 1;
    }

    return cnt;
}

// Returns the nth non-negative integer having at most k set bits.
int findNthNumber(int n, int k) {
    int validCnt = 0;
    int num = 0;

    // Generate numbers until the nth valid number is found.
    while (true) {
        if (countSetBits(num) <= k) {
            validCnt++;

            if (validCnt == n)
                return num;
        }

        num++;
    }
}

int main() {
    int n = 5, k = 1;

    cout << findNthNumber(n, k);

    return 0;
}
Java
class GFG {

    // Returns the number of set bits in num.
    static int countSetBits(int num) {
        int cnt = 0;

        while (num > 0) {
            cnt += num & 1;
            num >>= 1;
        }

        return cnt;
    }

    // Returns the nth non-negative integer having at most k set bits.
    static int findNthNumber(int n, int k) {
        int validCnt = 0;
        int num = 0;

        // Generate numbers until the nth valid number is found.
        while (true) {
            if (countSetBits(num) <= k) {
                validCnt++;

                if (validCnt == n)
                    return num;
            }

            num++;
        }
    }

    public static void main(String[] args) {
        int n = 5, k = 1;

        System.out.println(findNthNumber(n, k));
    }
}
Python
# Returns the number of set bits in num.
def countSetBits(num):
    cnt = 0

    while num > 0:
        cnt += num & 1
        num >>= 1

    return cnt


# Returns the nth non-negative integer having at most k set bits.
def findNthNumber(n, k):
    validCnt = 0
    num = 0

    # Generate numbers until the nth valid number is found.
    while True:
        if countSetBits(num) <= k:
            validCnt += 1

            if validCnt == n:
                return num

        num += 1


if __name__ == "__main__":
    n, k = 5, 1

    print(findNthNumber(n, k))
C#
using System;

class GFG
{
    // Returns the number of set bits in num.
    static int CountSetBits(int num)
    {
        int cnt = 0;

        while (num > 0)
        {
            cnt += num & 1;
            num >>= 1;
        }

        return cnt;
    }

    // Returns the nth non-negative integer having at most k set bits.
    static int findNthNumber(int n, int k)
    {
        int validCnt = 0;
        int num = 0;

        // Generate numbers until the nth valid number is found.
        while (true)
        {
            if (CountSetBits(num) <= k)
            {
                validCnt++;

                if (validCnt == n)
                    return num;
            }

            num++;
        }
    }

    static void Main()
    {
        int n = 5, k = 1;

        Console.WriteLine(findNthNumber(n, k));
    }
}
JavaScript
// Returns the number of set bits in num.
function countSetBits(num) {
    let cnt = 0;

    while (num > 0) {
        cnt += num & 1;
        num >>= 1;
    }

    return cnt;
}

// Returns the nth non-negative integer having at most k set bits.
function findNthNumber(n, k) {
    let validCnt = 0;
    let num = 0;

    // Generate numbers until the nth valid number is found.
    while (true) {
        if (countSetBits(num) <= k) {
            validCnt++;

            if (validCnt === n)
                return num;
        }

        num++;
    }
}

// Driver Code
const n = 5, k = 1;

console.log(findNthNumber(n, k));

Output
8

Time Complexity: O(ans * log(ans)), as each number up to the answer is checked, and counting its set bits takes O(log(ans)) time.
Auxiliary Space: O(1), as only a constant amount of extra space is used regardless of the input size.

[Expected Approach] Binary Search with Digit DP

The idea is to use binary search on the answer instead of generating every valid number. For any candidate number, we can efficiently determine how many non-negative integers less than or equal to it have at most k set bits using Digit DP on its binary representation. If this count is at least n, the candidate may be the answer, so we search the left half; otherwise, we search the right half. This allows us to find the smallest valid number satisfying the condition efficiently.

Working of Approach:

  • Perform binary search on the answer in the range [0, 1018].
  • For each middle value, represent it as a 64-bit binary string.
  • Use Digit DP to count the numbers less than or equal to the middle value having at most k set bits.
  • If the count is at least n, store the current value as a possible answer and continue searching in the left half.
  • Otherwise, search in the right half.
  • When the binary search completes, return the smallest number whose count of valid numbers up to it is at least n.
C++
#include <bits/stdc++.h>
using namespace std;

vector<vector<vector<long long>>> dp;

// Reset DP table before processing a new number.
void reset() {
    for (int t = 0; t < 2; t++) {
        for (int i = 0; i < 65; i++) {
            fill(dp[t][i].begin(), dp[t][i].end(), -1);
        }
    }
}

// Counts numbers having at most k set bits.
long long digitDp(string &s, int pos, int tight, int k) {
    if (k < 0)
        return 0;

    // All bits processed.
    if (pos == 0)
        return 1;

    // Reuse previously computed state.
    if (dp[tight][k][pos] != -1)
        return dp[tight][k][pos];

    // Current bit can go up to limit.
    int limit = tight ? s[s.length() - pos] - '0' : 1;
    long long ans = 0;

    for (int bit = 0; bit <= limit; bit++) {
        ans += digitDp(
            s,
            pos - 1,
            tight && (bit == limit), // Remain tight only if limit is chosen.
            k - bit                  // Decrease remaining set bits.
        );
    }

    return dp[tight][k][pos] = ans;
}

// Returns count of numbers in [0, n] with at most k set bits.
long long countNumbers(long long n, int k) {
    string s = bitset<64>(n).to_string();
    reset();
    return digitDp(s, s.length(), 1, k);
}

long long findNthNumber(int n, int k) {
    long long low = 0, high = 1000000000000000000LL;

    // DP[tight][remaining set bits][bits left]
    dp.assign(2, vector<vector<long long>>(65, vector<long long>(65, -1)));

    // Binary search for the smallest number
    // having at least n valid numbers before it.
    while (low <= high) {
        long long mid = low + (high - low) / 2;
        long long cnt = countNumbers(mid, k);

        if (cnt >= n)
            high = mid - 1;
        else
            low = mid + 1;
    }

    return low;
}

int main() {
    int n = 5, k = 1;

    cout << findNthNumber(n, k);

    return 0;
}
Java
import java.util.Arrays;

class GFG {

    static long[][][] dp;

    // Reset DP table before processing a new number.
    static void reset() {
        for (int t = 0; t < 2; t++) {
            for (int i = 0; i < 65; i++) {
                Arrays.fill(dp[t][i], -1);
            }
        }
    }

    // Counts numbers having at most k set bits.
    static long digitDp(String s, int pos, int tight, int k) {
        if (k < 0)
            return 0;

        // All bits processed.
        if (pos == 0)
            return 1;

        // Reuse previously computed state.
        if (dp[tight][k][pos] != -1)
            return dp[tight][k][pos];

        // Current bit can go up to limit.
        int limit = (tight == 1) ? s.charAt(s.length() - pos) - '0' : 1;
        long ans = 0;

        for (int bit = 0; bit <= limit; bit++) {
            ans += digitDp(
                s,
                pos - 1,
                (tight == 1 && bit == limit) ? 1 : 0, // Remain tight only if limit is chosen.
                k - bit                               // Decrease remaining set bits.
            );
        }

        return dp[tight][k][pos] = ans;
    }

    // Returns count of numbers in [0, n] with at most k set bits.
    static long countNumbers(long n, int k) {
        String s = String.format("%64s", Long.toBinaryString(n)).replace(' ', '0');
        reset();
        return digitDp(s, s.length(), 1, k);
    }

    static long findNthNumber(int n, int k) {
        long low = 0, high = 1000000000000000000L;

        // DP[tight][remaining set bits][bits left]
        dp = new long[2][65][65];

        // Binary search for the smallest number
        // having at least n valid numbers before it.
        while (low <= high) {
            long mid = low + (high - low) / 2;
            long cnt = countNumbers(mid, k);

            if (cnt >= n)
                high = mid - 1;
            else
                low = mid + 1;
        }

        return low;
    }

    public static void main(String[] args) {
        int n = 5, k = 1;

        System.out.println(findNthNumber(n, k));
    }
}
Python
from functools import lru_cache

# Counts numbers having at most k set bits.
def digitDp(s, pos, tight, k):
    if k < 0:
        return 0

    # All bits processed.
    if pos == 0:
        return 1

    # Current bit can go up to limit.
    limit = int(s[len(s) - pos]) if tight else 1
    ans = 0

    for bit in range(limit + 1):
        ans += digitDp(
            s,
            pos - 1,
            tight and bit == limit,  # Remain tight only if limit is chosen.
            k - bit                  # Decrease remaining set bits.
        )

    return ans


# Returns count of numbers in [0, n] with at most k set bits.
def countNumbers(n, k):
    s = bin(n)[2:].zfill(64)

    global digitDp
    digitDp = lru_cache(None)(digitDp)

    ans = digitDp(s, len(s), True, k)
    digitDp.cache_clear()

    return ans


def findNthNumber(n, k):
    low, high = 0, 10 ** 18

    # Binary search for the smallest number
    # having at least n valid numbers before it.
    while low <= high:
        mid = (low + high) // 2
        cnt = countNumbers(mid, k)

        if cnt >= n:
            high = mid - 1
        else:
            low = mid + 1

    return low


if __name__ == "__main__":
    n, k = 5, 1

    print(findNthNumber(n, k))
C#
using System;

class GFG
{
    static long[,,] dp = new long[2, 65, 65];

    // Reset DP table before processing a new number.
    static void Reset()
    {
        for (int tight = 0; tight < 2; tight++)
        {
            for (int k = 0; k < 65; k++)
            {
                for (int pos = 0; pos < 65; pos++)
                {
                    dp[tight, k, pos] = -1;
                }
            }
        }
    }

    // Counts numbers having at most k set bits.
    static long DigitDp(string s, int pos, int tight, int k)
    {
        if (k < 0)
            return 0;

        // All bits processed.
        if (pos == 0)
            return 1;

        // Reuse previously computed state.
        if (dp[tight, k, pos] != -1)
            return dp[tight, k, pos];

        // Current bit can go up to limit.
        int limit = (tight == 1) ? s[s.Length - pos] - '0' : 1;
        long ans = 0;

        for (int bit = 0; bit <= limit; bit++)
        {
            ans += DigitDp(
                s,
                pos - 1,
                (tight == 1 && bit == limit) ? 1 : 0, // Remain tight only if limit is chosen.
                k - bit                               // Decrease remaining set bits.
            );
        }

        return dp[tight, k, pos] = ans;
    }

    // Returns count of numbers in [0, n] with at most k set bits.
    static long CountNumbers(long n, int k)
    {
        string s = Convert.ToString(n, 2).PadLeft(64, '0');
        Reset();
        return DigitDp(s, s.Length, 1, k);
    }

    static long findNthNumber(int n, int k)
    {
        long low = 0, high = 1000000000000000000L;

        // Binary search for the smallest number
        // having at least n valid numbers before it.
        while (low <= high)
        {
            long mid = low + (high - low) / 2;
            long cnt = CountNumbers(mid, k);

            if (cnt >= n)
                high = mid - 1;
            else
                low = mid + 1;
        }

        return low;
    }

    static void Main()
    {
        int n = 5, k = 1;

        Console.WriteLine(findNthNumber(n, k));
    }
}
JavaScript
// Reset DP table before processing a new number.
let dp = [];

function reset() {
    dp = Array.from({ length: 2 }, () =>
        Array.from({ length: 65 }, () =>
            Array(65).fill(-1n)
        )
    );
}

// Counts numbers having at most k set bits.
function digitDp(s, pos, tight, k) {
    if (k < 0)
        return 0n;

    // All bits processed.
    if (pos === 0)
        return 1n;

    // Reuse previously computed state.
    if (dp[tight][k][pos] !== -1n)
        return dp[tight][k][pos];

    // Current bit can go up to limit.
    const limit = tight ? Number(s[s.length - pos]) : 1;
    let ans = 0n;

    for (let bit = 0; bit <= limit; bit++) {
        ans += digitDp(
            s,
            pos - 1,
            tight && bit === limit ? 1 : 0, // Remain tight only if limit is chosen.
            k - bit                         // Decrease remaining set bits.
        );
    }

    dp[tight][k][pos] = ans;
    return ans;
}

// Returns count of numbers in [0, n] with at most k set bits.
function countNumbers(n, k) {
    const s = n.toString(2).padStart(64, '0');
    reset();
    return digitDp(s, s.length, 1, k);
}

function findNthNumber(n, k) {
    let low = 0n, high = 1000000000000000000n;

    // Binary search for the smallest number
    // having at least n valid numbers before it.
    while (low <= high) {
        const mid = low + (high - low) / 2n;
        const cnt = countNumbers(mid, k);

        if (cnt >= BigInt(n))
            high = mid - 1n;
        else
            low = mid + 1n;
    }

    return low;
}

// Driver Code
const n = 5, k = 1;

console.log(findNthNumber(n, k).toString());

Output
8

Time Complexity: O(k * log2(ans)), as binary search performs O(log(ans)) iterations, and each iteration runs a Digit DP in O(k * log(ans)) time.
Auxiliary Space: O(k * log(ans)), due to the memoization table used by the Digit DP.

Comment