0% found this document useful (0 votes)
11 views

Coding Questions

Uploaded by

snehagupta1465
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views

Coding Questions

Uploaded by

snehagupta1465
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 59

ARRAY

1. Reverse the array


# Original list
arr = [1, 2, 3, 4, 5]

# Reverse the list using slicing


reversed_arr = arr[::-1]

print(reversed_arr) # Output: [5, 4, 3, 2, 1]

2. Min & max array


def find_min(arr):
if not arr:
raise ValueError("List is empty")
min_val = arr[0]
for item in arr:
if item < min_val:
min_val = item
return min_val

def find_max(arr):
if not arr:
raise ValueError("List is empty")
max_val = arr[0]
for item in arr:
if item > max_val:
max_val = item
return max_val

# Example usage
arr = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]

print(f"Minimum value: {find_min(arr)}") # Output: Minimum value: 1


print(f"Maximum value: {find_max(arr)}") # Output: Maximum value: 9

3. Find the "Kth" max and min element of an array


# Example list
arr = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]

# Define the value of k


k=3
try:
kth_min = find_kth_min(arr, k)
kth_max = find_kth_max(arr, k)

print(f"The {k}-th minimum value: {kth_min}") # Output: The 3-th minimum value: 3
print(f"The {k}-th maximum value: {kth_max}") # Output: The 3-th maximum value: 5
except ValueError as e:
print(e)

Given an array which consists of only 0, 1 and 2. Sort the array


4.

without using any sorting algo


def sort_012(arr):
"""
Sort an array consisting of 0s, 1s, and 2s using the Dutch National Flag algorithm.

Args:
arr (list): The list containing only 0s, 1s, and 2s.

Returns:
None: The list is sorted in place.
"""
low = 0
mid = 0
high = len(arr) - 1

while mid <= high:


if arr[mid] == 0:
# Swap arr[low] and arr[mid], increment both pointers
arr[low], arr[mid] = arr[mid], arr[low]
low += 1
mid += 1
elif arr[mid] == 1:
# Just move the mid pointer
mid += 1
else: # arr[mid] == 2
# Swap arr[mid] and arr[high], decrement high pointer
arr[high], arr[mid] = arr[mid], arr[high]
high -= 1

# Example usage
arr = [2, 0, 1, 2, 0, 1, 0]
sort_012(arr)
print(arr) # Output: [0, 0, 0, 1, 1, 2, 2]
5.Move all the negative elements to one side of the array
. # Python code for the same approach
def move(arr):
arr.sort()

# driver code
arr = [ -1, 2, -3, 4, 5, 6, -7, 8, 9 ]
move(arr)
for e in arr:
print(e , end = " ")

# This code is contributed by shinjanpatra

6. def find_union_and_intersection(arr1, arr2):


"""
Find the union and intersection of two sorted arrays.

Args:
arr1 (list): The first sorted list.
arr2 (list): The second sorted list.

Returns:
tuple: A tuple containing two lists: (union, intersection).
"""
union = []
intersection = []

i=0
j=0

# Traverse both arrays


while i < len(arr1) and j < len(arr2):
if arr1[i] < arr2[j]:
union.append(arr1[i])
i += 1
elif arr1[i] > arr2[j]:
union.append(arr2[j])
j += 1
else:
# Both are equal
union.append(arr1[i])
intersection.append(arr1[i])
i += 1
j += 1

# Add remaining elements from arr1


while i < len(arr1):
union.append(arr1[i])
i += 1

# Add remaining elements from arr2


while j < len(arr2):
union.append(arr2[j])
j += 1

return union, intersection

# Example usage
arr1 = [1, 2, 4, 5, 6]
arr2 = [2, 3, 5, 7]

union, intersection = find_union_and_intersection(arr1, arr2)

print("Union:", union) # Output: Union: [1, 2, 3, 4, 5, 6, 7]


print("Intersection:", intersection) # Output: Intersection: [2, 5]

7.def rotate_array_by_one(arr):
"""
Cyclically rotates an array by one position to the right.
Args:
arr (list): The list of elements to rotate.

Returns:
None: The array is rotated in place.
"""
if len(arr) <= 1:
return # No rotation needed for empty or single-element arrays

last_element = arr[-1] # Store the last element


# Shift all elements one position to the right
for i in range(len(arr) - 1, 0, -1):
arr[i] = arr[i - 1]
# Place the last element at the first position
arr[0] = last_element

# Example usage
arr = [1, 2, 3, 4, 5]
rotate_array_by_one(arr)
print(arr) # Output: [5, 1, 2, 3, 4]
8. def max_subarray_sum(arr):
"""
Finds the largest sum of a contiguous subarray using Kadane's Algorithm.
Args:
arr (list): The list of integers.

Returns:
int: The largest sum of the contiguous subarray.
"""
if not arr:
return 0 # Handle edge case where the list is empty

max_current = max_global = arr[0]

for num in arr[1:]:


max_current = max(num, max_current + num)
if max_current > max_global:
max_global = max_current

return max_global

# Example usage
arr = [1, -2, 3, 4, -1, 2, 1, -5, 4]
result = max_subarray_sum(arr)
print("The largest sum of the contiguous subarray is:", result) # Output: 10

9.def minimize_max_diff(heights, k):


# Sort the array to make it easier to calculate the min/max after modification
heights.sort()
# Initialize result as the current difference between the max and min heights
n = len(heights)
if n == 1:
return 0 # If there is only one height, no need to minimize anything

max_diff = heights[-1] - heights[0]

# Consider both ends after modification


small = heights[0] + k
big = heights[-1] - k

# Swap if needed to ensure small is less than big


if small > big:
small, big = big, small
# Traverse the heights array and update the max and min
for i in range(1, n-1):
subtract = heights[i] - k
add = heights[i] + k

