2917. Find the K-or of an Array
Problem Description
You are given an integer array nums
and an integer k
. The problem introduces a new operation called K-or, which is an extension of the standard bitwise OR operation.
In the K-or operation, a bit position in the result is set to 1
if at least k numbers in the array have a 1
in that bit position.
Your task is to return the K-or of the array nums
.
How K-or works:
- Look at each bit position across all numbers in the array
- Count how many numbers have a
1
in that specific bit position - If the count is greater than or equal to
k
, set that bit to1
in the result - Otherwise, set that bit to
0
in the result
Example walkthrough:
For nums = [7,12,9,8,9,15]
and k = 4
:
- In binary: 7 = 0111, 12 = 1100, 9 = 1001, 8 = 1000, 9 = 1001, 15 = 1111
- Bit 0 (rightmost): appears as
1
in numbers 7, 9, 9, 15 → count = 4 ≥ k, so bit 0 is set - Bit 1: appears as
1
in numbers 7, 15 → count = 2 < k, so bit 1 is not set - Bit 2: appears as
1
in numbers 7, 12, 15 → count = 3 < k, so bit 2 is not set - Bit 3: appears as
1
in numbers 12, 9, 8, 9, 15 → count = 5 ≥ k, so bit 3 is set - Result:
1001
in binary =9
in decimal
Special cases:
- When
k = 1
, the K-or equals the regular bitwise OR of all elements - When
k = nums.length
, a bit is set only if it appears in ALL numbers
The solution iterates through each of the 32 bit positions (since numbers can be up to 2^31 - 1
), counts how many numbers have that bit set using x >> i & 1
, and if the count meets the threshold k
, sets that bit in the answer using ans |= 1 << i
.
Intuition
The key insight is that we need to examine each bit position independently. Since the K-or operation determines each bit of the result based solely on how many input numbers have that bit set, we can process each bit position separately.
Think of it this way: for a regular OR operation, a bit is set if any number has it set. For K-or, we're extending this concept - a bit is set if at least k numbers have it set. This naturally leads us to count occurrences for each bit position.
Since we're dealing with 32-bit integers (constraint: nums[i] < 2^31
), we only need to check 32 bit positions. For each position i
from 0 to 31:
- Count how many numbers have bit
i
set - If this count meets our threshold
k
, include this bit in our result
To check if bit i
is set in a number x
, we use the bit manipulation technique (x >> i) & 1
:
x >> i
shifts the number right byi
positions, bringing biti
to the rightmost position& 1
masks everything except the rightmost bit, giving us either 0 or 1
To set bit i
in our answer, we use ans |= (1 << i)
:
1 << i
creates a number with only biti
set|=
performs OR assignment, adding this bit to our result
This approach is efficient because:
- We make a single pass through each bit position (32 iterations)
- For each bit, we scan the array once (n elements)
- Total time complexity is O(32 * n) = O(n), which is optimal since we must examine every number at least once
Solution Approach
The solution uses a bit manipulation approach with enumeration of bit positions. Here's how the implementation works:
Algorithm Steps:
- Initialize
ans = 0
to store our result - Iterate through each bit position
i
from 0 to 31 (covering all possible bits in a 32-bit integer) - For each bit position
i
:- Count how many numbers in
nums
have biti
set usingsum(x >> i & 1 for x in nums)
- If this count is greater than or equal to
k
, set biti
in our answer
- Count how many numbers in
Detailed Implementation Walkthrough:
def findKOr(self, nums: List[int], k: int) -> int:
ans = 0
for i in range(32):
cnt = sum(x >> i & 1 for x in nums)
if cnt >= k:
ans |= 1 << i
return ans
Line-by-line Explanation:
ans = 0
: Start with all bits set to 0for i in range(32)
: Check each of the 32 possible bit positionscnt = sum(x >> i & 1 for x in nums)
:- For each number
x
in the array x >> i
shiftsx
right byi
positions& 1
extracts the least significant bit (which was originally at positioni
)sum()
counts total numbers with biti
set
- For each number
if cnt >= k
: Check if at leastk
numbers have this bit setans |= 1 << i
: If condition met, set biti
in the answer1 << i
creates a number with only biti
set (e.g.,1 << 3
=1000
in binary = 8)|=
performs bitwise OR assignment to add this bit to our result
Example Trace with nums = [7,12,9,8,9,15]
, k = 4
:
i = 0
: cnt = 4 (from 7,9,9,15) ≥ 4, soans |= 1
→ ans = 1i = 1
: cnt = 2 (from 7,15) < 4, skipi = 2
: cnt = 3 (from 7,12,15) < 4, skipi = 3
: cnt = 5 (from 12,9,8,9,15) ≥ 4, soans |= 8
→ ans = 9- Final result: 9
Time and Space Complexity:
- Time: O(32 × n) = O(n), where n is the length of
nums
- Space: O(1), only using a constant amount of extra space
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a simple example with nums = [5, 3, 6]
and k = 2
.
First, let's convert our numbers to binary:
- 5 = 0101
- 3 = 0011
- 6 = 0110
Now we'll check each bit position from right to left (positions 0 to 31, though we only need to check up to position 2 for this example):
Bit Position 0 (rightmost bit):
- 5 = 0101 → has bit 0 set
- 3 = 0011 → has bit 0 set
- 6 = 0110 → does not have bit 0 set
- Count = 2, which is ≥ k (2), so bit 0 is set in result
Bit Position 1:
- 5 = 0101 → does not have bit 1 set
- 3 = 0011 → has bit 1 set
- 6 = 0110 → has bit 1 set
- Count = 2, which is ≥ k (2), so bit 1 is set in result
Bit Position 2:
- 5 = 0101 → has bit 2 set
- 3 = 0011 → does not have bit 2 set
- 6 = 0110 → has bit 2 set
- Count = 2, which is ≥ k (2), so bit 2 is set in result
Building the result:
- Start with
ans = 0
- Bit 0 qualifies:
ans |= (1 << 0)
→ ans = 0001 = 1 - Bit 1 qualifies:
ans |= (1 << 1)
→ ans = 0011 = 3 - Bit 2 qualifies:
ans |= (1 << 2)
→ ans = 0111 = 7
The K-or result is 7.
To verify: In binary, our result is 0111, which means bits 0, 1, and 2 are all set - exactly the bits where at least 2 numbers had that bit set.
Solution Implementation
1class Solution:
2 def findKOr(self, nums: List[int], k: int) -> int:
3 """
4 Find the bitwise OR of all integers that appear in at least k elements.
5
6 For each bit position, if at least k numbers have that bit set to 1,
7 then that bit should be set to 1 in the result.
8
9 Args:
10 nums: List of integers
11 k: Minimum count threshold
12
13 Returns:
14 The K-OR value of the array
15 """
16 result = 0
17
18 # Check each bit position (0 to 31 for 32-bit integers)
19 for bit_position in range(32):
20 # Count how many numbers have the current bit set to 1
21 count_with_bit_set = sum(
22 (num >> bit_position) & 1
23 for num in nums
24 )
25
26 # If at least k numbers have this bit set,
27 # set this bit in the result
28 if count_with_bit_set >= k:
29 result |= (1 << bit_position)
30
31 return result
32
1class Solution {
2 public int findKOr(int[] nums, int k) {
3 int result = 0;
4
5 // Check each bit position from 0 to 31 (32-bit integer)
6 for (int bitPosition = 0; bitPosition < 32; bitPosition++) {
7 int count = 0;
8
9 // Count how many numbers have the current bit set to 1
10 for (int number : nums) {
11 // Right shift by bitPosition and check if the least significant bit is 1
12 count += (number >> bitPosition) & 1;
13 }
14
15 // If at least k numbers have this bit set, include it in the result
16 if (count >= k) {
17 // Set the bit at bitPosition in the result
18 result |= (1 << bitPosition);
19 }
20 }
21
22 return result;
23 }
24}
25
1class Solution {
2public:
3 int findKOr(vector<int>& nums, int k) {
4 int result = 0;
5
6 // Check each bit position from 0 to 31 (32-bit integer)
7 for (int bitPosition = 0; bitPosition < 32; ++bitPosition) {
8 int countOnes = 0;
9
10 // Count how many numbers have 1 at the current bit position
11 for (int number : nums) {
12 // Right shift by bitPosition and check if the least significant bit is 1
13 countOnes += (number >> bitPosition) & 1;
14 }
15
16 // If at least k numbers have 1 at this bit position,
17 // set this bit in the result
18 if (countOnes >= k) {
19 result |= (1 << bitPosition);
20 }
21 }
22
23 return result;
24 }
25};
26
1/**
2 * Finds the K-OR of an array where each bit position in the result is set to 1
3 * if at least k numbers in the array have that bit set to 1
4 * @param nums - Array of non-negative integers
5 * @param k - Minimum count threshold for setting a bit in the result
6 * @returns The K-OR value of the array
7 */
8function findKOr(nums: number[], k: number): number {
9 let result: number = 0;
10
11 // Check each bit position (0 to 31 for 32-bit integers)
12 for (let bitPosition: number = 0; bitPosition < 32; bitPosition++) {
13 let bitCount: number = 0;
14
15 // Count how many numbers have the current bit set to 1
16 for (const num of nums) {
17 // Right shift by bitPosition and check if the least significant bit is 1
18 bitCount += (num >> bitPosition) & 1;
19 }
20
21 // If at least k numbers have this bit set, set it in the result
22 if (bitCount >= k) {
23 // Set the bit at bitPosition in the result using OR operation
24 result |= 1 << bitPosition;
25 }
26 }
27
28 return result;
29}
30
Time and Space Complexity
Time Complexity: O(32 × n)
which simplifies to O(n)
, where n
is the length of the array nums
.
The algorithm iterates through 32 bit positions (since we're checking 32-bit integers), and for each bit position, it iterates through all n
elements in the array to count how many numbers have that bit set. The inner sum operation sum(x >> i & 1 for x in nums)
takes O(n)
time, and this is executed 32 times, resulting in O(32 × n) = O(n)
.
Note that the reference answer mentions O(n × log M)
where M
is the maximum value in nums
. This is essentially equivalent because log M
represents the number of bits needed to represent the maximum value. For 32-bit integers, this is at most 32, so O(n × 32) = O(n × log M)
when considering M
as the maximum possible value.
Space Complexity: O(1)
The algorithm uses only a constant amount of extra space. The variables ans
, i
, and cnt
are the only additional storage used, regardless of the input size. The generator expression in the sum function doesn't create a list but evaluates lazily, so no additional space proportional to the input size is required.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Incorrect Bit Range Assumption
A common mistake is assuming that checking 32 bits is always sufficient or necessary. While the problem states numbers can be up to 2^31 - 1
, developers might:
- Use an insufficient range (e.g., only checking 16 bits)
- Use an excessive range unnecessarily (e.g., checking 64 bits when not needed)
Solution: Stick to 32 bits for standard integer problems, or dynamically determine the maximum bit length if optimization is critical:
max_bit_length = max(nums).bit_length() if nums else 0
for bit_position in range(max_bit_length):
# ... rest of the logic
2. Misunderstanding Bit Extraction Logic
The expression (num >> bit_position) & 1
can be confusing. Common errors include:
- Writing
num & (1 << bit_position)
without converting to 0 or 1 - Using
num >> bit_position % 2
which has different operator precedence
Solution: Always use parentheses for clarity and ensure the result is normalized to 0 or 1:
# Correct approaches: bit_is_set = (num >> bit_position) & 1 # Returns 0 or 1 # OR bit_is_set = 1 if (num & (1 << bit_position)) else 0
3. Off-by-One Error with Threshold
Developers might incorrectly implement the threshold check as count > k
instead of count >= k
, missing cases where exactly k
numbers have the bit set.
Solution: Always use >=
for "at least k" conditions:
if count_with_bit_set >= k: # Correct result |= (1 << bit_position)
4. Integer Overflow in Other Languages
While Python handles arbitrary precision integers automatically, implementing this in languages like Java or C++ requires careful consideration of integer overflow when using bit shifts.
Solution for other languages: Use appropriate data types:
// Java example long result = 0; result |= (1L << bit_position); // Use 1L for long literal
5. Inefficient Bit Counting
Some might try to convert numbers to binary strings and count '1's, which is inefficient:
# Inefficient approach - avoid this:
for i in range(32):
count = sum(1 for num in nums if bin(num)[2:].zfill(32)[31-i] == '1')
Solution: Always use bitwise operations for efficiency:
# Efficient approach:
count = sum((num >> bit_position) & 1 for num in nums)
Which of the two traversal algorithms (BFS and DFS) can be used to find whether two nodes are connected?
Recommended Readings
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!