Initial commit

This commit is contained in:
Michael Reber
2019-11-15 12:59:38 +01:00
parent 40a414d210
commit b880c3ccde
6814 changed files with 379441 additions and 0 deletions

View File

@@ -0,0 +1,67 @@
# Block swap algorithm for array rotation(Iterative)
#Initialize A=[0..d-1], B=[d..size-1]
#until size of A is equal to size of B
# a) If A is shorter
# 1. Divide B into Bl and Br such that Br is of same length as A.
# 2. Swap A and Br to change ABlBr into BrBlA.
# 3. Now A is at its final place, so recur on pieces of B.
# b) If A is longer
# 1. Divide A into Al and Ar such that Al is of same length as B.
# 2. Swap Al and B to change AlArB into BArAl.
# 3. Now B is at its final place, so recur on pieces of A.
#Finally when A and B are of equal size, block swap them.
# Iterative approach
def block_swap(a,d)
n=a.length
if n>0
if d>=n
d%=n
end
if d==0
return a
end
if d==n-d
swap(a,0,d,d)
end
i= d
j= n-d
while(i!=j)
if i<j
swap(a,d-i,d+j-i,i)
j-=i
else
swap(a,d-i,d,j)
i-=j
end
end
swap(a,d-i,d,i)
end
return a
end
def swap(a,start1,start2,d)
if (start1 != start2)
for i in 0...d
temp = a[start1+i]
a[start1+i] = a[start2+i]
a[start2+i] = temp
end
end
end
block_swap([1,2,3,4,5,6,7,8,9],5)

View File

@@ -0,0 +1,68 @@
# Block swap algorithm for array rotation(Recursive)
#Initialize A=[0..d-1], B=[d..size-1]
#until size of A is equal to size of B
# a) If A is shorter
# 1. Divide B into Bl and Br such that Br is of same length as A.
# 2. Swap A and Br to change ABlBr into BrBlA.
# 3. Now A is at its final place, so recur on pieces of B.
# b) If A is longer
# 1. Divide A into Al and Ar such that Al is of same length as B.
# 2. Swap Al and B to change AlArB into BArAl.
# 3. Now B is at its final place, so recur on pieces of A.
#Finally when A and B are of equal size, block swap them.
# Recursive Approach
#Driver function
def rotate_array(a, d) #Input array "a" and rotation by "d" elemets
finish =a.length-1
block_swap(a,0,finish,d)
end
def block_swap(a,start,finish,d)
n=finish-start+1
if n>0
if d>n
d%=n
end
if d==0
return a
end
if d==n-d
swap(a,start,start+d,d)
return a
elsif d<n-d
swap(a,start,finish-d+1,d)
block_swap(a,start,finish-d,d)
else
swap(a,start,d,n-d)
block_swap(a,n-d,n-1,(2*d)-n)
end
end
return a
end
#Utility function for swapping
def swap(a,start1,start2,d)
for i in 0...d
temp = a[start1+i]
a[start1+i] = a[start2+i]
a[start2+i] = temp
end
end
rotate_array([1,2,3,4,5,6,7,8,9,10],6)

View File

@@ -0,0 +1,46 @@
#Given an unsorted array of numbers ,return 1 if all the numbers are consecutive else return -1.
#Approach 1: Using an auxiliary array to keep track of visited elements
#Time-complexity:O(n),Auxiliary-space:O(n)
def check_consecutive(a)
len=a.length
min=a.min
max=a.max
if len==(max-min+1)
visited=Array.new(len,0)
for i in 0...len
return -1 unless visited[a[i]-min]==0
visited[a[i]-min]=1
end
return 1
end
return -1
end
check_consecutive([1,3,3,2]) # => -1
check_consecutive([1,4,3,2]) # => 1
#Approach 2: Instead of using visited(auxiliary) array, we traverse for each index i and make a[i]-min -ve,
#if a[i]-min is already -ve ,there is a repetition.
#Time-complexity:O(n),Auxiliary-space:O(1)
#Caveat: This algorithm modifies the content of the array and also this method might not work for negative numbers.
def check_consecutive(a)
len=a.length
min=a.min
max=a.max
if len==(max-min+1)
for i in 0...len
j=(a[i]).abs-min
if a[j]>0
a[j]=-a[j]
else
return -1
end
end
return 1
end
return -1
end
check_consecutive([1,3,3,2]) # => -1
check_consecutive([1,4,3,2,5]) # => 1

View File

@@ -0,0 +1,50 @@
#Given an unsorted array,Find a pair of elemens with given difference,if no such pair exists return -1.
#Approach 1: Sort the array then search using two pointers left and right
#Time-complexity: O(nlogn),Auxiliary-space:O(1)
def check_pair(a,x)
len=a.length
a.sort!
left=0
right=len-1
while left<right
diff=a[right]-a[left]
if diff==x.abs #Considering absolute difference as pair a,b and b,a have same absolute difference
return a[left],a[right]
elsif diff>x.abs
right-=1
else
left+=1
end
end
return -1
end
check_pair([5, 20, 3, 2, 50, 80],-78) # => [2, 80]
check_pair([5, 20, 3, 2, 50, 80],78) # => [2, 80]
check_pair([90, 70, 20, 80, 50],45) # => -1
#Approach 2: Using hash maps
#Time-complexity: O(n), Auxiliary-space: O(n){for hash}
def check_pair(a,x)
len=a.length
map=Hash.new()
for i in 0...len
t=x.abs+a[i] #if a-b=x then a=x+b
s=a[i]-x.abs #if a-b=x then b=x-a
if map[t]
return t,a[i]
elsif map[s]
return s,a[i]
end
map[a[i]]=1
end
return -1
end
check_pair([5, 20, 3, 2, 50, 80],-78) # => [2, 80]
check_pair([5, 20, 3, 2, 50, 80],78) # => [2, 80]
check_pair([90, 70, 20, 80, 50],45) # => -1

View File