# If the modification doesn't affect the range, skip this element


if subtract >= small or add <= big:
continue

# Update the small or big accordingly


if big - subtract <= add - small:
small = subtract
else:
big = add

return min(max_diff, big - small)

# Example usage:
heights = [1, 15, 10]
k=6
result = minimize_max_diff(heights, k)
print(f"The minimized maximum difference is: {result}")

10. Minimum no. of Jumps to reach end of an array


def min_jumps(arr):
n = len(arr)

# If array has only one element or cannot move forward


if n == 1:
return 0
if arr[0] == 0:
return -1

# Initialize maximum reach, steps and jumps


max_reach = arr[0]
step = arr[0]
jumps = 1

for i in range(1, n):


# If we reached the end of the array
if i == n - 1:
return jumps
# Update the maximum reach
max_reach = max(max_reach, i + arr[i])

# Use a step to move forward


step -= 1

# If no steps are remaining


if step == 0:
# We need to jump
jumps += 1

# If current index is greater than or equal to the max reachable point, return -1
if i >= max_reach:
return -1

# Reinitialize steps
step = max_reach - i

return -1 # If we never reached the end

# Example usage:
arr = [2, 3, 1, 1, 2, 4, 2, 0, 1, 1]
result = min_jumps(arr)
print(f"Minimum number of jumps to reach the end: {result}")

11. def find_duplicate(nums):


# Phase 1: Using Floyd's Tortoise and Hare (Cycle Detection)
slow = nums[0]
fast = nums[0]

# Move slow by 1 step and fast by 2 steps until they meet


while True:
slow = nums[slow]
fast = nums[nums[fast]]
if slow == fast:
break

# Phase 2: Find the entrance to the cycle (which is the duplicate)


slow = nums[0]
while slow != fast:
slow = nums[slow]
fast = nums[fast]

return slow

# Example usage:
nums = [3, 1, 3, 4, 2]
result

12. Merge 2 sorted arrays without using Extra space.


