Top Problems must be revised before interview
- Array
- Binary Search On Sorted Array
- Rotate An Array By N Elements
- Rotated Binary Search
- Smallest Common Number Between Three Arrays
- Find Low and High Index of a key in sorted array
- Move all Zeros to the beging of the Array
- Best Time to Buy and Sell Stock to Maximize Profit
- Merge An Array with Overlapping Intervals
- Find Pair With Given Sum in Array
- Squares Of a Sorted Array
- Container With Most Water
- Quick Sort Algorithm
- Sort Colors
- Arrange The Largest Number
- Shuffle Array
- First Missing Positive Integer
- Minimum Size Subarray Sum
- Next Element Greater Than Subset
- Product of All Elements Except Itself in an Array
- Linked-List
- Implementation of Single Linked List
- Reverse a Single Linked List
- Remove Duplicate From Linked List
- Delete All Occurrences of a Given Key in a Linked List
- Insertion Sort on Linked List
- Intersection of Linked Lists
- Nth Node from End of Linked List
- Swap Nth Node with Head
- Merge Two Sorted Linked Lists
- Merge Sort on Linked List
- Reverse Even Nodes In A Linked List
- Rotate List
- Reorder List
- Add Two Integers Represented as Linked Lists
- Deep Copy
- Math-&-Stats
- Strings
- Trees
- Stack-&-Queues
- Graph
- Back-Tracking
- Dynamic-Programming
- Miscellaneous
Binary Search is the most efficient way to search in Sorted array.
Time Complexity : O(logn)
Space Complexity : O(1) (iterative Solution), O(logn) recursive Solution
- first initialize two variables (low,high) with 0 and length of array
- start a loop which ends when low becomes equal or greater than high
- initialize a variable mid which will be the mid value of low and high, you can get using (low+mid)/2 but a better way to avoid overflow or underflow we should low + (high-low)/2
- than check if nums[mid] is equal to our target value
- [true] return with the mid index
- [false]else if than check if nums[mid] is greater than target
- [true] set high variable with mid -1
- [false] else if than check if nums[mid] is smaller than target
- [true] set low variable with mid + 1
- return -1 index it means element is not present in array
def binary_search(nums, target):
low = 0
high = len(nums) - 1
while low <= high:
mid = low + ((high - low) // 2)
if nums[mid] == target:
return mid
elif target < nums[mid]:
high = mid - 1
elif target > nums[mid]:
low = mid + 1
return -1O(*log*n) where n is the length of array
O(1) no extra space is used
- check base case (low is greater or equal to high) if true return -1 // it means target is not present in array
- calculate mid index of low and high use mid = low+high/2 or mid = low+(high-low)/2
- check if nums[mid] equal to target
- [true] HURRAH! (we found the element in array) return mid
- [False] check if nums[mid] smaller to target
def binary_search_rec(nums,target,low, high):
if low>=high:
return -1
mid = low + (high-low)/2
if nums[mid] == target:
return mid
if nums[mid] < target:
return binary_search_rec(nums,target, low, mid-1)
else:
return binary_search_rec(nums,target, mid+1, low)O(*log*n) where n is the length of array
O(*log*n) recursive stack space is used
We’re given an array of integers, nums. Rotate the array by n elements, where n is an integer:
- For positive values of n, perform a right rotation.
- For negative values of n, perform a left rotation. Make sure we make changes to the original array.
Original Array
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 1 | 10 | 20 | 0 | 59 | 86 | 32 | 11 | 9 | 40 |
After Rotation if N=3
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 11 | 9 | 40 | 1 | 10 | 20 | 0 | 59 | 86 | 32 |
After Rotation from Original if N= -2
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 20 | 0 | 59 | 86 | 32 | 11 | 9 | 40 | 1 | 10 |
Sample Input
nums = [2, 13, 15, 1, 0, 4]
n = 2
Expected Output
[0, 4 ,2, 13, 15, 1]
- Write a function to reverse Array from a index to b index
- get length of array
l - normalize
Nby taking modulus by lengthN=N%l - reverse array nums from 0 index to l-1 complete reverse
- reverse array nums from 0 index to n-1
- reverse array nums from n index to l-1
- return nums
def rotate_array(nums, n):
def reverse_array(nums, s,e):
while(s<e):
nums[s],nums[e] = nums[e],nums[s]
s+=1
e-=1
return nums
l = len(nums)
n = n%l
nums = reverse_array(nums,0,l-1)
nums = reverse_array(nums,0,n-1)
nums = reverse_array(nums,n,l-1)
return numsO(n) where n is length of array
O(1) no extra space is used
We’re given a sorted integer array, array and an integer value, key. The array is rotated by some arbitrary number. Search the target in this array. If the target does not exist then return -1.
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 13 | 14 | 20 | 0 | 2 | 3 | 5 | 7 | 8 | 11 |
array = [13, 14, 20, 0, 2, 3, 5, 7, 8, 11]
key = 20
2
- initialize low = 0 and high = length of array -1
- if low is greater than high return -1
- start loop till low is less than or equal to high
- initialize mid = low + (high-low)/2 we can also do mid = (low+high)/2 but this can cause overflow
- check if array[mid] is equal to key if yes return mid
- else check id array[low] is less than or equal to array[mid] if yes then
- check if key is greater than array[low] and key is less than array[mid] if yes then set high = mid-1
- else set low = mid+1
- else
- check if key is greater than array[mid] and key is less than array[high] if yes then set low = mid+1
- else set high = mid-1
- return -1
def binary_search_rotated(nums, target):
low = 0
high = len(nums)-1
if low>=high:
return -1
while low < high:
mid = low + (high-low)//2
if target == nums[mid]:
return mid
if nums[low] <= nums[mid]:
if target < nums[mid] and target >= nums[low]:
high = mid - 1
else:
low = mid + 1
else:
if target < nums[mid] and target <= nums[high]:
low = mid - 1
else:
high = mid + 1
return -1O(logn) where n is length of array
O(1) no extra space is used
Given three integer arrays sorted in ascending order, find the smallest number that is common in all three arrays. For example, let's look at the below three arrays. Here 6 is the smallest number that's common in all the arrays.
Input: [6, 7, 10, 25, 30, 63, 64], [0, 4, 5, 6, 7, 8, 50], [1, 6, 10, 14]
Output: 6
1. initialize i=0, j=0, k=0
2. start loop till i is less than length of array1 and j is less than length of array2 and k is less than length of array3
1. check if array1[i] is equal to array2[j] and array2[j] is equal to array3[k] if yes then return array1[i]
2. else check if array1[i] is less than array2[j] and array1[i] is less than array3[k] if yes then increment i
3. else check if array2[j] is less than array1[i] and array2[j] is less than array3[k] if yes then increment j
4. else increment k
3. return -1
def find_least_common_number(a, b, c):
i = 0
j = 0
k = 0
while i < len(a) and j < len(b) and k < len(c):
if a[i] == b[j] and b[j] == c[k]:
return a[i]
elif a[i] <= b[j] and a[i] <= c[k]:
i += 1
elif b[j] <= a[i] and b[j] <= c[k]:
j += 1
elif c[k] <= a[i] and c[k] <= b[j]:
k += 1
return -1O(n) where n is length of array
O(1) no extra space is used
Given a sorted array of integers, return the low and high index of the given key. Return -1 if not found. The array length can be in millions with lots of duplicates.
Input: [1, 2, 5, 5, 5, 5, 5, 5, 5, 5, 20]
Output: 2, 9
LOW INDEX
- initialize
low = 0andhigh = length of array -1 - initialize
mid = low + (high-low)/2we can also domid = (low+high)/2but this can cause overflow - start loop till
low <= high- check if
array[mid] <= keyif yes then setlow = mid+1 - else set
high = mid-1
- check if
- check if
array[low] == keyandlow < length of arrayif yes thenreturn low - else
return -1
HIGH INDEX
- initialize
low = 0andhigh = length of array -1 - initialize
mid = low + (high-low)/2we can also domid = (low+high)/2but this can cause overflow - start loop till
low <= high- check if
array[mid] == keyif yes then sethigh = mid-1 - else set
low = mid+1
- check if
- check if
array[high]is equal tokeyif yes thenreturn high - else
return -1
def find_low_index(arr, key):
low = 0
high = len(arr) - 1
mid = high // 2
while low <= high:
mid_elem = arr[mid]
if mid_elem < key:
low = mid + 1
else:
high = mid - 1
mid = low + (high - low) // 2
if low < len(arr) and arr[low] == key:
return low
return -1
def find_high_index(arr, key):
low = 0
high = len(arr) - 1
mid = high // 2
while low <= high:
mid_elem = arr[mid]
if mid_elem <= key:
low = mid + 1
else:
high = mid - 1
mid = low + (high - low) // 2
if high == -1:
return high
if high < len(arr) and arr[high] == key:
return high
return -1O(logn) where n is length of array
O(1) no extra space is used
Given an integer array, move all elements containing '0' to the left while maintaining the order of other elements in the array.
Input: [1,10,20,0,59,63,0,88,0]
Output: [0,0,0,1,10,20,59,63,88]
- initialize
write_index = length of array -1 - start loop from
length of array -1till0- check if
array[i] != 0if yes then setarray[write_index] = array[i]andwrite_index -= 1
- check if
- start loop from
write_indextill0and setarray[i] = 0
def move_zeros_to_left(nums):
i = len(nums) - 1
j = i
while i >= 0:
if nums[i]:
nums[j]=nums[i]
j-=1
i-=1
while j>=0:
nums[j] = 0
j-=1
return numsO(n) where n is length of array
O(1) no extra space is used
Given an array of numbers representing the daily stock prices of a company in chronological order, write a function that calculates the maximum profit you could have made from buying and selling that stock once. You must buy before you can sell it.
Input: [9, 11, 8, 5, 7, 10]
Output: 5
- check if
arrayisNoneorlength of array < 2if yes thenreturn None - initialize
current_buy = array[0],global_sell = array[1],global_profit = global_sell - current_buy,current_profit = float('-inf') - start loop from
1tilllength of array- set
current_profit = array[i] - current_buy - check if
current_profit > global_profitif yes then setglobal_profit = current_profitandglobal_sell = array[i] - check if
current_buy > array[i]if yes then setcurrent_buy = array[i]
- set
return global_sell - global_profit, global_sell
def find_buy_sell_stock_prices(array):
if array == None or len(array) < 2:
return None
current_buy = array[0]
global_sell = array[1]
global_profit = global_sell - current_buy
current_profit = float('-inf')
for i in range(1, len(array)):
current_profit = array[i] - current_buy
if current_profit > global_profit:
global_profit = current_profit
global_sell = array[i]
if current_buy > array[i]:
current_buy = array[i]
result = global_sell - global_profit, global_sell
return resultO(n) where n is length of array
O(1) no extra space is used
Given an array (list) of intervals as input where each interval has a start and end timestamps. Input array is sorted by starting timestamps. You are required to merge overlapping intervals and return output array (list).
Input: [(1, 5), (3, 7), (4, 6), (6, 8), (10, 12), (11, 15)]
Output: [(1, 8), (10, 15)]
- initialize
merged = [] - start loop from
1tilllength of array- check if
array[i][0] <= merged[-1][1]if yes then setmerged[-1][1] = max(merged[-1][1], array[i][1]) - else append
array[i]tomerged
- check if
return merged
def merge_intervals(v):
result = [v[0]]
j = 1
for i in range(1,len(v)):
if result[j-1][2] >= v[i][0]:
if v[i][1] > result[j-1][1]:
result[j-1][1] = v[i][0]
else:
result.append(v[i])
j+=1
return resultO(n) where n is length of array
O(1) no extra space is used
Given an unsorted array of integers, find a pair with given sum in it.
Input: [8, 7, 2, 5, 3, 1]
Sum: 10
Output: [0, 2] or [1, 4]
- initialize
hash_map = {} - start loop from
0tilllength of array- check if
array[i] in hash_mapif yes thenreturn True - else
hash_map[sum - array[i]] = i
- check if
return False
def find_sum_of_two(A, val):
hash_map = {}
for i in range(len(A)):
if A[i] in hash_map:
return True
else:
hash_map[val - A[i]] = A[i]
return FalseO(n) where n is length of array
O(n) where n is length of array for hash_map
Given an integer array nums sorted in non-decreasing order, return an array of the squares of each number sorted in non-decreasing order.
Input: nums = [-4,-1,0,3,10]
Output: [0,1,9,16,100]
- initialize
result = [] - initialize
left = 0,right = len(array) - 1 - start loop from
righttillleft- check if
abs(array[left]) > abs(array[right])if yes thenresult.append(array[left] * array[left])andleft += 1 - else
result.append(array[right] * array[right])andright -= 1
- check if
return result[::-1]to reverse the array
def sortedSquares(nums):
result = []
left = 0
right = len(nums) - 1
while left <= right:
if abs(nums[left]) > abs(nums[right]):
result.append(nums[left] * nums[left])
left += 1
else:
result.append(nums[right] * nums[right])
right -= 1
return result[::-1]O(n) where n is length of array
O(n) where n is length of array for result
Given n non-negative integers a1, a2, ..., an , where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of the line i is at (i, ai) and (i, 0). Find two lines, which, together with the x-axis forms a container, such that the container contains the most water.
Input: height = [1,8,6,2,5,4,8,3,7]
Output: 49
- initialize
left = 0,right = len(array) - 1 - initialize
max_area = 0 - start loop from
lefttillright- check if
array[left] < array[right]if yes thenmax_area = max(max_area, array[left] * (right - left))andleft += 1 - else
max_area = max(max_area, array[right] * (right - left))andright -= 1
- check if
return max_area
def max_water_area_container(height):
i = 0
j = len(height)-1
max_water = 0
while(i<j):
hi,hj= height[i],height[j]
container = min(hi,hj)* (j-i)
if max_water < container:
max_water = container
if hi < hj:
i+=1
else:
j-=1
return max_waterO(n) where n is length of array
O(1) no extra space is used
Given an array of integers, sort the array in ascending order using the Quick Sort algorithm.
Input: [8, 7, 2, 5, 3, 1]
Output: [1, 2, 3, 5, 7, 8]
Partition
- initialize
pivot_value = array[low] - initialize
i = low,j = high - start loop till
i < j- start loop till
i <= j and array[i] <= pivot_valueif yes theni += 1 - start loop till
array[j] > pivot_valueif yes thenj -= 1 - check if
i < jif yes thenarray[i], array[j] = array[j], array[i]
- start loop till
array[low], array[j] = array[j], pivot_valuereturn j
Quick Sort Helper
- check if
low < highif yes thenpivot_index = partition(array, low, high)quick_sort_helper(array, low, pivot_index-1)quick_sort_helper(array, pivot_index+1, high)
Quick Sort
quick_sort_helper(array, 0, len(array)-1)return array
def partition(nums, low, high):
pivot_value = nums[low]
i = low
j = high
while i<j:
while i <= j and nums[i] <= pivot_value:
i += 1
while nums[j] > pivot_value:
j-=1
if i<j:
nums[i], nums[j] = nums[j], nums[i]
nums[low], nums[j] = nums[j], pivot_value
return j
def quick_sort_helper(nums, low, high):
if low < high:
pivot_index = partition(nums, low, high)
quick_sort_helper(nums, low, pivot_index-1)
quick_sort_helper(nums, pivot_index+1, high)
def quick_sort(nums):
quick_sort_helper(nums, 0, len(nums)-1)
return numsO(nlogn) where n is length of array
O(logn) where n is length of array for recursion stack
Given an array nums with n objects colored red, white, or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white, and blue. We will use the integers 0, 1, and 2 to represent the color red, white, and blue, respectively.
Input: nums = [2,0,2,1,1,0]
Output: [0,0,1,1,2,2]
- initialize
low = 0,mid = 0,high = len(array) - 1 - start loop till
mid <= high- check if
array[mid] == 0if yes thenarray[low], array[mid] = array[mid], array[low]andlow += 1 - check if
array[mid] == 1if yes thenmid += 1 - check if
array[mid] == 2if yes thenarray[mid], array[high] = array[high], array[mid]andhigh -= 1
- check if
return array
def sort_colors(nums):
low = 0
mid = 0
high = len(nums) - 1
while mid <= high:
if nums[mid] == 0:
nums[low], nums[mid] = nums[mid], nums[low]
low += 1
mid += 1
elif nums[mid] == 1:
mid += 1
else:
nums[mid], nums[high] = nums[high], nums[mid]
high -= 1
return numsO(n) where n is length of array
O(1) no extra space is used
Given a list of non negative integers, arrange them in such a manner that they form the largest number possible.The result is going to be very large, hence return the result in the form of a string.
Input: [3, 30, 34, 5, 9]
Output: 9534330
- initialize
array = [str(i) for i in array] - sort the array using
lambdafunction return ''.join(array)
class LargerNumKey(str):
def __lt__(x,y):
return x+y > y+x
def largest_number(nums):
mapStr = map(str, nums)
mapStr = sorted(mapStr,key=LargerNumKey)
largest = ''.join(mapStr)
return '0' if largest[0] == '0' else largestO(nlogn) where n is length of array
O(n) where n is length of array for extra space used for storing string
Given an unsorted integer array nums, find the smallest missing positive integer.
Input: nums = [1,2,0]
Output: 3
- initialize
i = 0 - start loop till
i < len(array)- check if
array[i] > 0 and array[i] <= len(array) and array[i] != array[array[i]-1]if yes thenarray[array[i]-1], array[i] = array[i], array[array[i]-1]elsei += 1
- check if
- start loop till
i < len(array)- check if
array[i] != i+1if yes thenreturn i+1elsei += 1
- check if
return len(array)+1
def first_missing_positive(nums):
i = 0
while i < len(nums):
if nums[i] > 0 and nums[i] <= len(nums) and nums[i] != nums[nums[i]-1]:
nums[nums[i]-1], nums[i] = nums[i], nums[nums[i]-1]
else:
i += 1
i = 0
while i < len(nums):
if nums[i] != i+1:
return i+1
else:
i += 1
return len(nums)+1O(n) where n is length of array
O(1) no extra space is used
Given an array of positive integers nums and a positive integer target, return the minimal length of a contiguous subarray [numsl, numsl+1, ..., numsr-1, numsr] of which the sum is greater than or equal to target. If there is no such subarray, return 0 instead.
Input: target = 7, nums = [2,3,1,2,4,3]
Output: 2
- initialize
left = 0,sum1 = 0,result = float('inf') - start loop till
i < len(array)sum1 += array[i]- start loop till
sum1 >= targetresult = min(result,(i+1) - left)sum1 -= array[left]left += 1
- check if
result == float('inf')if yes thenreturn 0elsereturn result
def min_sub_array_len(target, nums):
left = 0
sum1 = 0
result = float('inf')
for i in range(len(nums)):
sum1 += nums[i]
while sum1>= target:
result = min(result,(i+1) - left)
sum1 -= nums[left]
left+=1
if result == float('inf'):
return 0
return resultO(n) where n is length of array
O(1) no extra space is used
Given an array, find the next greater element G[i] for every element A[i] in the array. The Next greater Element for an element A[i] is the first greater element on the right side of A[i] in array. More formally,
Input
nums1 = [4,1,2]
nums2 = [1,3,4,2].
Output
[-1, 3, -1]
- initialize
stack = [] - initialize
hash_map = {} - start loop from
0tilllength of array2- check if
stack is not empty and array2[i] > stack[-1]if yes thenhash_map[stack.pop()] = array2[i] - append
array2[i]tostack
- check if
- start loop from
0tilllength of array1- check if
array1[i] in hash_mapif yes thenarray1[i] = hash_map[array1[i]]elsearray1[i] = -1
- check if
- return
array1
def next_greater_element(nums1, nums2):
stack = []
hash_map = {}
for i in range(len(nums2)):
while stack and nums2[i] > stack[-1]:
hash_map[stack.pop()] = nums2[i]
stack.append(nums2[i])
for i in range(len(nums1)):
if nums1[i] in hash_map:
nums1[i] = hash_map[nums1[i]]
else:
nums1[i] = -1
return nums1O(n) where n is length of array
O(n) where n is length of array for stack and hash_map
Given an array of integers, return a new array such that each element at index i of the new array is the product of all the numbers in the original array except the one at i.
Input: [1, 2, 3, 4, 5]
Output: [120, 60, 40, 30, 24]
- initialize
result = [1] * len(array) - initialize
left = [1] * len(array) - initialize
right = [1] * len(array) - start loop from
1tilllength of arrayleft[i] = left[i-1] * array[i-1]
- start loop from
length of array - 2till-1right[i] = right[i+1] * array[i+1]
- start loop from
0tilllength of arrayresult[i] = left[i] * right[i]
- return
result
def product_except_self(nums):
result = [1] * len(nums)
left = [1] * len(nums)
right = [1] * len(nums)
for i in range(1, len(nums)):
left[i] = left[i-1] * nums[i-1]
for i in range(len(nums)-2, -1, -1):
right[i] = right[i+1] * nums[i+1]
for i in range(len(nums)):
result[i] = left[i] * right[i]
return resultO(n) where n is length of array
O(n) where n is length of array for left, right and result
class Node
private:
<variable> data
<Pointer Node> next
public:
<function> constructor(data):
mine.data = data
mine.next = NULL
class SingleLinkedList
private:
<Pointer Node> head
public:
<function> constructor():
head = NULL
<function> constructor(<variable> data):
head = Node(data)
<function> constructor(<Pointer Node> head):
<Pointer Node> ptr = head
mine.head = NULL
while ptr != NULL:
mine.insert_at_tail(ptr.data)
ptr = ptr.next
<function> insert_at_head(<variable> data):
<Pointer Node> new_node = Node(data)
if head == NULL:
head = new_node
else:
new_node.next = head
head = new_node
<function> insert_at_tail(<variable> data):
<Pointer Node> new_node = Node(data)
if head == NULL:
head = new_node
else:
<Pointer Node> ptr = head
while ptr.next != NULL:
ptr = ptr.next
ptr.next = new_node
<function> insert_at_position(<variable> data, <variable> position):
<Pointer Node> new_node = Node(data)
if head == NULL:
head = new_node
else:
<Pointer Node> ptr = head
<Pointer Node> prev = NULL
<variable> count = 0
while ptr != NULL and count < position:
prev = ptr
ptr = ptr.next
count += 1
prev.next = new_node
new_node.next = ptr
<function> delete_at_head():
if head == NULL:
return
else:
<Pointer Node> ptr = head
head = head.next
ptr.next = NULL
delete ptr
<function> delete_at_tail():
if head == NULL:
return
else:
<Pointer Node> ptr = head
<Pointer Node> prev = NULL
while ptr.next != NULL:
prev = ptr
ptr = ptr.next
prev.next = NULL
delete ptr
<function> delete_at_position(<variable> position):
if head == NULL:
return
else:
<Pointer Node> ptr = head
<Pointer Node> prev = NULL
<variable> count = 0
while ptr != NULL and count < position:
prev = ptr
ptr = ptr.next
count += 1
prev.next = ptr.next
ptr.next = NULL
delete ptr
<function> delete_by_value(<variable> data):
if head == NULL:
return
else:
<Pointer Node> ptr = head
<Pointer Node> prev = NULL
while ptr != NULL and ptr.data != data:
prev = ptr
ptr = ptr.next
if ptr == NULL:
return
else:
prev.next = ptr.next
ptr.next = NULL
delete ptr
<function> search(<variable> data):
if head == NULL:
return False
else:
<Pointer Node> ptr = head
while ptr != NULL and ptr.data != data:
ptr = ptr.next
if ptr == NULL:
return False
else:
return True
Given a singly linked list, write a function to reverse the linked list.
Input: 1->2->3->4->5->NULL
Output: 5->4->3->2->1->NULL
- initialize
prev = NULL,curr = head,next = NULL - start loop till
curr != NULLnext = curr.nextcurr.next = prevprev = currcurr = next
head = prev- return
head
def reverseLinkedList(head):
if head is None or head.next is None:
return head
prev = None
curr = head
next = None
while curr is not None:
next = curr.next
curr.next = prev
prev = curr
curr = next
head = prev
return headNode* reverseLinkedList(Node* head){
if (head == NULL || head->next == NULL)
return head;
Node *prev = NULL;
Node *curr = head;
Node *next = NULL;
while(curr != NULL){
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
head = prev;
return head;
}O(n) where n is length of linked list
O(1) no extra space is used
Given a linked list, delete all duplicates such that each element appear only once. Linked List can be unSorted
Input: 1->2->3->3->2->1->NULL
Output: 1->2->3->NULL
- initialize
ptr = head - initialize
hash_set = set() - add
ptr.datatohash_set - while
ptr.next != NULL- check if
ptr.next.data in hash_setif yes thenptr.next = ptr.next.next - else
hash_set.add(ptr.next.data)andptr = ptr.next
- check if
- return
head
def removeDuplicates(head):
if head is None or head.next is None:
return head
curr = head
hashset = set()
hashset.add(curr.data)
while curr.next is not None:
if curr.next.data in hashset:
curr.next = curr.next.next
else:
hashset.add(curr.next.data)
curr = curr.next
return head0Node* removeDuplicates(Node* head){
if (head == NULL || head->next == NULL)
return head;
Node *curr = head;
unordered_set<int> hashset;
hashset.insert(curr->data);
while(curr->next != NULL){
if (hashset.find(curr->next->data) != hashset.end()){
curr->next = curr->next->next;
}
else{
hashset.insert(curr->next->data);
curr = curr->next;
}
}
return head;
}O(n) where n is length of linked list
O(n) used for hashset
Given a singly linked list, delete all occurrences of a given key in it. Linked List can be unSorted
Input: 1->2->3->3->2->1->NULL, key = 2
Output: 1->3->3->1->NULL
- if
head == NULLreturnNULL - initialize
curr = head,prev = NULL - while
curr != NULL- if
curr.data == key- if
prev == NULLthenhead = curr.nextandcurr = head - else
prev.next = curr.nextandcurr = curr.next
- if
- else
prev = currandcurr = curr.next
- if
- return
head
def deleteAllOccurences(head, key):
if head is None:
return None
curr = head
prev = None
while curr is not None:
if curr.value == key:
if prev is None:
head = curr.next
curr = head
else:
prev.next = curr.next
curr = curr.next
else:
prev = curr
curr = curr.next
return headNode* deleteAllOccurences(Node * Head, int key){
if (Head == NULL)
return;
Node *curr = Head;
Node *prev = NULL;
while(curr != NULL){
if (curr->data == key){
if (prev == NULL){
Head = curr->next;
curr = Head;
}
else{
prev->next = curr->next;
curr = curr->next;
}
}
else{
prev = curr;
curr = curr->next;
}
}
return Head;
}O(n) where n is length of linked list
O(1) no extra space is used
Given a linked list, sort it using insertion sort.
Input: 1->3->2->4->5->1->NULL
Output: 1->1->2->3->4->5->NULL
- if
node == NULLreturnhead - if
head == NULLornode.value <= head.valuethennode.next = headand returnnode - initialize
curr = head - while
curr.next != NULLandcurr.next.value < node.valuethencurr = curr.next
node.next = curr.nextandcurr.next = node- return
head
- if
head == NULLreturnNULL - initialize
sorted_list = NULL,curr = head - while
curr != NULL- initialize
temp = curr.next sorted_list = sorted_insert(sorted_list, curr)curr = temp
- initialize
- return
sorted_list
def sorted_insert(head, node):
if node is None:
return head
if head is None or node.value <= head.value:
node.next = head
return node
curr = head
while curr.next is not None and curr.next.value < node.value:
curr = curr.next
node.next = curr.next
curr.next = node
return head
def insertion_sort(head):
if head is None:
return None
sorted_list = None
curr = head
while curr is not None:
temp = curr.next
sorted_list = sorted_insert(sorted_list, curr)
curr = temp
return sorted_listO(n^2) where n is length of linked list
O(1) no extra space is used
Given two singly linked lists of size N and M, write a program to get the point where two linked lists intersect each other.
- initialize
l1 = length(head1),l2 = length(head2) - if
l1 > l2thenreturn intersect(head2, head1) - initialize
diff = l2 - l1,curr1 = head1,curr2 = head2 - for
i = 0todiffdocurr2 = curr2.next - while
curr1 != NULLandcurr2 != NULLdo- if
curr1 == curr2thenreturn curr1 curr1 = curr1.next,curr2 = curr2.next
- if
- return
NULL
def intersect(head1, head2):
l1 = length(head1)
l2 = length(head2)
if l1 > l2:
return intersect(head2, head1)
diff = l2 - l1
curr1 = head1
curr2 = head2
for i in range(diff):
curr2 = curr2.next
while curr1 is not None and curr2 is not None:
if curr1 == curr2:
return curr1
curr1 = curr1.next
curr2 = curr2.next
return NoneO(n) where n is length of linked list
O(1) no extra space is used
- initialize
hash_set = set(),curr = head1 - while
curr != NULLdohash_set.add(curr),curr = curr.next - initialize
curr = head2 - while
curr != NULLandcurr not in hash_setdocurr = curr.next - return
curr
def intersect_using_extra_space(head1,head2):
hash_set = set()
curr = head1
while curr is not None:
hash_set.add(curr)
curr = curr.next
curr = head2
while curr is not None and curr not in hash_set:
curr = curr.next
return currO(n) where n is length of linked list
O(n) used for hashset
Given a linked list consisting of L nodes and given a number N. The task is to find the Nth node from the end of the linked list.
Input: 1->2->3->4->5, N = 2
Output: 4
- initialize
ptr = head - while
n > 0andptr != NULLdoptr = ptr.next,n -= 1 - if
ptr == NULLandn > 0thenreturn NULL - while
ptr != NULLdoptr = ptr.next,head = head.next - return
head
def find_nth_from_end(head,n):
ptr = head
while n>0 and ptr is not None:
ptr = ptr.next
n-=1
if ptr is None and n>0:
return None
while ptr is not None:
ptr = ptr.next
head = head.next
return headO(n) where n is length of linked list
O(1) no extra space is used
Given a singly Linked List, write a function to swap the Nth node from the beginning with head
Input: 1->2->3->4->5, N = 4
Output: 4->2->3->1->5
- initialize
prev = head,curr = head - while
n > 0andcurr.next != NULLdoprev = curr,curr = curr.next,n -= 1 - if
n == 0andprev != NULLthenswap(prev, head) - return
head
def swap_nth_node(head, n):
prev = head
curr = head
while n>0 and curr.next is not None:
prev = curr
curr = curr.next
n-=1
if n==0 and prev is not None:
head.value, prev.value = prev.value, head.value
return headO(n) where n is length of linked list
O(1) no extra space is used
Given two sorted linked lists consisting of N and M nodes respectively. The task is to merge both of the list (in-place) and return head of the merged list.
Input: 1->3->5->7->9, 2->4->6->8
Output: 1->2->3->4->5->6->7->8->9
- if
head1 == NULLthenreturn head2 - if
head2 == NULLthenreturn head1 - if
head1.value < head2.valuethenhead1.next = merge_sorted(head1.next, head2),return head1 - else
head2.next = merge_sorted(head1, head2.next),return head2
def merge_sorted(head1, head2):
if head1 is None:
return head2
if head2 is None:
return head1
if head1.value < head2.value:
head1.next = merge_sorted(head1.next, head2)
return head1
else:
head2.next = merge_sorted(head1, head2.next)
return head2O(n+m) where n and m are length of linked lists
O(1) no extra space is used
Given Pointer/Reference to the head of a doubly linked list of N nodes, the task is to Sort the given doubly linked list using Merge Sort in both non-decreasing and non-increasing order.
Input: 8->4->2->5
Output: 2->4->5->8
- check if
head == NULLthenreturn head - initialize
slow = head,fast = head - while
fast.next != NULLandfast.next.next != NULLdoslow = slow.next,fast = fast.next.next - return
slow
- check if
head == NULLorhead.next == NULLthenreturn head - initialize
mid = get_mid(head),next_to_mid = mid.next,mid.next = NULL - initialize
left = merge_sort(head),right = merge_sort(next_to_mid) - initialize
sorted_list = merge_sorted(left, right) - return
sorted_list
def get_middle(head):
if head is None:
return head
slow = head
fast = head
while fast.next is not None and fast.next.next is not None:
slow = slow.next
fast = fast.next.next
return slow
def merge_sort(head):
if head is None or head.next is None:
return head
mid = get_mid(head)
next_to_mid = mid.next
mid.next = None
left = merge_sort(head)
right = merge_sort(next_to_mid)
sorted_list = merge_sorted(left, right)
return sorted_listO(nlogn) where n is length of linked list
O(1) no extra space is used
Given a singly linked list, reverse nodes at even indices (starting at 1).
Input: 1->2->3->4->5->6->NULL
Output: 1->6->3->4->5->2->NULL
- initialize
curr = head,l_even = NULL - while
curr != NULLandcurr.next != NULLdoeven = curr.next,curr.next = even.next,even.next = l_even,l_even = even,curr = curr.next - return
head,l_even
- if
odd == NULLthenreturn even - if
even == NULLthenreturn odd - initialize
head = odd - while
odd.next != NULLdotemp = odd.next,odd.next = even,even = even.next,odd.next.next = temp,odd = temp odd.next = even- return
head
- initialize
odd,even = odd_and_even_nodes(head) - return
merge_alternate(odd, even)
def odd_and_even_nodes(head):
curr = head
l_even = None
while curr and curr.next:
even = curr.next
curr.next = even.next
even.next = l_even
l_even = even
curr = curr.next
return head, l_even
def merge_alternate(odd, even):
if not odd:
return even
if not even:
return odd
head = odd
while odd.next:
temp = odd.next
odd.next = even
even = even.next
odd.next.next = temp
odd = temp
odd.next = even
return head
def reverse_even_nodes(head):
odd,even = odd_and_even_nodes(head)
return merge_alternate(odd, even)O(n) where n is length of linked list
O(1) no extra space is used
Given a singly linked list, rotate the linked list counter-clockwise by k nodes. Where k is a given positive integer. For example, if the given linked list is 10->20->30->40->50->60 and k is 4, the list should be modified to 50->60->10->20->30->40. Assume that k is smaller than the count of nodes in linked list.
Input: 1->2->3->4->5->NULL, k = 2
Output: 3->4->5->1->2->NULL
- initialize
n = n % len(head) - if
n == 0orhead == NULLthenreturn head - initialize
curr = head - for
i in range(n-1)docurr = curr.next - initialize
new_head = curr.next curr.next = NULLcurr = new_head- while
curr.next != NULLdocurr = curr.next curr.next = head- return
new_head
def rotate_list(head,n):
n = n % len(head)
if n == 0 or not head:
return head
curr = head
for i in range(n-1):
curr = curr.next
new_head = curr.next
curr.next = None
curr = new_head
while curr.next:
curr = curr.next
curr.next = head
return new_headO(n) where n is length of linked list
O(1) no extra space is used
Given a singly linked list L: L0→L1→…→Ln-1→Ln, reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→… You must do this in-place without altering the nodes' values. For example, Given {1,2,3,4}, reorder it to {1,4,2,3}.
Input: 1->2->3->4->NULL
Output: 1->4->2->3->NULL
- if
head == NULLthenreturn NULL, NULL - initialize
slow = head,fast = head.next - while
fast != NULLandfast.next != NULLdoslow = slow.next,fast = fast.next.next - initialize
head2 = slow.next slow.next = NULL- initialize
rev_head2 = NULL - while
head2 != NULLdotemp = head2.next,head2.next = rev_head2,rev_head2 = head2,head2 = temp head2 = rev_head2- return
head,head2
Explained Above in Odd and Even Nodes Problem Link
- initialize
head1, head2 = halves(head) - return
merge_alternate(head1, head2)
def halves(head):
if not head:
return None, None
slow = head
fast = head.next
while fast and fast.next:
slow = slow.next
fast = fast.next.next
head2 = slow.next
slow.next = None
rev_head2 = None
while head2:
temp = head2.next
head2.next = rev_head2
rev_head2 = head2
head2 = temp
head2 = rev_head2
return head, head2
def merge_alternate(head1, head2):
if not head1:
return head2
if not head2:
return head1
head = head1
while head1.next:
temp = head1.next
head1.next = head2
head2 = head2.next
head1.next.next = temp
head1 = temp
head1.next = head2
return head
def reorder_list(head):
head1, head2 = halves(head)
return merge_alternate(head1, head2)O(n) where n is length of linked list
O(1) no extra space is used
Given two numbers represented by two lists, write a function that returns sum list. The sum list is list representation of addition of two input numbers. Suppose the digits are stored in forward order. In that case, repeat the above problem. Given two numbers represented by two lists, write a function that returns sum list. The sum list is list representation of addition of two input numbers.
Input:
First List: 5->6->3 // represents number 365
Second List: 8->4->2 // represents number 248
Output:
Resultant list: 3->1->6 // represents number 613
- initialize
carry = 0 - initialize
head = None - while
int1 != NULLorint2 != NULLorcarry != 0do- initialize
sum = carry - if
int1 != NULLthensum += int1.value,int1 = int1.next - if
int2 != NULLthensum += int2.value,int2 = int2.next - initialize
digit = sum % 10 carry = sum // 10- if
head == NULLthenhead = LinkedListNode(digit),tail = head - else
tail.next = LinkedListNode(digit),tail = tail.next
- initialize
- return
head
def add_integers(int1,int2):
carry = 0
head = None
while int1 or int2 or carry:
sum = carry
if int1:
sum += int1.value
int1 = int1.next
if int2:
sum += int2.value
int2 = int2.next
digit = sum % 10
carry = sum // 10
if not head:
head = LinkedListNode(digit)
tail = head
else:
tail.next = LinkedListNode(digit)
tail = tail.next
return headO(n) where n is length of linked list
O(1) no extra space is used
Given a linked list. We have to copy the given linked list such that change in one copy will not reflect in other.
Input : 1->2->3->4->5
Output : 1`->2`->3`->4`->5`
- initialize
deep_head = None,deep_tail = None,curr = head - while
curr != NULLdo- if
deep_head == NULLthendeep_head = LinkedListNode(curr.value),deep_tail = deep_head - else
deep_tail.next = LinkedListNode(curr.value),deep_tail = deep_tail.next curr = curr.next
- if
- return
deep_head
def deep_copy_list(head):
deep_head = None
deep_tail = None
curr = head
while curr:
if not deep_head:
deep_head = LinkedListNode(curr.value)
deep_tail = deep_head
else:
deep_tail.next = LinkedListNode(curr.value)
deep_tail = deep_tail.next
curr = curr.next
return deep_headO(n) where n is length of linked list
O(n) where n is length of linked list for new Linked List.