@@ -0,0 +1,48 @@
#Given an array A[] and a number x, check for pair in A[] with sum as x
#Approach 1: Using Hash Map
#Time-complexity: O(n), Space-complexity: O(n) {extra space required for hashmap}
def check_pair(arr,x)
len=arr.length
flag=false
map=Hash.new()
for i in 0...len
t=x-arr[i]
if map[t]
flag=true
break
end
map[arr[i]]=1
end
if flag
return "Array has two elements with sum:#{x}"
else
return "Array doesn't have two elements with sum:#{x}"
end
end
check_pair([5,4,10,-2,3,2,-1,9],9)
##Approach 2: Sorting and then searching using left and right indexes.
#Time-complexity: O(nlogn) //O(nlogn)+O(n), Space-complexity: O(1)
def check_pair(arr,x)
len=arr.length
arr.sort! # You can choose your own sorting algorithm
left=0
right=len-1
while left<right
if (arr[left]+arr[right]==x)
return "Array has two elements with sum:#{x}"
elsif (arr[left]+arr[right]>x)
right-=1
else
left+=1
end
end
return "Array doesn't have two elements with sum:#{x}"
end
check_pair([5,4,10,-2,3,2,-1,9],9)

27
ruby/Arrays/ClosestSum.rb Normal file
View File

@@ -0,0 +1,27 @@
#Given array of integers(both +ve and -ve) find the two elements such that their sum is closest to given number x.
#Time-complexity: O(nlogn) // O(nlogn){for sorting}+O(n), Auxiliary-space:O(1)
#Algorithm: Sort the array and using two indexes left and right update the closest sum
def closest_sum(a,x)
a.sort! #You can choose any sorting algorithm of your choice with
left=min_l=0
right=min_r=a.length-1
min_sum = 1.0/0.0 #Initializing min_sum with infinity
while(left<right)
sum=(a[left]+a[right])-x
if sum.abs<min_sum
min_sum=sum.abs
min_l=left
min_r=right
end
if sum<0
left+=1
else
right-=1
end
end
print " The two elements whose sum is minimum are #{a[min_l]} and #{a[min_r]}"
end
closest_sum([1,3,2,4,5],9) # => The two elements whose sum is minimum are 4 and 5

View File

@@ -0,0 +1,26 @@
#Given an array 'a',create a product array where product[i]==product of all elements except a[i]
#Time-complexity: O(n), Space-complexity: O(n),Auxiliary-space: O(1)
def product_array(a)
len=a.length
product=Array.new(len,1) # Initilaize product array elements to 1
temp=1
#Loop to store product of left elements
for i in 0...len
product[i]=temp
temp*=a[i]
end
temp=1 #reset temp variable to 1
#Loop to multiply stored left products with right products
for i in (len-1).downto(0)
product[i]*=temp
temp*=a[i]
end
return product
end
product_array([1,2,3,4,5,6]) # => [720, 360, 240, 180, 144, 120]

View File

@@ -0,0 +1,18 @@
#Given an array of length n contains elements from 0 to n-1,
#Print all the duplicate elements in O(n) time and constant space.
def print_duplicates(a)
n=a.length
print "Duplicate elements are: "
for i in 0...n
if a[a[i].abs]<0
print "#{a[i].abs} "
else
a[a[i].abs]= -a[a[i].abs]
end
end
return
end
print_duplicates([1, 4, 6, 4, 3, 6, 1]) # => Duplicate elements are: 4 6 1

View File

@@ -0,0 +1,28 @@
=begin
Equilibrium index of an array is an index such that the sum of elements at lower indexes is equal to the sum of elements at higher indexes.
For example, in an arrya A:
A[]=[-7,1,5,2,-4,3,0]
3 is an equilibrium index, because:
A[0] + A[1] + A[2] = A[4] + A[5] + A[6]
Time-complexity: O(n)
Auxiliary-space: O(1)
=end
def find_equilibrium(a)
len = a.length
leftsum=0
rightsum=0
for x in a
rightsum+=x
end
for i in 0...len
rightsum-=a[i]
if (leftsum == rightsum)
return i
end
leftsum+=a[i]
end
return -1
end

View File

@@ -0,0 +1,51 @@
# Problem:
=begin
Given an array of size N ,taht has elements in range 1 to N ,all elements in the arrayb are unique,
Find the missing number.
e.g.
array = [1,5,2,4,6]
answer = 3
=end
#Approach 1 - Find the sum of all elements of array and substract it from sum of the range , the difference will be missing number.
# Time-complexity = O(n)
#Caveats: If the numbers are very large the sum can lead to integer overflow.
def find_missing_number(a)
n = a.length+1
range_sum = (n * (n+1))/2 # Sum of numbers from 1 to n is (n* n+1 )/2
arr_sum = 0
for x in a
arr_sum+=x
end
return missing_element = range_sum - arr_sum
end
#Approach 2 (No integer overflow)- Take bitwise XOR of all elements of the array with the numbers in given range,
#As( a XOR a == 0 ) all numbers present in array will xor out and become zero except the missing number.
# Time-complexity = O(n)
def find_missing_number(a)
n = a.length+1
missing_element = 0
(1..n).each {|num| missing_element^= num}
for x in a
missing_element^=x
end
return missing_element
end
#Ruby magic
#One line code but it uses O(n) auxiliary-space, it returns an array containing only the missing_element
# Array1-Array2 in ruby returns an array containing all the elements that are in Array1 but not in Array2
def find_missing_number(a)
n = a.length+1
range = Array (1..n)
missing_element = range-a
end

View File

@@ -0,0 +1,31 @@
# Given an array and a value, find if there is a pythagorean triplet in array.
#Pythagorean triplets:3 no.'s for which sum of squares of any two==square of third number.
#Time-complexity: O(n^2),Auxiliary-space:O(1)
#Algorithm:Square each element,Sort,fix element then search in the array using two pointers left and right
def pythagorean_triplet(a)
len=a.length
a.map! {|x| x**2 } #Replacing every array element with its square(if you don't want to modify the array then extra space is required to store the squares)
a.sort!
for i in (len-1).downto(2)
x=a[i]
left=0
right=i-1
while left<right
if (a[left]+a[right])==x
return "Triplet found #{Math.sqrt(a[left])},#{Math.sqrt(a[right])},#{Math.sqrt(a[i])}"
elsif (a[left]+a[right])<x
left+=1
else
right-=1
end
end
end
return -1
end
pythagorean_triplet([1,2,3,3,34,4,4]) # => -1
pythagorean_triplet([1,2,3,3,34,13,12,5]) # => Triplet found 5,12,13

View File