def next_gap(gap):
if gap <= 1:
return 0
return (gap // 2) + (gap % 2)

def merge(arr1, arr2, n, m):


gap = n + m # Initialize the gap as the total number of elements

gap = next_gap(gap) # Find the initial gap


while gap > 0:
# First, compare elements in arr1
i=0
while i + gap < n:
if arr1[i] > arr1[i + gap]:
arr1[i], arr1[i + gap] = arr1[i + gap], arr1[i] # Swap
i += 1

# Now, compare elements between arr1 and arr2


j = gap - n if gap > n else 0
while i < n and j < m:
if arr1[i] > arr2[j]:
arr1[i], arr2[j] = arr2[j], arr1[i] # Swap
i += 1
j += 1

# Lastly, compare elements in arr2


if j < m:
j=0
while j + gap < m:
if arr2[j] > arr2[j + gap]:
arr2[j], arr2[j + gap] = arr2[j + gap], arr2[j] # Swap
j += 1

# Reduce the gap for the next iteration


gap = next_gap(gap)

# Example usage:
arr1 = [1, 4, 7, 8, 10]
arr2 = [2, 3, 9]
n = len(arr1)
m = len(arr2)
merge(arr1, arr2, n, m)
print("Merged arr1:", arr1)
print("Merged arr2:", arr2)

13. Kadane's Algo [V.V.V.V.V IMP]


def kadane(arr):
# Initialize variables
max_current = arr[0] # This will track the current subarray sum
max_global = arr[0] # This will store the global maximum sum

for i in range(1, len(arr)):


# Update max_current by including the current element or starting a new subarray
max_current = max(arr[i], max_current + arr[i])

# Update max_global if max_current is greater


if max_current > max_global:
max_global = max_current

return max_global

# Example usage:
arr = [-2, 1, -3, 4, -1, 2, 1, -5, 4]
result = kadane(arr)
print(f"The maximum subarray sum is: {result}")

14. Merge Intervals

def merge_intervals(intervals):
if not intervals:
return []

# Step 1: Sort the intervals by the start time


intervals.sort(key=lambda x: x[0])

# Step 2: Initialize the result with the first interval


merged = [intervals[0]]

for i in range(1, len(intervals)):


# If the current interval overlaps with the last merged interval, merge them
if intervals[i][0] <= merged[-1][1]:
merged[-1][1] = max(merged[-1][1], intervals[i][1])
else:
# If not overlapping, add the current interval to the merged list
merged.append(intervals[i])

return merged

# Example usage:
intervals = [[1, 3], [2, 6], [8, 10], [15, 18]]
result = merge_intervals(intervals)
print(f"Merged Intervals: {result}")

15. Next Permutation


def next_permutation(nums):
# Step 1: Find the first decreasing element from the right
i = len(nums) - 2
while i >= 0 and nums[i] >= nums[i + 1]:
i -= 1

# If no such element is found, the list is sorted in descending order


if i == -1:
nums.reverse()
return nums

# Step 2: Find the next larger element to swap with nums[i]


j = len(nums) - 1
while nums[j] <= nums[i]:
j -= 1

# Step 3: Swap the two elements


nums[i], nums[j] = nums[j], nums[i]

# Step 4: Reverse the elements to the right of i


nums[i + 1:] = reversed(nums[i + 1:])

return nums

# Example usage:
nums = [1, 2, 3]
print(next_permutation(nums)) # Output: [1, 3, 2]

16. Count Inversion

def merge_and_count(arr, temp_arr, left, mid, right):


i = left # Starting index for left subarray

j = mid + 1 # Starting index for right subarray

k = left # Starting index to be sorted

inv_count = 0

# Merge the two subarrays

while i <= mid and j <= right:

if arr[i] <= arr[j]:

temp_arr[k] = arr[i]

i += 1

else:

temp_arr[k] = arr[j]

inv_count += (mid-i + 1) # All remaining elements in the left subarray are inversions

j += 1

k += 1

# Copy the remaining elements of the left subarray, if any

while i <= mid:

temp_arr[k] = arr[i]

i += 1

k += 1

# Copy the remaining elements of the right subarray, if any

while j <= right:


temp_arr[k] = arr[j]

j += 1

k += 1

# Copy the sorted subarray into the original array

for i in range(left, right + 1):

arr[i] = temp_arr[i]

return inv_count

def merge_sort_and_count(arr, temp_arr, left, right):

inv_count = 0

if left < right:

mid = (left + right)//2

inv_count += merge_sort_and_count(arr, temp_arr, left, mid)

inv_count += merge_sort_and_count(arr, temp_arr, mid + 1, right)

inv_count += merge_and_count(arr, temp_arr, left, mid, right)

return inv_count

def count_inversions(arr):

temp_arr = [0]*len(arr)
return merge_sort_and_count(arr, temp_arr, 0, len(arr)-1)

# Example usage

arr = [1, 20, 6, 4, 5]

print(f"Number of inversions are {count_inversions(arr)}")

17. def max_profit(prices):


if not prices:

return 0

min_price = float('inf') # Initialize the minimum price as infinity

max_profit = 0 # Initialize maximum profit

for price in prices:

if price < min_price:

min_price = price # Update minimum price

elif price - min_price > max_profit:

max_profit = price - min_price # Update maximum profit

return max_profit

# Example usage

prices = [7, 1, 5, 3, 6, 4]

print(f"Maximum profit: {max_profit(prices)}")


19. def find_pairs(arr, target_sum):

seen = set() # Set to store numbers we have seen

pairs = [] # List to store the result pairs

for num in arr:

# Calculate the number needed to form the target sum

complement = target_sum - num

# If the complement exists in the set, we found a pair

if complement in seen:

pairs.append((complement, num))

# Add the current number to the set

seen.add(num)

return pairs

# Example usage

arr = [1, 5, 7, -1, 5]

target_sum = 6

result = find_pairs(arr, target_sum)

print(f"Pairs with sum {target_sum}: {result}")

20. def find_common_elements(arr1, arr2, arr3):


i, j, k = 0, 0, 0 # Initialize pointers for arr1, arr2, and arr3

common_elements = []

# Traverse all three arrays while elements are left in all of them

while i < len(arr1) and j < len(arr2) and k < len(arr3):

# If all three elements are equal, add it to the result and move all pointers

if arr1[i] == arr2[j] == arr3[k]:

common_elements.append(arr1[i])

i += 1

j += 1

k += 1

# Move the pointer in the array with the smallest element

elif arr1[i] < arr2[j]:

i += 1

elif arr2[j] < arr3[k]:

j += 1

else:

k += 1

return common_elements

# Example usage

arr1 = [1, 5, 10, 20, 40, 80]

arr2 = [6, 7, 20, 80, 100]


arr3 = [3, 4, 15, 20, 30, 70, 80, 120]

result = find_common_elements(arr1, arr2, arr3)

print(f"Common elements: {result}")

21. def rearrange_alternate(arr):

n = len(arr)

# Step 1: Partition the array to move negative numbers to the left side and positive numbers
to the right side

i = -1 # Index of last negative number

for j in range(n):

if arr[j] < 0:

i += 1

arr[i], arr[j] = arr[j], arr[i] # Swap negative number to the left side

# Now, all negative numbers are on the left and positive numbers are on the right

pos = i + 1 # Index of first positive number

neg = 0 # Index of first negative number

# Step 2: Swap alternately

while pos < n and neg < pos and arr[neg] < 0:

# Swap negative and positive numbers

arr[neg], arr[pos] = arr[pos], arr[neg]

pos += 1
neg += 2 # Move the negative index by 2 to maintain alternating order

return arr

# Example usage

arr = [1, 2, 3, -4, -1, 4, -6, -9, -10]

result = rearrange_alternate(arr)

print(f"Rearranged array: {result}")

22. def subarray_with_zero_sum(arr):

# Create an empty set to store cumulative sums

cumulative_sum = set()

# Initialize the sum of elements

current_sum = 0

# Traverse through the array

for num in arr:

# Add current element to cumulative sum

current_sum += num

# If current sum is 0 or already exists in the set, we found a subarray with sum 0

if current_sum == 0 or current_sum in cumulative_sum:

return True
# Add the current sum to the set

cumulative_sum.add(current_sum)

# No subarray with 0 sum was found

return False

# Example usage

arr = [4, 2, -3, 1, 6]

result = subarray_with_zero_sum(arr)

print(f"Subarray with zero sum exists: {result}")

23. def factorial(n):

result = 1

for i in range(2, n + 1):

result *= i

return result

# Example usage

n = 100 # Large number

print(f"Factorial of {n} is: {factorial(n)}")

24. def max_product_subarray(arr):

if not arr:
return 0

# Initialize variables

max_so_far = min_so_far = result = arr[0]

# Traverse through the array

for num in arr[1:]:

# If current element is negative, swap max and min

if num < 0:

max_so_far, min_so_far = min_so_far, max_so_far

# Update max_so_far and min_so_far

max_so_far = max(num, max_so_far * num)

min_so_far = min(num, min_so_far * num)

# Update result with the maximum product found so far

result = max(result, max_so_far)

return result

# Example usage

arr = [2, 3, -2, 4]

result = max_product_subarray(arr)

print(f"Maximum product subarray: {result}")


25. def longest_consecutive_subsequence(arr):

if not arr:

return 0

# Insert all elements into a set for O(1) lookups

num_set = set(arr)

longest_streak = 0

# Iterate over each number in the array

for num in num_set:

# Check if it's the start of a sequence

if num - 1 not in num_set:

current_num = num

current_streak = 1

# Count the length of the consecutive sequence

while current_num + 1 in num_set:

current_num += 1

current_streak += 1

# Update the maximum streak length

longest_streak = max(longest_streak, current_streak)


return longest_streak

# Example usage

arr = [100, 4, 200, 1, 3, 2]

result = longest_consecutive_subsequence(arr)

print(f"Length of the longest consecutive subsequence: {result}")

26. def find_elements_appearing_more_than_n_by_k(arr, k):

n = len(arr)

if k <= 1:

return arr # If k is 1 or less, all elements are valid

# Step 1: Find potential candidates

candidates = {}

for num in arr:

if num in candidates:

candidates[num] += 1

elif len(candidates) < k - 1:

candidates[num] = 1

else:

to_remove = []

for key in candidates:

candidates[key] -= 1

if candidates[key] == 0:
to_remove.append(key)

for key in to_remove:

del candidates[key]

# Step 2: Verify the candidates

candidates = {num: 0 for num in candidates.keys()}

for num in arr:

if num in candidates:

candidates[num] += 1

# Collect all candidates that appear more than n/k times

result = []

for num, count in candidates.items():

if count > n // k:

result.append(num)

return result

# Example usage

arr = [1, 2, 3, 1, 1, 2, 2, 3, 3, 4, 4]

k=3

result = find_elements_appearing_more_than_n_by_k(arr, k)

print(f"Elements appearing more than n/k times: {result}")


27. def max_profit_with_two_transactions(prices):

n = len(prices)

if n == 0:

return 0

# Initialize arrays to store profits

profit_one = [0] * n

profit_two = [0] * n

# Compute maximum profit for one transaction

min_price = prices[0]

for i in range(1, n):

min_price = min(min_price, prices[i])

profit_one[i] = max(profit_one[i - 1], prices[i] - min_price)

# Compute maximum profit for two transactions

max_price = prices[-1]

for i in range(n - 2, -1, -1):

max_price = max(max_price, prices[i])

profit_two[i] = max(profit_two[i + 1], max_price - prices[i])

# Combine results to find the maximum profit with two transactions

max_profit = 0

for i in range(n):
max_profit = max(max_profit, profit_one[i] + profit_two[i])

return max_profit

# Example usage

prices = [12, 14, 17, 10, 14, 13, 12, 15]

result = max_profit_with_two_transactions(prices)

print(f"Maximum profit with at most two transactions: {result}")

28. def is_subset(arr1, arr2):

# Convert arr1 to a set for O(1) average time complexity for membership checks

set_arr1 = set(arr1)

# Check if all elements of arr2 are present in set_arr1

for element in arr2:

if element not in set_arr1:

return False

return True

# Example usage

arr1 = [11, 1, 13, 21, 3, 7]

arr2 = [11, 3, 7]

result = is_subset(arr1, arr2)


print(f"Array {arr2} is a subset of array {arr1}: {result}")

29. def find_triplets(arr, target_sum):

arr.sort() # Sort the array

n = len(arr)

triplets = []

for i in range(n - 2):

left = i + 1

right = n - 1

while left < right:

current_sum = arr[i] + arr[left] + arr[right]

if current_sum == target_sum:

triplets.append((arr[i], arr[left], arr[right]))

# Move pointers to avoid duplicates

while left < right and arr[left] == arr[left + 1]:

left += 1

while left < right and arr[right] == arr[right - 1]:

right -= 1

left += 1

right -= 1

elif current_sum < target_sum:

left += 1

else:
right -= 1

return triplets

# Example usage

arr = [1, 2, -1, 0, -2, 1]

target_sum = 0

result = find_triplets(arr, target_sum)

print(f"Triplets that sum to {target_sum}: {result}")

30. def trap(height):

if not height:

return 0

n = len(height)

left_max = [0] * n

right_max = [0] * n

# Fill left_max array

left_max[0] = height[0]

for i in range(1, n):

left_max[i] = max(left_max[i - 1], height[i])

# Fill right_max array


right_max[n - 1] = height[n - 1]

for i in range(n - 2, -1, -1):

right_max[i] = max(right_max[i + 1], height[i])

# Calculate total water trapped

total_water = 0

for i in range(n):

total_water += min(left_max[i], right_max[i]) - height[i]

return total_water

# Example usage

height = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]

