# Array & vectors
- Sequential memory locations
- random access by zero based indexing - O(1)
- cache friendly -> improves system level performance asymptotically same
- cache(fastest) -> ram -> hard drive
- in C++ arrays are fixed sized
### Types
- fixed size arrays
- dynamic sized arrays
- c++ - vector
- java - array list
- pythion - list
### Operations
- Search
- unsorted - TC: O(n)
- sorted - TC: O(log n) -> depending on runtime implmentation it can have SC: O(n)
- Insert
- insert in middle or begining - TC: O(n)
- insert when array is not full -> shift elements to right and insert in middle - O(n)
- insert when array is full -> create 2n array and copy all elements in left, insert and insert right elements O(n), Auxillary space -> O(n)
- insert at the end - TC: O(1)
- deletion
- delete at the begining or middle - TC: O(n)
- delete at the end - TC: O(1)
- Getting ith Element: TC: O(1)
- Updating ith element: TC: O(1)
``` python
a = [1, 2, 3, 4]
a.append(5)
a.pop() # removes last element and return it
len(a)
a[:] # clone
a[:2] # first two elements in array # [1, 2]
a[1:3] # from 1st index element to 3rd index element # [2, 3]
a[-3:] # last three lements
a.index(3) # index of 3 if item not found it throws ValueError exception
filter(None, a) # return list without None values
# Iterate
for i, x in enumerate(nums):
print(i, x)
for i in range(len(nums)):
print(i)
for x in nums:
print(x)
nums.sort() # TC: O(nlogn) SC: O(1) or O(n) depending on runtime implementation
nums.sort(reverse=True)
nums.sort(key=lambda x: x[1])
nums.insert(1, 10) # TC: O(n) SC: O(1)
```
### Vectors or list or dynamic sized arrays
dynamic sized array implementation is called vectors
- implimentation using arrays or linked list
- array implimentation is prefered because its cache friendly and memory compact since there are no attional pointers
### Operations
- Insert at end -> O(n) worst cast -> O(1) amotized analysis or average case - since we cannot get worst case at each step
- Insert in middle -> O(n)
- Given an array you have to reverse it
- Complexity
- TC - O(n)
- SC - O(1)
- Logic -> two pointer approach, loop from zero to n/2 and swap
``` python
def reverse(arr):
n = len(arr)
for l in range(n // 2):
r = n - 1 - i
arr[l], arr[r] = arr[r], arr[l]
return arr
```
- find an element in unsorted array
- complexity
- TC - O(n)
- SC - O(1)
- Logic -> traverse find an element then return true or else reach to end and return false
- worst case is if item is not found or item is last element
``` python
# TC: O(n)
# SC: O(1)
def search(arr, target):
for i, x in enumerate(arr):
if x == target:
return i
return -1
```
- number of distinct elements
- array of input elements, 0 < arr[i] < 1000.
- Note: use visited array
``` python
# TC: O(n)
# SC: O(1)
def count_distinct(arr, target):
visited = [False] * 1000
for x in arr:
if visited[x] == False:
visited[x] = True
result = 0
for x in visited:
if x == True:
result += 1
return result
```
- number of element frequency
- array of input elements, 0 < arr[i] < 1000.
- Note: use count array or frequency array
``` python
# TC: O(n)
# SC: O(1)
def freqency(arr, target):
freq = [0] * 1000
for x in arr:
visited[x] += 1
return freq
```
- sort the array aka bucket search ideal if there are limited charecter set
- array of input elements, 0 < arr[i] < 1000.
- Note: use count array and print them
``` python
# TC: O(n)
# SC: O(1)
def sort(arr, target):
freq = [0] * 1000
for x in arr:
visited[x] += 1
result = []
for i, x in enumerate(freq):
if x > 0:
for j in range(x):
result.append(i)
return result
```
- find largest element in an array
- TC: O(n) SC: O(1)
- find second largest element in an array
- Two pass method
- first pass find the largest - find the index of largest
- second pass find the second largest - find the index of seond largest which is not the value of first largest element
- TC O(n) SC:(1)
- Single pass
- store the index of largest and second largest
- init largest to first element
- for every element from 1 to last element
- if item is bugger than largest lement
- set seond largest as largest
- set the largest as current
- else if item is equals to largest
- ignore
- else - if less than largest
- if second largest is -1
- assign this is seond largest
- item is equals to second largest then ignore
- item is bigger than second largest
- upddate the seond largest index
- TC: O(n) SC: O(1)
- using min heap of size k (if items are repeated it wont get ignored)
- get subset of array of size k
- heapy the array(min heap)
- loop from k to n
- if current item is bigger than the first object in heap
- pop and push that item in to the heap
- return the first element
- TC: O(k + nlogk), SC: O(k)
- find kth largest element in an array using iteration
- TC: O(kn)
- SC: O(1)
- 2 sum
- 2 loops brute force
- TC: O(n ^ 2)
- SC: O(1)
- hash table two pass
- TC: O(n)
- SC: O(n)
- hash table one pass
- TC: O(n)
- SC: O(n)
- sorted array - two pointer approach
- TC: O(nlogn) O(n) if array is already sorted
- SC: O(1)
- if we are returning index we need to store original index before sorting
- TC: O(nlogn)
- SC: O(n)
``` python
TC: O(n)
SC: O(1)
def two_sum(nums, targer):
l = 0
r = len(nums) - 1
while l < r:
curr_sum = nums[l] + nums[r]
if curr_sum == target:
return True
if curr_sum < target:
l += 1
else:
r -= 1
return False
```
- intersection
- use frequency array of first array and match with second one
- TC: O(m + m)
- SC: O(max(n, m)) -> result + frequency array
- Can optimize SC: to O(min(m,n)) with simple trick
- sort both the arrays and use two pointer approach
- TC((n + m) log (m + n))
- SC(min(m,n)) -> result
- stock buy sell
- One traversal
- Keep track of global min and max price
- while updating the min dont update the max price since buy and sell should happen on different date
- check if array is sorted
- global_ispositive = None
- loop from 1 to n
- is_positive = current_item - prev
- if global_ispositive is None
- global_ispositive = is_positive
- else:
if global_ispositive != is_positive:
return Fale
- return true
- reverse an array
- contains duplicate in unsorted array
- Naive Solution
- TC: O(n ^2)
- SC: O(1)
- Sort and Search
- TC: O(nlogn)
- SC: O(1)
- hash table to store visited elements
- TC: O(n)
- SC: O(n)
- if n range within constant
- TC: O(n)
- SC: O(1) -> like accii charecters
- remove duplicates from sorted array
- dont create new array of different size
- iterate each element store global prev selement if its repeated then update to None else update the global
- just rearrange the elements and return the new size
- move zeros to end
``` python
count = None
while i in range(len(arr)):
if arr[i] != 0:
arr[i], arr[count] = arr[count], arr[i]
count += 1
```
- left rotate an array by 1 postion
- init temp = arr[0]
- for i in range(n)
- arr[i - 1] = arr[i]
- arr[n - 1] = temp
- TC: O(n) SC: O(1)
``` python
def rotate_array(arr):
temp = arr[0]
for i, x in enumerate(arr):
if i == 0:
continue
arr[i - 1] = x
arr[len(arr) - 1] = temp
```
- left rotate an array by k postions
- solution 1
- left rotate d time
- TC: O(nd) SC: O(1)
- solution 2
- init temp = arr[d:]
- for i in range(d, n)
- arr[i - d] = arr[i]
- arr[n - 1] = temp
- TC: O(n) SC: O(d)
- reversal
- reverse(0, d-1)
- reverse(d, n - 1)
- reverse(0, n - 1)
- TC: O(n) SC: O(1)
- leaders in an array
- iterate from right and keep track of the max
- if there are next max then add to leaders
- maximum difference problem with order
- keep track of local min value and global difference
- iterate and update globsl min and max gloval difference
- frequencies in an sorted array
- keep track of last item and last freque
- if items chnage print and init for next
- sock buy or sell
- trapping rain water
- maximum consecutive 1s
- max subarray sum
- solution1
- generate prefix sum
- iterate and update gloval_max diff and global min
- solution2 - kadanes algorithm
- for every item in index
- either take prev_max + arr[i] or [i]
- update gloval max
- max subarray with target sum
- using hash table of prefix sum
- TC: O(n)
- SC: O(n)
- longest even odd subarray
- simiar to maximum consecutive 1s
- max circular sum subraary
- majority element
- min consecutive flips
- sliding window technique
- find the max sum of k consiquitive elements
- given an unsorted array of non-negative integer. if ther eis sum of subarray with given sum
- two pointer right and left
- first keep incrasing the right until sum is greater than target
- keep removing items from left until either its same or smaller
- count distinct elemtns in every window of size k
- n bonacci numbers
- prefix sum technique
- get range sum query
- find if there is an equilibirium point or pivot point
- Can be solved without prefix sum
- calculate total_sum
- iterate through each element
- calculate left_sum
- if left_sum == right_sum
- return index
- update right_sum from the total_sum
- Can be solved with prefix sum
- check if prefix sum of i -1 = suffix_sum of i + 1
- right sum = total sum - left sum
- maximum apperaing element in their range
- check if a given array can be divided into three parts of equal sum
- check if there a subarray with zero sum
- find the longest subarray with equal 0 and 1