@@ -0,0 +1,124 @@
# Given an array of n+2 elements with elements value lying beween 1 to n.
# All elements occur once except two.Print the two repeating numbers.
#Approach 1: Using sum and product of array (Making two equation)
#Time-complexity: O(n) Auxiliary-space: O(1)
#Caveat: If array is large this can lead to integer overflow.
def find_duplicates(a)
len=a.length
n=len-2
sum_of_series= (n*(n+1))/2 #Sum of series 1 to n
#Find sum and product of array elements
sum=0
product=1
for x in a
sum+=x
product*=x
end
sum-=sum_of_series #sum is a+b now,where a and b are repeating numbers
product/=fact(n) #product is a*b now,where a and b are repeating numbers
temp= Math.sqrt((sum**2)-(4*product)).to_i # temp is a-b
print "#{(sum+d)/2} #{(sum-d)/2}"
end
def fact(x)
return 1 if (x==0 || x==1)
factorial=1
while x>1
factorial*=x
x-=1
end
return factorial
end
find_duplicates([1,2,3,4,5,5,6,7,8,8]) # => 5 8
#Approach 2: Use count array
#Time-complexity: O(n) Auxiliary-space: O(n) {for count array}
def find_duplicates(a)
len=a.length
n=len-2
count=Array.new(n,0) # count has length n
for i in 0...len
if count[a[i]-1]==1
print "#{a[i]} "
else
count[a[i]-1]+=1
end
end
return
end
find_duplicates([1,2,3,4,5,5,6,7,8,8]) # => 5 8
#Approach 3: Using Array Indexing
#Time-complexity: O(n) Auxiliary-space: O(1)
#Caveat: This algorithm modifies the array-elements
def find_duplicates(a)
len=a.length
for i in 0...len
if a[a[i].abs]<0
print "#{a[i].abs} "
else
a[a[i].abs]= -a[a[i].abs]
end
end
return
end
find_duplicates([1,2,3,4,5,5,6,7,8,8]) # => 5 8
#Approach 4: Using bitwise XOR,take xor of all elements and all numbers from 1 to n then,
#find rightmost set bit,divide the range in two sets and take xor of each set, first with xor then with range.
#Time-complexity: O(n) Auxiliary-space: O(1)
def find_duplicates(a)
len=a.length
n=len-2
xor= 0
x,y=0,0 #variables to store duplicates
#xor of all numbers from 1 to n
for i in 1..n
xor^=i
end
#xor of all array elements
for i in 0...len
xor^=a[i]
end
#Rightmost set bit
set_bit_pos= xor & ~(xor-1)
#Divinding array in two sets ,one with set bit at set_bit_pos and other with 0.
for i in 0...len
if (a[i] & set_bit_pos == 0)
x^=a[i] # XOR of first-set(with 0 at set_bit_pos) in array
else
y^=a[i] # XOR of second-set(with 1 at set_bit_pos) in array
end
end
for i in 0..n
if (i & set_bit_pos == 0)
x^=i # XOR of first-set(with 0 at set_bit_pos) in range
else
y^=i # XOR of second-set(with 1 at set_bit_pos) in range
end
end
print "#{x} #{y}"
return
end
find_duplicates([1,2,3,4,5,5,6,7,8,8]) # => 5 8

View File

@@ -0,0 +1,20 @@
#Fitcher-Yates shuffling algorithm
#(start from last element,swap with random element from the array,decrement array size by one and repeat until array size is 1)
#Time-complexity: O(n)
def shuffle(arr)
n=arr.length
for i in (n-1).downto(1)
j=Random.rand(i+1)
swap(arr,i,j)
end
print arr
end
def swap(arr,i,j)
temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
end
shuffle([1,2,3,4,5,6])

View File

@@ -0,0 +1,28 @@
=begin
Given an array of n distinct integers sorted in ascending order, find a fixed point in the array.
Fixed Point in an array is an index i such that arr[i] is equal to i, i.e. a[i]==i
Time-complexity: O(logn)
Space-complexity: O(1)
Algorithm: Binary Search
=end
def fixed_point(a)
n=a.length
hi=n-1
lo=0
while(hi>=lo)
mid=lo+(hi-lo)/2
if a[mid]==mid
return mid
elsif a[mid]<mid
lo=mid+1
else
hi=mid-1
end
end
#if no fixed point exists
return -1
end

View File

@@ -0,0 +1,17 @@
=begin
Given an array, find a fixed point in the array.
Fixed Point in an array is an index i such that arr[i] is equal to i, i.e. a[i]==i
Time-complexity: O(n)
Space-complexity: O(1)
Algorithm: Linear Search
=end
def fixed_point(a)
n=a.length
for i in 0...n
if a[i]==i
return i
end
end
#if no fixed point exists
return -1
end

View File

@@ -0,0 +1,54 @@
# Given a sorted array and a value x, Find Ceil(ceiling of x is the smallest element in array greater than or equal to x)
# and Floor(the greatest element smaller than or equal to x) of x.
#Algorithm: Binary-search
#Time-complexity: O(logn),Auxiliary-space:O(1)
def find_floor_ceil(a,key)
len=a.length
floor=find_floor(a,0,len,key)
ceil=find_ceil(a,-1,len-1,key)
if floor==-1
puts "floor doesn't exist"
if ceil==-1
puts "Ceil doesn't exist"
return -1
else
return "Ceil is #{a[ceil]}"
end
else
if ceil==-1
puts "Ceil doesn't exist"
return "Floor is #{a[floor]}"
else
return "Floor is #{a[floor]} and Ceil is #{a[ceil]}"
end
end
end
#Method to find floor
def find_floor(a,lo,hi,key)
return -1 if key<a[lo]
while hi-lo>1
mid=lo+(hi-lo)/2
if a[mid]<=key
lo=mid
else
hi=mid
end
end
return lo
end
#Method to find Ceil
def find_ceil(a,lo,hi,key)
return -1 if key>a[hi]
while hi-lo>1
mid=lo+(hi-lo)/2
if a[mid]>=key
hi=mid
else
lo=mid
end
end
return hi
end
find_floor_ceil([1, 2, 8, 10, 10, 12, 19],19) # => Floor is 19 and Ceil is 19

View File