result = trap(height)

print(f"Total trapped water: {result}")

31. def find_min_diff(arr, m):

n = len(arr)

# Edge case: If number of students is more than packets, return -1

if m > n:

return -1

# Sort the array


arr.sort()

# Initialize the minimum difference

min_diff = float('inf')

# Slide the window of size m across the sorted array

for i in range(n - m + 1):

current_diff = arr[i + m - 1] - arr[i]

min_diff = min(min_diff, current_diff)

return min_diff

# Example usage

arr = [12, 4, 7, 9, 2, 23, 25, 41, 30, 40, 28, 42, 30, 44, 48, 43, 50]

m = 7 # Number of students

result = find_min_diff(arr, m)

print(f"Minimum difference is: {result}")

32. def smallest_subarray_with_sum(arr, target_sum):

n = len(arr)

min_length = float('inf')

current_sum = 0

start = 0
for end in range(n):

current_sum += arr[end]

# Contract the window as long as the current_sum is greater than the target_sum

while current_sum > target_sum:

min_length = min(min_length, end - start + 1)

current_sum -= arr[start]

start += 1

return min_length if min_length != float('inf') else 0

# Example usage

arr = [1, 4, 45, 6, 10, 19]

target_sum = 51

result = smallest_subarray_with_sum(arr, target_sum)

print(f"Length of the smallest subarray with sum greater than {target_sum}: {result}")

33. def three_way_partition(arr, pivot):

low = 0

