Bit Manupulation (Advanced Maths)¶
Prime factorisation of a Number¶
You are given an integer array queries of length n. Return the prime factorization of each number in array queries in sorted order.
Input : queries = [2, 3, 4, 5, 6]
Output : [ [2], [3], [2, 2], [5], [2, 3] ]
Explanation : The values 2, 3, 5 are itself prime numbers.
The prime factorization of 4 will be --> 2 * 2.
The prime factorization of 6 will be --> 2 * 3.
Input : queries = [7, 12, 18]
Output : [ [7], [2, 2, 3], [2, 3, 3] ]
Explanation : The value 7 itself is a prime number.
The prime factorization of 12 will be --> 2 * 2 * 3.
The prime factorization of 18 will be --> 2 * 3 * 3.
Approach 1 (Brute Force)¶
- for each num calculate prime factors separately
- handle factors for 2 separately
- for odd factors (starting from 3)
- loop till i*i <= num and increment by 2
- e.g. 3,5,7,9, etc
- note if 9 is a factor then 3 will also be a factor and it will already be convered
- every time keep dividing num when we get remainder=0
- if num > 1 , add that as a factor too
In [3]:
def prime_factors(nums):
def compute_factors(num):
factors = []
# Handle 2 factors
while num % 2 ==0:
factors.append(2)
num = num // 2
# Check odd factors
i=3
while i*i <= num:
while num % i ==0:
factors.append(i)
num = num // i
i+=2
if num >1:
factors.append(num)
return factors
result = []
for num in nums:
factors = compute_factors(num)
result.append(factors)
return result
print(prime_factors([2, 3, 4, 5, 6]))
print(prime_factors([7, 12, 18]))
[[2], [3], [2, 2], [5], [2, 3]] [[7], [2, 2, 3], [2, 3, 3]]
Complexity¶
- N = len(nums)
- a number can have max log2 (num) factors
- e.g. 16 -> 2x2x2x2 = 4 factors = log 2(16) = 4
O(N * sqrt num)
O(N * log 2 (num))
All Divisors of a Number¶
You are given an integer n. You need to find all the divisors of n. Return all the divisors of n as an array or list in a sorted order. A number which completely divides another number is called it's divisor.
Input: n = 6
Output: [1, 2, 3, 6]
Input: n = 8
Output: [1, 2, 4, 8]
Approach 1 (Brute Force)¶
- loop till 1 to n
- if it is a divisor add it to result
In [8]:
def compute_divisors(num):
divisors = []
for i in range(1,num+1,1):
if num % i ==0:
divisors.append(i)
return divisors
print(compute_divisors(6))
print(compute_divisors(8))
[1, 2, 3, 6] [1, 2, 4, 8]
Complexity¶
- O(num)
- O(sqrt(num))
Approach 2 (Optimize time)¶
- instead of running till 1 to num
- we can run till 1 to sqrt(num)
- if i is divisor then num // i is also a divisor
In [9]:
def compute_divisors(num):
small_divisors = []
large_divisors = []
i =1
while i*i <=num:
if num % i ==0:
small_divisors.append(i)
large_divisors.append(num //i)
i+=1
# Remove the duplicate if num is a perfect square
if small_divisors and small_divisors[-1] == large_divisors[-1]:
large_divisors.pop()
return small_divisors + large_divisors[::-1]
print(compute_divisors(6))
print(compute_divisors(8))
[1, 2, 3, 6] [1, 2, 4, 8]
Complexity¶
- O(sqrt(num))
- O(sqrt(num))