@@ -0,0 +1,47 @@
#Given a sorted array arr[] and a number x, write a function that counts the occurrences of x in arr[]
#Algorithm: Binary Search
#Time-complexity:O(logn),Auxiliary space:O(1)
def count_occurences(a,key)
len=a.length
#observe boundary conditions
i=first(a,-1,len-1,key)
return i if i==-1 # return -1 if key not present in array
j=last(a,0,len,key)
return j-i+1,j,i
end
def first(a,lo,hi,key)
#loop to find first occurence
while hi-lo>1
mid=lo+(hi-lo)/2
if a[mid]>=key
hi=mid
else
lo=mid
end
end
if a[hi]==key
return hi
else
return -1
end
end
def last(a,lo,hi,key)
#loop to find last occurence
while hi-lo>1
mid=lo+(hi-lo)/2
if a[mid]<=key
lo=mid
else
hi=mid
end
end
return lo
end
count_occurences([1, 1, 2, 2, 2, 2, 3,3],1)

View File

@@ -0,0 +1,40 @@
#Juggling Algorithm for array rotation!
#Time complexity: O(n) , Auxiliary-Space: O(1)
def left_rotate_array(a, d) #Input array "a" and rotation by "d" elemets
n=a.length
if n>0
if d>n # if d>n ,we take modulo n
d%=n
end
for i in 0...gcd(d,n)
temp=a[i]
j=i
while(true)
k=j+d
if k>=n
k=k-n
end
if k==i
break
end
a[j]=a[k]
j=k
end
a[j]=temp
end
end
return a
end
def gcd(x,y)
if y==0
return x
else
return gcd(y,x%y)
end
end

View File

@@ -0,0 +1,22 @@
#Knuth Shuffling Algorithm(Choose random number between i and n-i and swap)
#Time-complexity: O(n)
def shuffle(arr)
len = arr.length
for i in 0...len
r = Random.rand(len-i)+i
swap(arr,i,r)
end
return arr
end
def swap(arr,i,j)
temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
end
shuffle([1,2,3,4,5,6])

View File

@@ -0,0 +1,22 @@
=begin
Algorithm to print all the LEADERS in the array.
An element is leader if it is greater than all the elements to its right side,the rightmost element is always a leader.
Time-complexity: O(n)
Auxiliary-space: O(1)
=end
def find_leaders(a)
n = a.length
max_from_right = a[n-1]
print "#{max_from_right}"+" "
for i in (n-2).downto(0)
if a[i]>max_from_right
max_from_right=a[i]
print "#{max_from_right}"+" "
end
end
end
find_leaders([16, 17, 4, 3, 5, 2]) # => 2 5 17

View File

@@ -0,0 +1,36 @@
# Find majority element(if exists) in a given array.
# A majority element in an array A[] of size n is an element that appears more than n/2 times
#Time-complexity: O(n), Auxiliary-space:O(1)
#Moore's Voting algorithm
def majority_element(a)
len=a.length
maj_index=0
count=1
for i in 1...len
if a[i]==a[maj_index]
count+=1
else
count-=1
end
if count==0
a[maj_index]=a[i]
count=1
end
end
candidate=a[maj_index]
count=0
for i in 0...len
if a[i]==candidate
count+=1
end
end
if count > (len/2)
return candidate
else
return -1
end
end
majority_element([2, 2, 3, 5, 2, 3])

View File

@@ -0,0 +1,32 @@
# Find majority element(if exists) in a given sorted array.
# A majority element in an array A[] of size n is an element that appears more than n/2 times
#Time-complexity: O(logn), Auxiliary-space:O(1)
#Algorithm: Binary-search
def majority_element(a)
len=a.length
lo=0
hi=len-1
candidate=a[lo+(hi-lo)/2]
while hi-lo>1
mid=lo+(hi-lo)/2
if a[mid]>=candidate
hi=mid
else
lo=mid
end
end
if a[hi]==candidate
left_index=hi
right_index=left_index+(len/2)
if a[right_index]==candidate
return candidate
else
return -1
end
end
end
majority_element([1,2, 2, 3, 3, 3, 3]) # => 3

View File

@@ -0,0 +1,44 @@
#Given an array find maximum difference between two elements such that the karger appears after the smaller.
#Approach 1: keep track of min so far and find the diff.
#Time-complexity:O(n),Auxiliary-space:O(1)
def max_diff(a)
len=a.length
min_so_far=a[0]
diff=a[1]-a[0]
for i in 1...len
diff= a[i]-min_so_far if (a[i]-min_so_far > diff)
min_so_far=a[i] if (a[i] < min_so_far)
end
return diff
end
max_diff([100, 10, 5, 91, 1, 8, 16, 21]) # => 86
#Approach 2: find diff between adjacent elements,now find the max sum subarray of diff.
#Time-complexity:O(n),Auxiliary-space:O(1)
def max_diff(a)
len=a.length
diff=a[1]-a[0]
curr_sum=diff
max_sum=curr_sum
for i in 1...len-1
#calculate current diff
diff=a[i+1]-a[i]
#calculate current sum
if curr_sum>0
curr_sum+=diff
else
curr_sum=diff
end
#update max_sum
max_sum=curr_sum if curr_sum>max_sum
end
return max_sum
end
min_diff([100, 10, 5, 91, 1, 8, 16, 21]) # => 86

28
ruby/Arrays/MaxJminusI.rb Normal file
View File

@@ -0,0 +1,28 @@
#Given an array arr[], find the maximum j i such that arr[j] > arr[i].
# Time-complecity: O(n), Space-complexity:O(n)
def max_index_diff(a)
len=a.length
max_diff=-1
lmin=Array.new(len)
rmax=Array.new(len)
lmin[0]=a[0]
for i in 1...len
lmin[i]=[a[i],lmin[i-1]].min
end
rmax[len-1]=a[len-1]
for i in (len-2).downto(0)
rmax[i]=[a[i],rmax[i+1]].max
end
i=j=0
while (j<len && i<len)
if lmin[i]<rmax[j]
max_diff=[max_diff,j-i].max
j+=1
else
i+=1
end
end
return max_diff
end
max_index_diff([34, 8, 10, 3, 2, 80, 30, 33, 1]) # => 6

View File