mid = 0

high = len(arr) - 1

while mid <= high:

if arr[mid] < pivot:


arr[low], arr[mid] = arr[mid], arr[low]

low += 1

mid += 1

elif arr[mid] == pivot:

mid += 1

else:

arr[high], arr[mid] = arr[mid], arr[high]

high -= 1

# Example usage

arr = [3, 8, 2, 1, 5, 6, 4, 7]

pivot = 5

three_way_partition(arr, pivot)

print(f"Array after three-way partitioning around {pivot}: {arr}")

34. def min_swaps_to_bring_elements_together(arr, K):

n = len(arr)

# Count the number of elements less than or equal to K

count = sum(1 for x in arr if x <= K)

# Find the number of elements greater than K in the initial window of size `count`

current_window = sum(1 for i in range(count) if arr[i] > K)

min_swaps = current_window
# Slide the window across the array

for i in range(count, n):

if arr[i] > K:

current_window += 1

if arr[i - count] > K:

current_window -= 1

min_swaps = min(min_swaps, current_window)

return min_swaps

# Example usage

arr = [1, 3, 5, 2, 8, 6, 4, 7]

K=5

result = min_swaps_to_bring_elements_together(arr, K)

print(f"Minimum swaps required: {result}")

35. def min_operations_to_make_palindrome(arr):

n = len(arr)

l, r = 0, n - 1

operations = 0

while l < r:
if arr[l] != arr[r]:

operations += 1

l += 1

r -= 1

return operations

# Example usage

arr = [1, 3, 5, 3, 1]

result = min_operations_to_make_palindrome(arr)

print(f"Minimum operations required: {result}")

36. def find_median_sorted_arrays(A, B):

n = len(A)

# Ensure A is the smaller array

if len(A) > len(B):

A, B = B, A

# Binary search on the smaller array A

low, high = 0, len(A)

while low <= high:

partitionA = (low + high) // 2


partitionB = (n + n + 1) // 2 - partitionA

maxLeftA = float('-inf') if partitionA == 0 else A[partitionA - 1]

minRightA = float('inf') if partitionA == len(A) else A[partitionA]

maxLeftB = float('-inf') if partitionB == 0 else B[partitionB - 1]

minRightB = float('inf') if partitionB == len(B) else B[partitionB]

if maxLeftA <= minRightB and maxLeftB <= minRightA:

# Correct partition

if (n + n) % 2 == 0:

return (max(maxLeftA, maxLeftB) + min(minRightA, minRightB)) / 2.0

else:

return max(maxLeftA, maxLeftB)

elif maxLeftA > minRightB:

# Too far right on A, move left

high = partitionA - 1

else:

# Too far left on A, move right

low = partitionA + 1

raise ValueError("Input arrays are not sorted or have invalid sizes")

# Example usage
A = [1, 3, 8, 9, 15]

B = [7, 11, 19, 21, 18]

result = find_median_sorted_arrays(A, B)

print(f"Median of the two sorted arrays: {result}")

37. def find_median_sorted_arrays(A, B):

# Ensure A is the smaller array

if len(A) > len(B):

A, B = B, A

m, n = len(A), len(B)

low, high = 0, m

while low <= high:

partitionA = (low + high) // 2

partitionB = (m + n + 1) // 2 - partitionA

maxLeftA = float('-inf') if partitionA == 0 else A[partitionA - 1]

minRightA = float('inf') if partitionA == m else A[partitionA]

maxLeftB = float('-inf') if partitionB == 0 else B[partitionB - 1]

minRightB = float('inf') if partitionB == n else B[partitionB]

if maxLeftA <= minRightB and maxLeftB <= minRightA:


if (m + n) % 2 == 0:

return (max(maxLeftA, maxLeftB) + min(minRightA, minRightB)) / 2.0

else:

return max(maxLeftA, maxLeftB)

elif maxLeftA > minRightB:

high = partitionA - 1

else:

low = partitionA + 1

raise ValueError("Input arrays are not sorted or have invalid sizes")

# Example usage

A = [1, 3, 8]

B = [7, 9, 10, 11]

result = find_median_sorted_arrays(A, B)

print(f"Median of the two sorted arrays: {result}")


1. def count_set_bits_bitwise(n):

count = 0

while n:

count += n & 1 # Increment count if the least significant bit is 1

n >>= 1 # Right shift the bits of the number

return count

# Example usage

n = 29 # Binary representation: 11101

result = count_set_bits_bitwise(n)

print(f"Number of set bits in {n} using bit manipulation: {result}")

2. def find_two_non_repeating_elements(arr):

# Step 1: XOR all elements

xor_all = 0

for num in arr:

xor_all ^= num

# Step 2: Find a set bit in xor_all (rightmost set bit)

set_bit = xor_all & -xor_all


# Step 3: Initialize variables to hold the two unique numbers

num1, num2 = 0, 0

# Step 4: Divide elements into two groups and XOR separately

for num in arr:

if num & set_bit:

num1 ^= num

else:

num2 ^= num

return num1, num2

# Example usage

arr = [4, 3, 2, 7, 8, 2, 3, 1]

result = find_two_non_repeating_elements(arr)

print(f"The two non-repeating elements are: {result}")

3. def count_bits_to_flip(A, B):

# Step 1: XOR A and B

xor_result = A ^ B

# Step 2: Count the number of set bits in the XOR result

count = 0

while xor_result:
count += xor_result & 1 # Increment count if the least significant bit is 1

xor_result >>= 1 # Right shift the bits of the XOR result

return count

# Example usage

A = 29 # Binary: 11101

B = 15 # Binary: 01111

result = count_bits_to_flip(A, B)

print(f"Number of bits to flip to convert {A} to {B}: {result}")

4. def count_set_bits(n):

count = 0

i=0

