Lecture 2 (Interview Problems on bit manupulations)¶
Find the number that appears odd number of times¶
Given an array of nums of n integers. Every integer in the array appears twice except one integer. Find the number that appeared once in the array.
Input: nums = [1, 2, 2, 4, 3, 1, 4]
Output: 3
Input: nums = [5]
Output: 5
Approach 1 (sorting)¶
- sort the numbers ascending -result a[i] != a[i-1] and a[i+2]
In [2]:
def find_odd(nums):
n = len(nums)
if n ==1:
return nums[0]
nums.sort()
for i in range(1,n-1):
if nums[i] != nums[i-1] and nums[i] != nums[i+1]:
return nums[i]
return 0
print(find_odd([1, 2, 2, 4, 3, 1, 4]))
print(find_odd([5]))
3 5
Complexity¶
- N : len(nums)
O(N long N)
O(1)
Approach 2 (count map)¶
- create a count map of each num
- find the num which has count of 1
In [3]:
from collections import Counter
def find_odd(nums):
n = len(nums)
if n ==1:
return nums[0]
count_map = Counter(nums)
for num,count in count_map.items():
if count ==1:
return num
print(find_odd([1, 2, 2, 4, 3, 1, 4]))
print(find_odd([5]))
3 5
Complexity¶
- N = len(nums)
O(N)
O(N)
Approach 3 (Bit Manupulation)¶
- a ^ a = 0
- a ^ 0 = a
- xoring all elements of num = some X (rest will become 0) X = xor(num[i] ^ 0) = nums[i]
In [7]:
def find_odd(nums):
n = len(nums)
res = nums[0]
for i in range(1,n):
res = res ^ nums[i]
return res
print(find_odd([1, 2, 2, 4, 3, 1, 4]))
print(find_odd([5]))
3 5
Complexity¶
- N = len(nums)
O(N)
O (1)
Find XOR of numbers from L to R¶
Given two integers L and R. Find the XOR of the elements in the range [L , R].
Input : L = 3 , R = 5
Output : 2
Explanation : answer = (3 ^ 4 ^ 5) = 2.
Input : L = 1, R = 3
Output : 0
Explanation : answer = (1 ^ 2 ^ 3) = 0.
Approach 1 (Forward pass)¶
In [8]:
def find_xor(left, right):
res =0
while left <= right:
res ^= left
left +=1
return res
print(find_xor(3,5))
print(find_xor(1,3))
2 0
Complexity¶
- N = right - left + 1
- O(N)
- O(1)
Approach 2 (Using XOR pattern)¶
- xor (L to R) = XOR (1 to R) ^ XOR(1 to L -1)
- xor (1 to N) = repeates pattern every 4 nums
If N % 4 == 0 → result = N If N % 4 == 1 → result = 1 If N % 4 == 2 → result = N + 1 If N % 4 == 3 → result = 0
In [9]:
def find_xor(left, right):
def xor_1_to_n(n):
if n % 4 ==0:
return n
if n% 4 ==1:
return 1
if n% 4 ==2:
return n+1
if n % 4 ==3:
return 0
return xor_1_to_n(right) ^ xor_1_to_n(left -1)
print(find_xor(3,5))
print(find_xor(1,3))
2 0
Complexity¶
O(1)
O(1)
Find the two numbers appearing odd number of times¶
Input: nums = [1, 2, 1, 3, 5, 2]
Output: [3, 5]
Input: nums = [-1, 0]
Output: [-1, 0]
Approach 1 (Count map)¶
In [11]:
from collections import Counter
def find_two_odd(nums):
count_map = Counter(nums)
result = []
for num,count in count_map.items():
if count % 2 ==1:
result.append(num)
return result
print(find_two_odd([1, 2, 1, 3, 5, 2]))
print(find_two_odd([-1, 0]))
[3, 5] [-1, 0]
Complexity¶
- N = len(nums)
O(N)
O(N)
Approach 2 (Using Xor)¶
- X = xor(nums[i]) = xor(num1 ,num2) as all even will cancel out
- since num1 != num2 , xor(num1,num2) must have atleast 1 set bit
- Parition the numbers into 2 groups
- Group A: numbers with that bit is set
- Group B : numbers with that bit is not set
- xor them seprately
- xor(groupA) = num1
- xor(groupB) = num2
In [ ]:
def find_two_odd(nums):
xor_all = 0
for num in nums:
xor_all ^= num
rightmost_set_bit = (xor_all & (xor_all -1)) ^ xor_all # or(xor_all & -xor_all)
num1,num2 =0,0
for num in nums:
if num & rightmost_set_bit:
num1 ^= num
else:
num2 ^= num
return [num1,num2]
print(find_two_odd([1, 2, 1, 3, 5, 2]))
print(find_two_odd([-1, 0]))
[3, 5] [-1, 0]
Complexity¶
- N = len(nums)
O(N)
O(1)