@@ -0,0 +1,35 @@
#Given an array of integers(both positive and negative),find the subarray with maximum product.
# Time Complexity: O(n),Auxiliary Space: O(1)
#Note: It doesnt work for arrays like {0, 0, -20, 0}, {0, 0, 0}.. etc
def max_product(a)
len=a.length
max_ending_here=min_ending_here=max_so_far=1
for i in 0...len
# If this element is +ve, update max_ending_here.
# Update minEndingHere only if minEndingHere is negative
if a[i]>0
max_ending_here=max_ending_here*a[i]
min_ending_here = [min_ending_here*a[i],1].min
# If this element is 0, then the maximum product
# cannot end here, make both maxEndingHere and minEndingHere 0
# Assumption: Output is alway greater than or equal to 1.
elsif a[i]==0
max_ending_here=min_ending_here=1
# If this element is -ve,min_ending here is previous max_ending_here*current
#max_ending_here is min of previous min_ending_here*current and 1
else
temp=max_ending_here
max_ending_here=[min_ending_here*a[i],1].max
min_ending_here=temp*a[i]
end
max_so_far=max_ending_here if max_so_far<max_ending_here
end
return max_so_far
end
max_product([-2, -3, 0, -2, -40]) # => 80

View File

@@ -0,0 +1,30 @@
# Algorithm to find the largest possible continuos sum in an array.
#Time-complexity: O(n), Auxiliary space: O(1)
# Algorithm-paradigm: Dynamic-programming
# This algorithm doesn't work for negative numbers,it simply returns zero if all numbers are negative.
def max_continuos_sum(a)
max_ending_sum = max_slice_sum =0
n=a.length
for i in 0...n
max_ending_sum = [0,(max_ending_sum+a[i])].max
max_slice_sum = [max_slice_sum,max_ending_sum].max
end
return max_slice_sum
end
max_continuos_sum([1,1,-1,2,3,4,-9,3,4,5,-6]) # => 13
# Algorithm to handle negative numbers as well
def max_continuos_sum(a)
max_ending_sum = max_slice_sum =a[0]
n=a.length
for i in 0...n
max_ending_sum = [a[i],(max_ending_sum+a[i])].max
max_slice_sum = [max_slice_sum,max_ending_sum].max
end
return max_slice_sum
end
max_continuos_sum([-5,-4,-10,-2,-3,-2,-1,-9]) #=> -1

View File

@@ -0,0 +1,17 @@
#Given an array of positive numbers,find the maximum possible sum such that no two chosen numbers are adjacent
#Time-complexity: O(n),Auxiliary-space:O(1)
def max_sum(a)
len=a.length
incl=a[0]
excl=0
for i in 1...len
temp=[excl,incl].max
incl=excl+a[i]
excl=temp
end
return [incl,excl].max
end
max_sum([1,2,3,-1,4,5,0]) # => 9

View File

@@ -0,0 +1,55 @@
#Given an Bitonic Array(array of integers which is initially increasing and then decreasing),
#find the maximum value in the array
#Time-complexity: O(logn),Auxiliary-space:O(1)
#Algorithm: Binary-search
=begin
#caveat:This method works only for distinct numbers,
coz in case of too many duplicates cause it not possible to decide by constant comparisons at mid, which subarray to choose
#it will not work for an array like {0, 1, 1, 2, 2, 2, 2, 2, 3, 4, 4, 5, 3, 3, 2, 2, 1, 1} .
=end
# Recursive
def maximum(a,lo,hi)
if lo==hi
return a[lo]
end
if hi==lo+1
if arr[lo]<arr[hi]
return a[hi]
else
return a[lo]
end
end
mid=lo+(hi-lo)/2
return a[mid] if (a[mid]>a[mid+1] && a[mid]>a[mid-1])
if (a[mid]>a[mid+1] && a[mid]<a[mid-1])
return maximum(a,lo,mid-1)
else
return maximum(a,mid+1,hi)
end
end
maximum([1,2,3,4,2,1],0,3) #=> 4
#Iterative
def maximum(a)
lo=0
hi=a.length-1
while hi-lo>1
mid=lo+(hi-lo)/2
if a[mid]>a[mid-1]
lo=mid
else
hi=mid
end
end
return [a[lo],a[hi]].max
end
maximum([1,2,3,4,2,1]) #=> 4

View File

@@ -0,0 +1,55 @@
#Given an array and number K,Print the maximum value in each sub-arrays of size K
#Time-complexity:O(nk),Auxiliary-space:O(1)
def find_max(a,k)
len=a.length
return -1 if len<k
for i in 0..len-k
max=a[i]
for j in i+1...i+k
if a[j]>max
max=a[j]
end
end
print "#{max} "
end
return
end
find_max([9,1,8,2,7,3,6,4,5,15,17],4)
#Optimized(Though the complexity is same asymptotically but the average running time is very much optimized)
#Check if max of last k-length subarray lies in the new window if yes then just compare the max and newly added element
def find_max(a,k)
len=a.length
return -1 if len<k
max=a[0]
max_index=0
for i in 0..len-k
unless max_index<i
if a[i+k-1]>max
max=a[i+k-1]
max_index=i+k-1
end
else
max=a[i]
max_index=i
for j in i...i+k
if a[j]>max
max=a[j]
max_index=j
end
end
end
print "#{max} "
end
return
end
find_max([1,2,3,1,4,5,2,3,6],3)
find_max([9,1,8,2,7,3,6,4,5,15,17],4)

View File

@@ -0,0 +1,43 @@
# There are 2 sorted arrays A and B of size n each.
# find the median of the array obtained after merging the above 2 arrays(i.e. array of length 2n).
#Algorithm :Binary-search
#Time-complexity:O(logn),Auxiliary-space: O(1)
def get_median(a,a1,lo1,hi1,lo2,hi2)
#Length of the arrays
len=hi1-lo1+1
return -1 if len<=0 # return -1 if array is empty or invalid
return (a[lo1]+a1[lo2])/2 if len==1 # return median if each array is of size 1
return ([a[lo1], a1[lo2]].max + [a[hi1], a1[hi2]].min)/2 if len==2 # return median if each array is of size 2
#Median and index of median of array 1
m1,m1_i=median(a,len,lo1)
#Median and index of median of array 2
m2,m2_i=median(a1,len,lo2)
#Compare medians if equal return either m1 or m2,
#else if m1<m2 median lies in m1,hi1 and lo1,m2
#else m1>m2 median lies in m1,hi1 and lo1,m2
if m1==m2
return m1
elsif m1<m2
return get_median(a,a1,m1_i,hi1,lo2,m2_i)
else
return get_median(a,a1,lo1,m1_i,m2_i,hi2)
end
end
# Utility function to find median of array
def median(arr,n,lo)
if n%2==0
return (arr[lo+(n/2)]+arr[lo+((n/2)-1)])/2,lo+(n/2)
else
return arr[lo+(n/2)],lo+(n/2)
end
end
get_median([1,2,3,5,5],[1,2,5,9,11],0,4,0,4) # => 4