while (1 << i) <= n:

# Total pairs of bits in the current position

total_pairs = (n + 1) // (1 << (i + 1)) * (1 << i)

# Count of remaining bits in the last incomplete group

remaining_bits = max(0, (n + 1) % (1 << (i + 1)) - (1 << i))

# Add the counts


count += total_pairs + remaining_bits

i += 1

return count

# Example usage

n=5

result = count_set_bits(n)

print(f"Total number of set bits from 1 to {n}: {result}")

5. def is_power_of_two(n):

# A number is a power of two if it has exactly one bit set and is greater than zero

return n > 0 and (n & (n - 1)) == 0

# Example usage

n = 16

result = is_power_of_two(n)

print(f"{n} is a power of two: {result}")

6. def find_position_of_set_bit(n):

# Check if the number is a power of two

if n <= 0 or (n & (n - 1)) != 0:

raise ValueError("The number does not have exactly one set bit.")
# Find the position of the only set bit

position = 1

while n > 1:

n >>= 1 # Right shift the number to find the bit position

position += 1

return position

# Example usage

n = 16 # Binary: 00010000

position = find_position_of_set_bit(n)

print(f"The position of the only set bit in {n} is: {position}")

7. def copy_set_bits(src, target, start, end):

# Mask to isolate the bits in the range [start, end]

# Create a mask with 1s in the range [start, end]

all_ones = ~0 # This is -1 in binary (all bits set to 1)

left = all_ones << (end + 1) # Mask for bits left of the range

right = (1 << start) - 1 # Mask for bits right of the range

mask = left | right # Combine masks to isolate the range

# Clear the bits in the target number within the range [start, end]

target_cleared = target & mask


# Extract bits from the source number

src_bits = (src >> start) & ~(mask >> start)

# Copy the extracted bits to the target number

target_with_bits = target_cleared | (src_bits << start)

return target_with_bits

# Example usage

src = 0b1101 # Source number (binary: 1101)

target = 0b0000 # Target number (binary: 0000)

start = 1 # Starting position of the range (0-based index)

end = 3 # Ending position of the range (0-based index)

result = copy_set_bits(src, target, start, end)

print(f"Target after copying set bits: {bin(result)}")

8. def divide(dividend, divisor):

# Constants for the bounds of integer values

INT_MAX = 2**31 - 1

INT_MIN = -2**31

# Handle special cases

if dividend == 0:
return 0

if divisor == 0:

raise ValueError("Cannot divide by zero.")

# Determine the sign of the result

negative = (dividend < 0) != (divisor < 0)

# Work with positive numbers for simplicity

dividend, divisor = abs(dividend), abs(divisor)

quotient = 0

power = 31 # Assuming 32-bit integers

# Find the largest power of two multiple of the divisor

while dividend >= divisor:

# Find the highest bit where (divisor << power) is <= dividend

while (divisor << power) > dividend:

power -= 1

# Update dividend and quotient

dividend -= divisor << power

quotient += 1 << power

# Apply the sign to the quotient


if negative:

quotient = -quotient

# Handle overflow cases

if quotient < INT_MIN:

return INT_MIN

if quotient > INT_MAX:

return INT_MAX

return quotient

# Example usage

dividend = 10

divisor = 3

result = divide(dividend, divisor)

print(f"Result of dividing {dividend} by {divisor} is: {result}")

10. def square_number(n):

# Handle the case where n is negative

if n < 0:

n = -n # Square of a negative number is the same as the square of its positive counterpart

result = 0

odd_number = 1
# Sum the first n odd numbers

for _ in range(n):

result += odd_number

odd_number += 2

return result

# Example usage

number = 5

result = square_number(number)

print(f"The square of {number} is: {result}")

11. def power_set(nums):

power_set_size = 1 << len(nums) # 2^n

result = []

for i in range(power_set_size):

subset = []

for j in range(len(nums)):

# Check if the j-th bit in i is set

if i & (1 << j):

subset.append(nums[j])

result.append(subset)
return result

# Example usage

nums = [1, 2, 3]

result = power_set(nums)

print(f"Power set of {nums}: {result}")

1. class TrieNode:
def __init__(self):
self.children = {} # Dictionary to store child nodes
self.is_end_of_word = False # Flag to mark the end of a word
class Trie:
def __init__(self):
self.root = TrieNode() # Initialize the root of the trie

def insert(self, word):


node = self.root
for char in word:
if char not in node.children:
node.children[char] = TrieNode() # Create a new node if it does not exist
node = node.children[char]
node.is_end_of_word = True # Mark the end of the word

def search(self, word):


node = self.root
for char in word:
if char not in node.children:
return False # Word not found
node = node.children[char]
return node.is_end_of_word # Return True if it is the end of the word

def starts_with(self, prefix):


node = self.root
for char in prefix:
if char not in node.children:
return False # Prefix not found
node = node.children[char]
return True # Return True if the prefix is found

# Example usage
trie = Trie()
trie.insert("hello")
trie.insert("world")

print(trie.search("hello")) # Output: True


print(trie.search("hell")) # Output: False
print(trie.starts_with("hell")) # Output: True
print(trie.starts_with("worl")) # Output: True
print(trie.starts_with("worlds")) # Output: False

2. class TrieNode:
def __init__(self):
self.children = {} # Dictionary to store child nodes
self.count = 0 # Count of how many words pass through this node
class Trie:
def __init__(self):
self.root = TrieNode()

def insert(self, word):


node = self.root
for char in word:
if char not in node.children:
node.children[char] = TrieNode()
node = node.children[char]
node.count += 1 # Increment count for each node visited

def find_unique_prefix(self, word):


node = self.root
prefix = ''
for char in word:
prefix += char
node = node.children[char]
if node.count == 1: # Unique prefix found
return prefix
return prefix
def find_shortest_unique_prefixes(words):
trie = Trie()

# Insert all words into the trie


for word in words:
trie.insert(word)

# Find the shortest unique prefix for each word


unique_prefixes = {}
for word in words:
unique_prefixes[word] = trie.find_unique_prefix(word)

return unique_prefixes

# Example usage
words = ["apple", "banana", "appetizer", "bat", "batman"]
unique_prefixes = find_shortest_unique_prefixes(words)
print("Shortest unique prefixes:")
for word, prefix in unique_prefixes.items():
print(f"{word}: {prefix}")

4. class TrieNode:
def __init__(self):
self.children = {}
self.is_end_of_word = False
class Trie:
def __init__(self):
self.root = TrieNode()
def insert(self, word):
node = self.root
for char in word:
if char not in node.children:
node.children[char] = TrieNode()
node = node.children[char]
node.is_end_of_word = True
def word_break(s, dictionary):
# Build the trie from the dictionary
trie = Trie()
for word in dictionary:
trie.insert(word)

# DP array to check if the string can be segmented


dp = [False] * (len(s) + 1)
dp[0] = True # Empty string is always a valid segmentation

# Iterate over each position in the string


for i in range(1, len(s) + 1):
node = trie.root
# Check all substrings ending at position i
for j in range(i, 0, -1):
if s[j-1] in node.children:
node = node.children[s[j-1]]
if node.is_end_of_word and dp[j-1]:
dp[i] = True
break
else:
break

return dp[len(s)]

# Example usage
dictionary = ["apple", "pie", "applepie"]
s = "applepie"
print(word_break(s, dictionary)) # Output: True

s = "applepieb"
print(word_break(s, dictionary)) # Output: False

6. from collections import defaultdict

def group_anagrams(words):
# Dictionary to store lists of anagrams
anagram_dict = defaultdict(list)

# Group words by their sorted character tuple


for word in words:
sorted_word = ''.join(sorted(word))
anagram_dict[sorted_word].append(word)

# Print all groups of anagrams


for group in anagram_dict.values():
print(group)

# Example usage
words = ["eat", "tea", "tan", "ate", "nat", "bat"]
group_anagrams(words)

7. class PhoneDirectory:
def __init__(self):
self.contacts = {} # Dictionary to store contacts

def add_contact(self, name, phone_number):


"""Add a contact to the directory."""
if name in self.contacts:
print(f"Contact '{name}' already exists. Updating phone number.")
self.contacts[name] = phone_number
print(f"Contact '{name}' added/updated with phone number {phone_number}.")

def remove_contact(self, name):


"""Remove a contact from the directory."""
if name in self.contacts:
del self.contacts[name]
print(f"Contact '{name}' removed.")
else:
print(f"Contact '{name}' not found.")

def search_contact(self, name):


"""Search for a contact by name."""
if name in self.contacts:
return f"Contact '{name}' found with phone number {self.contacts[name]}."
else:
return f"Contact '{name}' not found."

def list_contacts(self):
"""List all contacts in the directory."""
if self.contacts:
for name, phone_number in self.contacts.items():
print(f"Name: {name}, Phone Number: {phone_number}")
else:
print("No contacts in the directory.")

# Example usage
directory = PhoneDirectory()
directory.add_contact("Alice", "123-456-7890")
directory.add_contact("Bob", "987-654-3210")
print(directory.search_contact("Alice"))
print(directory.search_contact("Charlie"))
directory.list_contacts()
directory.remove_contact("Alice")
directory.list_contacts()

8. def print_unique_rows(matrix):
unique_rows = set()

# Iterate through each row in the matrix


for row in matrix:
# Convert the row to a tuple (for immutability and hashing)
row_tuple = tuple(row)
if row_tuple not in unique_rows:
# Add the row to the set and print it
unique_rows.add(row_tuple)
print(row)

# Example usage
matrix = [
[1, 0, 1],
[0, 1, 0],
[1, 0, 1],
[0, 1, 0],
[1, 1, 0]
]

print("Unique rows in the matrix:")


print_unique_rows(matrix)

1. class MinHeap:
def __init__(self):
self.heap = []

def parent(self, i):


return (i - 1) // 2

def left_child(self, i):


return 2 * i + 1

def right_child(self, i):


return 2 * i + 2

def min_heapify(self, i):


smallest = i
left = self.left_child(i)
right = self.right_child(i)

if left < len(self.heap) and self.heap[left] < self.heap[smallest]:


smallest = left

if right < len(self.heap) and self.heap[right] < self.heap[smallest]:


smallest = right

if smallest != i:
self.heap[i], self.heap[smallest] = self.heap[smallest], self.heap[i]
self.min_heapify(smallest)

def insert(self, key):


self.heap.append(key)
index = len(self.heap) - 1
while index > 0 and self.heap[self.parent(index)] > self.heap[index]:
self.heap[self.parent(index)], self.heap[index] = self.heap[index],
self.heap[self.parent(index)]
index = self.parent(index)

def extract_min(self):
if len(self.heap) < 1:
return None
min_item = self.heap[0]
self.heap[0] = self.heap.pop()
self.min_heapify(0)
return min_item