View File

@@ -0,0 +1,27 @@
# A sorted array is rotated at some unknown point, find the minimum element in it
# Time-complexity: O(logn),Auxiliary-space:O(1)
# Algorithm: Binary-Search
#This method cannot handle duplicates
def search_minimum(a)
lo=0
hi=a.length-1
while(lo<=hi)
mid= lo+(hi-lo)/2
if (mid>0 && a[mid-1]>a[mid])
return "Minimum element is #{a[mid]} at #{mid}"
elsif a[mid]>a[hi]
lo=mid+1
else
hi=mid-1
end
end
return "Minimum element is #{a[lo]} at #{lo}"
end
search_minimum([5, 6, 1, 2, 3, 4]) #=> Minimum element is 1 at 2
# It doesnt look possible to search minimum in O(Logn) time in all cases when duplicates are allowed.
# Consider {2, 2, 2, 2, 2, 2, 2, 2, 0, 2} and {2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}.

View File

@@ -0,0 +1,27 @@
#Given an array of random numbers, Push all the zeros of a given array to the end of the array
#Time Complexity: O(n),Auxiliary Space: O(1)
##Algorithm:
#Traverse the given array from left to right andmaintain count of non-zero elements in array.
# For every non-zero element arr[i], put the element at arr[count] and increment count.
# After complete traversal, all non-zero elements have already been shifted to front end and count is set as index of first 0.
# Now run a loop which makes all elements zero from count till end of the array zero.
def move_zeros(a)
len=a.length
count=0
for i in 0...len
if a[i]!=0
a[count]=a[i]
count+=1
end
end
# Loop from count to len-1 and fill it with zeros
while count<len
a[count]=0
count+=1
end
return a
end
move_zeros([1,2,0,3,0,4,0,5,0,0,6]) # => [1, 2, 3, 4, 5, 6, 0, 0, 0, 0, 0]

View File

@@ -0,0 +1,25 @@
#Given an array of integers,print the next greatest element for each of the element
#Time-complexity:O(n),Auxiliary-space:O(n){stack}
def find_nge(a)
stk=[]
top=-1
for i in 0...a.length
while(top>-1 && stk[top]<a[i])
puts "#{stk[top]} -> #{a[i]}"
stk.pop()
top-=1
end
stk.push(a[i])
top+=1
end
while top>-1
puts "#{stk[top]} -> #{-1}"
top-=1
end
end
find_nge([23,12,56,22,6,34])

View File

@@ -0,0 +1,35 @@
# Given an array where all elements appear even number of times except one.
# All repeating occurrences of elements appear in pairs and these pairs are not adjacent (there cannot be more than two consecutive occurrences of any element).
# Find the element that appears odd number of times.
# Note that input like {2, 2, 1, 2, 2, 1, 1} is valid as all repeating occurrences occur in pairs and these pairs are not adjacent.
# Input like {2, 1, 2} is invalid as repeating elements dont appear in pairs. Also, input like {1, 2, 2, 2, 2} is invalid as two pairs of 2 are adjacent.
# Input like {2, 2, 2, 1} is also invalid as there are three consecutive occurrences of 2.
#Time-complexity: O(logn),Auxiliary-space:O(1)
#Algorithm:Binary-search
def search_odd(a)
lo=0
hi=a.length-1
while hi-lo>1
mid=lo+(hi-lo)/2
if mid%2==0
if a[mid]==a[mid+1]
lo=mid+2
else
hi=mid
end
else
if a[mid]==a[mid-1]
lo=mid+1
else
hi=mid
end
end
end
return a[lo]
end
search_odd([3,1, 1, 2, 2, 3, 3, 4, 4,600, 600, 4, 4]) # => [3]

View File

@@ -0,0 +1,38 @@
#Given an array which may contain duplicates,print all distinct elements.
#e.g. [1,1,2,3,3,4,5,6,6,6,6] should print 1 2 3 4 5 6.
#Approach 1: Using Sorting
#Time-complexity: O(nlogn){of sorting},Auxiliary-space : O(1)
def print_distinct(a)
n=a.length
a.sort! #You can use any o(nlogn) sorting algorithm you wish
i=0
while i<n
while (i<n-1 && a[i] == a[i+1])
i+=1
end
print "#{a[i]} "
i+=1
end
return
end
print_distinct([4, 7, 4, 1, 1, 4, 8, 10, 6, 7]) # => 1 4 6 7 8 10
#Approach 2: Using Hashing
#Time-complexity: O(n),Auxiliary-space:O(n) {for hash}
def print_distinct(a)
n=a.length
hash=Hash.new()
for i in 0...n
unless hash[a[i]]
hash[a[i]]=1
print "#{a[i]} "
end
end
return
end
print_distinct([4, 7, 4, 1, 1, 4, 8, 10, 6, 7]) # => 4 7 1 8 10 6

View File

@@ -0,0 +1,39 @@
#Given a matrix(2D array),print all of its elements in spiral order.
#e.g. [[1,2,3].[4,,5,6],[7,8,9]] => 1 2 3 6 9 8 7 4 5
def spiralOrder(a)
n=a.length
m=a[0].length
t=0
b=m-1
r=n-1
l=0
dir=0
while t<=b && l<=r
if dir==0
for i in l..r
print "#{a[t][i]} "
end
t+=1
dir=1
elsif dir==1
for i in t..b
print "#{a[i][r]} "
end
r-=1
dir=2
elsif dir==2
for i in r.downto(l)
print "#{a[b][i]} "
end
b-=1
dir=3
else
for i in b.downto(t)
print "#{a[i][l]} "
end
l+=1
dir=0
end
end
end

View File

@@ -0,0 +1,27 @@
#Given an array replace every element by product of previous and next
#first element is replaced by product of first and second and last element by product of last and second last
#Time-complexity: O(n),Auxiliary-space: O(1)
def modify(a)
len=a.length
if len<=0
return -1
end
#update first element
prev=a[0]
a[0]*=a[1]
for i in 1...len-1
current=a[i] #Keep track of current element
a[i]=prev*a[i+1]
prev=current #Store current element for next iteration
end
#update last element
a[len-1]*=prev
return a
end
modify([3,6,1,7,8,2]) # => [18, 3, 42, 8, 14, 16]

View File

@@ -0,0 +1,22 @@
#Given an array replace every element with the next greatest element(largest number on right side) on the right side of the array,
#as there is no element on the right side of last element replace it with -1
#Time-complexity: O(n),Auxiliary-space:O(1)
def replace_with_nge(a)
len=a.length
max=a[len-1]
a[len-1]=-1
for i in (len-2).downto(0)
current=a[i]
a[i]=max
if current>max
max=current
end
end
return a
end
replace_with_nge([5,8,12,10,4,6]) # => [12, 12, 10, 6, 6, -1]

View File

@@ -0,0 +1,34 @@
#Reversal Algorithm for array rotation
#Time complexity : O(n), Auxiliary space: O(1)
def left_rotate_array(a,d) #Input array "a" and rotation by "d" elemets
n=a.length
if n>0
if d>n # if d>n ,we take modulo n
d%=n
end
reverse(a,0,d-1)
reverse(a,d,n-1)
reverse(a,0,n-1)
end
return a
end
def reverse(a,first,last) #Utility function for reversing array
i=first
j=last
while i<j
temp=a[i]
a[i]=a[j]
a[j]=temp
i+=1
j-=1
end
return a
end

View File

@@ -0,0 +1,41 @@
#Given an array reverse it without using extra-space
#Time-complexity: O(n), Auxiliary-space: O(1)
# Iterative
def reverse_array(a)
right=a.length-1
left=0
while(left<right)
#swap the elements
temp=a[left] #Swapping can be like done like this a[left],a[right]=a[right],a[left]
a[left]=a[right]
a[right]=temp
left+=1
right-=1
end
print a
end
reverse_array([1,2,3,4,5]) # => [5,4,3,2,1]
# Recursive
#driver program
def driver_program(a)
right=a.length-1
left=0
reverse_array(a,left,right)
print a
end
def reverse_array(a,left,right)
return if left>=right
#swap the elements
temp=a[left]
a[left]=a[right]
a[right]=temp
reverse_array(a,left+1,right-1)
end
driver_program([1,2,3,4,5]) # => [5,4,3,2,1]

View File

@@ -0,0 +1,32 @@
# A sorted array is rotated at some unknown point, Search given element in it
# Time-complexity: O(logn),Auxiliary-space:O(1)
# Algorithm: Binary-Search
def search(a,key)
lo=0
hi=a.length-1
while lo<=hi
mid=lo+(hi-lo)/2
if a[mid]==key
return mid
elsif a[mid]>=a[lo]
if (a[mid]>key && a[lo]<=key)
hi=mid-1
else
lo=mid+1
end
else
if (a[mid]<key && a[hi]>=key)
lo=mid+1
else
hi=mid-1
end
end
end
return -1
end
# It doesnt look possible to search in O(Logn) time in all cases when duplicates are allowed.
# Consider searching 0 in {2, 2, 2, 2, 2, 2, 2, 2, 0, 2} and {2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}.

View File

@@ -0,0 +1,33 @@
#Given an array A[] consisting 0s, 1s and 2s, put all 0s first, then all 1s and all 2s in last.
##Brute-force: Count 0s and 1s (using 2 varibales)and rewrite array first with counted zeros then by counted 1s and then by 2s
#Time-complexity:O(n),Auxiliary-space:O(1)
##Algorithm: Dutch National Flag Algorithm
#Time-complexity:O(n),Auxiliary-space:O(1)
def segregate(a)
right=a.length-1
left=0
current=0
while(current<=right)
if a[current]==0
swap(a,left,current)
left+=1
current+=1
elsif a[current]==2
swap(a,right,current)
right-=1
else
current+=1
end
end
print a
end
def swap(a,i,j)
a[i],a[j]=a[j],a[i]
end
segregate([0, 1, 1, 0, 1, 2, 1, 2, 0, 0, 0, 1])

View File

@@ -0,0 +1,30 @@
#Given an array of 0s and 1s in random order.Segregate 0s on left side and 1s on right side of the array.
##Brute-force: Count 0s and rewrite array first with counted zeros then by 1
#Time-complexity:O(n),Auxiliary-space:O(1)
##Algorithm: Dutch National Flag Algorithm
#Time-complexity:O(n),Auxiliary-space:O(1)
def segregate(a)
left=0
right=a.length-1
while left<right
#Increment left index while we see 0 at left
while a[left]== 0
left+=1
end
#Decrement right index while we see 1 at right
while a[right]==1
right-=1
end
#Exchange arr[left] and arr[right]
if left<right
a[left],a[right]=a[right],a[left]
left+=1
right-=1
end
end
return a
end
segregate([1,0,1,1,0,0]) # => [0, 0, 0, 1, 1, 1]

View File

@@ -0,0 +1,24 @@
#Given an array of elements,Find the smallest and second smallest element.
#time-complexity: O(n),Auxiliary-space:O(1)
def find_smallest2(a)
len=a.length
min= second= 1.0/0.0
for i in 0...len
if a[i]<min
second=min
min=a[i]
elsif a[i]<second
second=a[i]
end
end
return min,second
end
find_smallest2([1,2,3,-1,4,5,0]) # => [-1, 0]

View File

@@ -0,0 +1,54 @@
# Given a sorted array of n unique integers where each integer is in the range from 0 to m-1 and m > n.
# Find the smallest number that is missing from the array.
#Algorithm: Binary Search (Compare elements with indexes and then decide)
#Time-complexity: O(logn), Auxiliary-space: O(1)
# Iterative
def smallest_missing(a)
lo=0
hi=a.length-1
while hi>lo
mid=lo+(hi-lo)/2
if a[mid]>mid
hi=mid
else
lo=mid+1
end
end
if a[lo]==lo # if lo == end of array
print lo+1
else
print lo
end
end
smallest_missing([0, 1, 2, 3]) #=> 4
smallest_missing([0, 1, 2, 5]) #=> 3
#recursive
#Driver function
def driver_func(a)
lo=0
hi=a.length-1
print smallest_missing(a,lo,hi)
end
#Algorithm
def smallest_missing(a,lo,hi)
if lo>hi
return hi+1
end
if a[lo] != lo
return lo
end
mid= lo+(hi-lo)/2
if a[mid]>mid
return smallest_missing(a,lo,mid)
else
return smallest_missing(a,mid+1,hi)
end
end
driver_func([0, 1, 2, 3]) #=> 4
driver_func([0, 1, 2, 5]) #=> 3