def build_min_heap(self):
for i in range(len(self.heap) // 2 - 1, -1, -1):
self.min_heapify(i)

def __str__(self):
return str(self.heap)

# Example usage
min_heap = MinHeap()
min_heap.insert(10)
min_heap.insert(20)
min_heap.insert(5)
min_heap.build_min_heap()
print("Min-Heap:", min_heap)
print("Extract Min:", min_heap.extract_min())
print("Min-Heap after extraction:", min_heap)

2. class MaxHeap:
def __init__(self, array):
self.heap = array
self.build_max_heap()

def parent(self, i):


return (i - 1) // 2

def left_child(self, i):


return 2 * i + 1

def right_child(self, i):


return 2 * i + 2

def max_heapify(self, i, size):


largest = i
left = self.left_child(i)
right = self.right_child(i)

if left < size and self.heap[left] > self.heap[largest]:


largest = left

if right < size and self.heap[right] > self.heap[largest]:


largest = right

if largest != i:
self.heap[i], self.heap[largest] = self.heap[largest], self.heap[i]
self.max_heapify(largest, size)

def build_max_heap(self):
for i in range(len(self.heap) // 2 - 1, -1, -1):
self.max_heapify(i, len(self.heap))

def heap_sort(array):
max_heap = MaxHeap(array)
size = len(max_heap.heap)

for i in range(size - 1, 0, -1):


# Swap the root of the heap with the last element
max_heap.heap[0], max_heap.heap[i] = max_heap.heap[i], max_heap.heap[0]
# Reduce the size of the heap and heapify the root
max_heap.max_heapify(0, i)

return max_heap.heap

# Example usage
array = [4, 10, 3, 5, 1]
sorted_array = heap_sort(array)
print("Sorted Array:", sorted_array)

3. from collections import deque

def max_of_subarrays(arr, k):


if not arr or k <= 0:
return []

n = len(arr)
if k > n:
return []

max_elements = []
dq = deque() # To store indices of array elements

for i in range(n):
# Remove elements outside the current window
if dq and dq[0] == i - k:
dq.popleft()

# Remove elements from the deque that are smaller than the current element
while dq and arr[dq[-1]] < arr[i]:
dq.pop()
# Add the current element's index to the deque
dq.append(i)

# The maximum of the current window is at the front of the deque


if i >= k - 1:
max_elements.append(arr[dq[0]])

return max_elements

# Example usage
arr = [1, 3, -1, -3, 5, 3, 6, 7]
k=3
print("Maximum of all subarrays of size", k, ":", max_of_subarrays

4. import heapq

def k_largest_elements_heap(arr, k):


if k <= 0 or k > len(arr):
return []

# Build a min-heap of the first k elements


min_heap = arr[:k]
heapq.heapify(min_heap)

for num in arr[k:]:


if num > min_heap[0]:
heapq.heappushpop(min_heap, num)

return sorted(min_heap, reverse=True)

# Example usage
arr = [3, 2, 1, 5, 6, 4]
k=2
print("The", k, "largest elements are:", k_largest_elements_heap(arr, k))

5. import heapq
def kth_smallest_largest_heap(arr, k):
if k <= 0 or k > len(arr):
return None, None

# Min-Heap for k-th largest element


min_heap = []
for num in arr:
if len(min_heap) < k:
heapq.heappush(min_heap, num)
elif num > min_heap[0]:
heapq.heappushpop(min_heap, num)

kth_largest = min_heap[0]

# Max-Heap for k-th smallest element (using negative values for max-heap simulation)
max_heap = []
for num in arr:
if len(max_heap) < k:
heapq.heappush(max_heap, -num)
elif -num > max_heap[0]:
heapq.heappushpop(max_heap, -num)

kth_smallest = -max_heap[0]

return kth_smallest, kth_largest

# Example usage
arr = [3, 2, 1, 5, 6, 4]
k=2
kth_smallest, kth_largest = kth_smallest_largest_heap(arr, k)
print(f"The {k}th smallest element is: {kth_smallest}")
print(f"The {k}th largest element is: {kth_largest}")

6. import heapq

def kth_smallest_largest_heap(arr, k):


if k <= 0 or k > len(arr):
return None, None

# Min-Heap for k-th largest element


min_heap = []
for num in arr:
if len(min_heap) < k:
heapq.heappush(min_heap, num)
elif num > min_heap[0]:
heapq.heappushpop(min_heap, num)

kth_largest = min_heap[0]

# Max-Heap for k-th smallest element (using negative values for max-heap simulation)
max_heap = []
for num in arr:
if len(max_heap) < k:
heapq.heappush(max_heap, -num)
elif -num > max_heap[0]:
heapq.heappushpop(max_heap, -num)

kth_smallest = -max_heap[0]

return kth_smallest, kth_largest

# Example usage
arr = [3, 2, 1, 5, 6, 4]
k=2
kth_smallest, kth_largest = kth_smallest_largest_heap(arr, k)
print(f"The {k}th smallest element is: {kth_smallest}")
print(f"The {k}th largest element is: {kth_largest}")

7. import heapq

class ListNode:
def __init__(self, value=0, next=None):
self.value = value
self.next = next

def __lt__(self, other):


return self.value < other.value

def merge_k_sorted_linked_lists(lists):
if not lists:
return None

min_heap = []

# Initialize the heap with the head of each linked list


for i, node in enumerate(lists):
if node:
heapq.heappush(min_heap, (node.value, i, node))

# Dummy node to simplify the merging process


dummy = ListNode()
current = dummy

while min_heap:
_, index, node = heapq.heappop(min_heap)
current.next = node
current = current.next

# If there is a next node in the same list, add it to the heap


if node.next:
heapq.heappush(min_heap, (node.next.value, index, node.next))

return dummy.next

# Helper function to create a linked list from a list of values


def create_linked_list(values):
if not values:
return None
head = ListNode(values[0])
current = head
for value in values[1:]:
current.next = ListNode(value)
current = current.next
return head

# Helper function to print a linked list


def print_linked_list(head):
current = head
while current:
print(current.value, end=" -> " if current.next else "\n")
current = current.next

# Example usage
lists = [
create_linked_list([1, 4, 5]),
create_linked_list([1, 3, 4]),
create_linked_list([2, 6])
]

merged_head = merge_k_sorted_linked_lists(lists)
print("Merged linked list:")
print_linked_list(merged_head)

8.

You might also like