View File

@@ -0,0 +1,34 @@
#Given an array ,sort the array by descending order of count of element,
#if count is same then the element which comes in array first comes first in sorted array.
#Time-complexity: O(nlogn) , Auxiliary-space: O(n) {for hash}
def sort_by_frequency(a)
len=a.length
freq=Hash.new() #Hash to store element,count and starting index
for i in 0...len
# Storing count and index in hash with element as the key
unless freq[a[i]]
freq[a[i]]={}
freq[a[i]][:count]=1
freq[a[i]][:index]=i
else
freq[a[i]][:count]+=1
end
end
freq=freq.sort_by{|k,v| [-v[:count],v[:index]]} # Sort the hash by decreasing count value and if count is same then by index(starting index)
p=0 # Index to iterate over array
# Iterate on hash
freq.each do |k,v|
for i in 0...v[:count]
a[p]=k
p+=1
end
end
return a
end
sort_by_frequency([1,3,3,3,4,4,4,2,2,2,5]) # => [3, 3, 3, 4, 4, 4, 2, 2, 2, 1, 5]
sort_by_frequency([1,3,3,3,4,4,4,2,2,2,5,5,6,7,7,7,8,8]) # => [3, 3, 3, 4, 4, 4, 2, 2, 2, 7, 7, 7, 5, 5, 8, 8, 1, 6]

View File

@@ -0,0 +1,37 @@
#Swapping two variables
#Method 1 (using temporary variable)
def swap(a,b)
temp = a
a = b
b = temp
return a,b
end
#Method 2 (Ruby magic)
def swap(a,b)
a,b=b,a
return a,b
end
#Method 3 (Using sum and difference, no temporary variable required)
#Caveat: Can lead to integer overflow if a and b are really large integers
def swap(a,b)
a = a+b
b = a-b
a = a-b
return a,b
end
#Method 4 (Using bitwise XOR ,no temporary variable required)
def swap(a,b)
a = a^b
b = a^b
a = a^b
return a,b
end

View File

@@ -0,0 +1,26 @@
#Given an array and a value, find if there is a triplet in array whose sum is equal to the given value.
#Time-complexity: O(n^2),Auxiliary-space:O(1)
#Algorithm:Sort,fix element then search in the array using two pointers left and right
def search_triplet(a,key)
len=a.length
a.sort! #Any sorting technique can be chosen
for i in 0...len-1
sum= key-a[i]
left=i+1
right=len-1
while(left<right)
if a[left]+a[right]==sum
return a[i],a[left],a[right]
elsif a[left]+a[right]>sum
right-=1
else
left+=1
end
end
end
return -1
end
search_triplet([12, 3, 4, 1, 6, 9],25) # => [4, 9, 12]

View File

@@ -0,0 +1,70 @@
#Given two sorted arrays ,Print the elements in the union and intersection of these arrays
#Time-complexity:O(n+m)(n=length of array1 and m=length of array2),Auxiliary-space: O(1)
# Method for finding Union
def union(a,b)
len1=a.length
len2=b.length
ctr1=0
ctr2=0
puts "Union of the gives arrays:"
while (ctr1<len1 && ctr2<len2)
if a[ctr1]==b[ctr2]
print "#{a[ctr1]} "
ctr1+=1
ctr2+=1
elsif a[ctr1]<b[ctr2]
print "#{a[ctr1]} "
ctr1+=1
else
print "#{b[ctr2]} "
ctr2+=1
end
end
#Printing remaining elements(if any)
while ctr1<len1
print "#{a[ctr1]} "
ctr1+=1
end
while ctr2<len2
print "#{b[ctr2]} "
ctr2+=1
end
end
# Method for finding Intersection
def intersection(a,b)
len1=a.length
len2=b.length
ctr1=0
ctr2=0
puts "Intersection of the gives arrays:"
while (ctr1<len1 && ctr2<len2)
if a[ctr1]==b[ctr2]
print "#{a[ctr1]} "
ctr1+=1
ctr2+=1
elsif a[ctr1]<b[ctr2]
ctr1+=1
else
ctr2+=1
end
end
end
#Ruby magic: One line solutions
def union(a,b)
print a | b # union([1,2,3],[2,3,4]) => [1, 2, 3, 4]
end
def intersection(a,b)
print a & b # intersection([1,2,3],[2,3,4]) => [2, 3]
end

View File

@@ -0,0 +1,70 @@
#Given an unsorted array,find the minimum length of subarraay,sorting which sorts the whole array.
#Time-complexity: O(n),Auxiliary-space:O(1)
=begin
Algorithm: Scan left to right and find first index where next element is less than current,let it be l
(if l==a.length-1 it is already sorted),similarly scan right to left and search first index
where previous element is larger than current,let it be r.Now search for min and max in l to r,
now from 0 to l-1 find first element which is greater than min(let it be i) and
from r+1 to a.length-1 find first element which is less than max.(let it be j)
set l= i and r=j
minimum length= r-l+1
start=l
end=r
=end
def unsorted_sub(a)
n=a.length
l=0
r=n-1
for i in 0...n-1
if a[i]>a[i+1]
l=i
break
else
l+=1
end
end
return "The complete array is sorted" if l==n-1
for i in (n-1).downto(1)
if a[i]<a[i-1]
r=i
break
else
r-=1
end
end
min_i,max_i=find_minmax(a,l,r)
for i in 0...l
if a[i]>a[min_i]
l=i
break
end
end
for i in (n-1).downto(r+1)
if a[i]<a[max_i]
r=i
break
end
end
return "Length: #{r-l+1}, Starting index: #{l}, Ending index: #{r}"
end
def find_minmax(a,lo,hi)
min=max=lo
for i in (lo+1)..hi
if a[i]>a[max]
max=i
elsif a[i]<min
min=i
else
next
end
end
return min,max
end
unsorted_sub([15, 16, 21, 30, 25, 41, 28, 39, 58]) # => Length: 5, Starting index: 3, Ending index: 7
unsorted_sub([1,2,3,4,5,6]) # => The complete array is sorted