Selection Sort algorithm - algorithm

Selection Sort:
I have created a selection sorting algorithm but someone said to me its not right selection sort.
If its not right so what type of sorting is it? and how it is different then selection sorting.
Code:
void selection_Sort(int arr[] , int size){
int temp , length = size;
for(int i = 0; i < size ; i++){
for(int j = i + 1; j < size ; j++){
if(arr[i] > arr[j]){
temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
}
}
}
please tell me how can i improve it?

To transform this code into selection sort, you have to find index of minimal element in the inner cycle, and exchange element at this index with i-th element after inner cycle finishes.
So overall number of swaps does not exceed N (while your current code could produce about N^2/2 swaps)

You have implemented Bubble sort.
The selection sort means you should find the lowest(or bigest) element in inner cycle and then switch it with element to the left/right which is at the edge of selecting (like in the picture).
There are three similar sorting alghoritms - select sort, insert sort and bubble sort you can watch how they behave here : http://i.imgur.com/fq0A8hx.gif

You have to implement a minimum element after outer for loop.
Here is the code:
def selectionSort(arr):
for i in range(len(arr)):
# Find the minimum element in remaining
# unsorted array
min_idx = i
for j in range(i+1, len(arr)):
if arr[min_idx] > arr[j]:
min_idx = j
# Swap the found minimum element with
# the first element
arr[i], arr[min_idx] = arr[min_idx], arr[i]
return arr
arr = [7,4,5,9,8,2,1]
print(selectionSort(arr))
How Selection sort works?
Starting from the first element, we search the smallest element in the array, and replace it with the element in the first position.
We then move on to the second position, and look for smallest element present in the subarray, starting from index 1, till the last index.
We replace the element at the second position in the original array, or we can say at the first position in the subarray, with the second smallest element.
4.This is repeated, until the array is completely sorted.

Selection Sort in Javascript
Comparing each with the rest and swapping with the smallest from the rest
Try this code here: https://repl.it/#VinitKhandelwal/selection-sort-javascript
function selectionSort(arr){
let min;
let i;
let j;
let temp;
console.log("Input Array");
console.log(arr);
for (i = 0; i < arr.length-1; i++) {
min = i;
for (j = i+1; j < arr.length; j++) {
console.log(arr[i], arr[j]);
if (arr[j] < arr[min]) {
console.log(arr[j]);
min = j;
}
}
if (min !== i) {
temp = arr[min];
arr[min] = arr[i];
arr[i] = temp;
console.log(arr);
}
}
console.log("Sorted using Selection Sort");
return arr
}
console.log(selectionSort([5,7,6,9,8,2,1,4,3]));
// console.log(selectionSort([1,2,3,4,5,6,7,8,9])); // uncomment to try best case, i.e. sorted

var Selectionsort = function (A) {
for (var i = 0; i < A.length; i++) {
var imin = i;
for (var j = i + 1; j <= A.length; j++) {
if (A[j] < A[imin])
imin = j;
}
var tmp = A[i];
A[i] = A[imin];
A[imin] = tmp;
}
return A;
};
var A = [10, 20, 30, 40, 50, 60, 70, 80];
var Aftersorted = Selectionsort(A);
console.log(Aftersorted);

You can improve it this way:
void selectionSort(double array[], int size) {
int min;
double temp;
for (int step = 0; step < size-1; step++) {
min = step;
for (int i = step+1; i < size; i++) {
if (array [i] < array[min]) {
min = i;
}
}
temp = array[step];
array [step] = array[min];
array [min] = temp;
}

Selection Sort in C
Selection sort is basically selecting the very first element of your unsorted sub-array as a minimum and comparing it with the other elements of your sub-array to find your original minimum. Then, replacing that minimum element with the first element of your sub-array. That's all!
Here goes my code...
#include <stdio.h>
void selectionSort(int n){
int arr[n],i,j,minIndex;
printf("\nInsert %d elements:\n",n);
for(i=0;i<n;i++){
scanf("%d",&arr[i]);
}
printf("Insert complete.\n\n");
printf("Your array looks like:\n");
for(i=0;i<n;i++){
printf("%d ",arr[i]);
}
//Selection Sort Algorithm
for(i=0;i<n-1;i++){
minIndex = i;
for(j=i+1;j<n;j++){
if(arr[j] < arr[minIndex]){
minIndex = j;
}
}
//Swapping elements
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
printf("\n\nAfter sorting your array looks like:\n");
for(i=0;i<n;i++){
printf("%d ",arr[i]);
}
}
int main(){
int n;
printf("Enter number of array elements: ");
scanf("%d",&n);
selectionSort(n);
return 0;
}
Result: -

Related

Will this Selection Sort Code work in O(n) for best case?

I search everywhere on the internet for the best case time complexity of selection sort that is o(n^2). But i write and tested this below code of selection sort that can work in O(n) for best case (that is array is already sorted). Please find the mistake in this program
This is my code:
#include <bits/stdc++.h>
using namespace std;
/* Function to print an array */
void printArray(int arr[], int size)
{
int i;
for (i = 0; i < size; i++)
cout << arr[i] << " ";
cout << endl;
}
void swap(int *xp, int *yp)
{
int temp = *xp;
*xp = *yp;
*yp = temp;
}
void selectionSort(int arr[], int n)
{
int i, j, max_idx;
// One by one move boundary of unsorted subarray
for (i = 0; i < n - 1; i++)
{
cout << endl;
printArray(arr, n);
// Find the minimum element in unsorted array
max_idx = 0;
int count = 0;
for (j = 1; j < n - i; j++)
{
if (arr[j] >= arr[max_idx])
{
max_idx = j;
count++;
}
}
if (count != n - i - 1)
{ //swap only if not already sorted
// Swap the found minimum element with the first element
swap(&arr[max_idx], &arr[n - i - 1]);
}
else //already Sorted so returning
{
return;
}
//cout << "Sorted array: \n";
printArray(arr, n);
}
}
// Driver program to test above functions
int main()
{
int arr[] = {2, 1, 4, 3, 6, 5, 8, 7};
int n = sizeof(arr) / sizeof(arr[0]);
selectionSort(arr, n);
cout << "Sorted array: \n";
printArray(arr, n);
return 0;
}
// This is code is contributed by www.bhattiacademy.com
Yes, your algorithm has a best case running time of Θ(n), because if the array is already in ascending order then count will equal n - 1 on the first iteration of the outer loop, so the algorithm will terminate early.
Your algorithm is different to the standard selection sort algorithm, which looks like this:
for(int i = 0; i < n - 1; i++) {
int min_idx = i;
for(int j = i + 1; j < n; j++) {
if(arr[j] < arr[min_idx]) {
min_idx = j;
}
}
swap(&arr[i], &arr[min_idx]);
}
The selection sort algorithm iteratively searches for the minimum remaining element and swaps it into place. This doesn't create an opportunity to detect that the array is already in increasing order, so there's no opportunity to terminate early, and selection sort's best case running time is therefore Θ(n2).
Selection Sort: Idea Given an array of n items
1.Find the largest item x, in the range of [0…n−1]
2.Swap x with the (n−1)th item
3.Reduce n by 1 and go to Step 1
Selection sort function you can use following algorithm has hint to write the code:

largest sum of contiguous subarray No Larger than k

For example,
we have
{2,2,-1},
when k = 0, return -1.
when k = 3, return 3.
This is even tricky because we have negative numbers and an additional variable k. k can be any value, negative, don't make any assumption.
I cannot refer to https://en.wikipedia.org/wiki/Maximum_subarray_problem and https://www.youtube.com/watch?v=yCQN096CwWM to solve this problem.
Can any body help me? Better use Java or JavaScript.
Here is a classic algorithm o(n) for the maximum(no variable k):
public int maxSubArray(int[] nums) {
int max = nums[0];
int tsum = nums[0];
for(int i=1;i<nums.length;i++){
tsum = Math.max(tsum+nums[i],nums[i]);
max = Math.max(max,tsum);
}
return max;
}
This is an o(nlogn) solution referred to
https://www.quora.com/Given-an-array-of-integers-A-and-an-integer-k-find-a-subarray-that-contains-the-largest-sum-subject-to-a-constraint-that-the-sum-is-less-than-k
private int maxSumSubArray(int[] a , int k){
int max = Integer.MIN_VALUE;
int sumj = 0;
TreeSet<Integer> ts = new TreeSet();
ts.add(0);
for(int i=0;i<a.length;i++){
sumj += a[i];
if (sumj == k) return k;
Integer gap = ts.ceiling(sumj - k);
if(gap != null) max = Math.max(max, sumj - gap);
ts.add(sumj);
}
return max;
}
I was influenced by the classic solution mentioned in the question.
This problem can be simply solved by an o(n^2) solution:
private int maxSumSubArray(int[] a , int k){
int max = Integer.MIN_VALUE;
for(int i=0;i<a.length;i++){
int tsum = 0;
for(int j=i;j<a.length;j++){
tsum += a[j];
if(tsum <= k) max=Math.max(max,tsum);
}
}
return max;
}
Here's a naive algorithm that runs in O(n²).
std::array<int, 3> input = {2, 2, -1};
int k = -1;
int sum = 0, largestSum = *std::min_element(input.begin(), input.end()) -1;
int i = 0, j = 0;
int start = 0, end = 0;
while (largestSum != k && i != input.size()) {
sum += input[j];
if (sum <= k && sum > largestSum) {
largestSum = sum;
start = i;
end = j;
}
++j;
if (j == input.size()) {
++i;
j = i;
sum = 0;
}
}
That's C++ but it shouldn't be hard to write in Java or Javascript.
It basically tries every sum possible (there are n*(n+1)/2) and stops if it finds k.
largestSum must be initialized to a low-enough value. Since the minimum element of the input could equal k, I subtracted 1 to it.
start and end are the first and last indices of the final subarray.
Of course, it could be improved if you had any constraints on the inputs.
Live example
Here's one in python O(n^2):
def maxsubfunc(arr, k):
s = 0
maxsofar = -1
for i,n in enumerate(arr):
s += n
if s <= k:
maxsofar = max(maxsofar, s)
else:
maxnow = s
for j in range(i):
maxnow -= arr[j]
if maxnow < k:
maxsofar = max(maxnow, maxsofar)
return maxsofar
Wonder why no one's discussing the Sliding Window based Solution for this( O(n) ).
Initialise the window with first element. Keep track of start index of window.
Iterate over the array, adding the current element to window.
If sum becomes > k, reduce the window from start until sum becomes <= k.
Check if sum > maxSumSoFar, set maxSumSoFar = sum.
Note -> 'sum' in above algo is the sum of elements in current window.
int findMaxSubarraySum(long long arr[], int N, long long K)
{
long long currSum = arr[0];
long long maxSum = LLONG_MIN;
int startIndex = 0;
if(currSum <= X) maxSum = currSum;
for(int i=1; i<N; i++){
currSum += arr[i];
while(currSum > K && startIndex <= i){
currSum -= arr[startIndex];
startIndex++;
}
if(currSum <= K) maxSum = max(maxSum, currSum);
}
return (int)maxSum;
}
Can be solved using simple sliding window. First keep adding sum of array elements and if sum exceeds k decrease it by subtracting elements from start. This works only if array has non-negative numbers.
int curr_sum = arr[0], max_sum = 0, start = 0;
// To find max_sum less than sum
for (int i = 1; i < n; i++) {
// Update max_sum if it becomes
// greater than curr_sum
if (curr_sum <= sum)
max_sum = max(max_sum, curr_sum);
// If curr_sum becomes greater than
// sum subtract starting elements of array
while (curr_sum + arr[i] > sum && start < i) {
curr_sum -= arr[start];
start++;
}
// Add elements to curr_sum
curr_sum += arr[i];
}
// Adding an extra check for last subarray
if (curr_sum <= sum)
max_sum = max(max_sum, curr_sum);
return max_sum;
# 3 steps to solve Kadane's Algorithm
//approach
sum=0
maxi=arr[0]
for i=0 to arr.length {
//steps
1. sum=sum+arr[i]
2. maxi=max(maxi,sum)
3. if(sum<0) -> sum=0
}
return maxi
//solution
nums=[-2,1,-3,4,-1,2,1,-5,4]
class Solution {
public int maxSubArray(int[] nums) {
int sum=0;
int maxi=nums[0];
for(int i=0 ; i<nums.length ; i++){
sum+=nums[i];
maxi=Math.max(maxi,sum);
if(sum<0){
sum=0;
}
}
return maxi;
}

Bubble Sort using Bubble Up

Given the algorithm for Bubble Sort:
Algorithm BubbleSort(A[0...n]):
for i <- 0 to n-2 do
for j <- 0 to n-2-i do
if(A[j+1] < A[j] then swap(A[j], A[j+1]))
I have to rewrite the Bubble Sort algorithm using where we "Bubble Up" the smallest element to the ith position on the ith pass through the list.
Can anyone help me with this?
Currently you are traversing the array from the start, therefore if you come upon the largest element, it will be "Bubbled up" to the end of the array. If you want to do the opposite, "Bubbling down" the smallest element to the start, you need to traverse the array in the opposite direction, from the end to the start. Hope it helps you to find the way.
#include<stdio.h>
void bubbleSort(int *x,int size)
{
int e,f,m,g;
m=size-2;
while(m>0)
{
e=0;
f=1;
while(e<=m)
{
if(x[f]<x[e])
{
g=x[e]; //swaping
x[e]=x[f];
x[f]=g;
}
e++;
f++;
}
m--;
}
}
void main()
{
int x[10],y;
for(y=0;y<=9;y++) //loop to insert 10 numbers into an array
{
printf("Enter a number: ");
scanf("%d",&x[y]);
}
bubbleSort(x,10); //pass number entered by user and size of array to bubbleSort
for(y=0;y<=9;y++) //loop to print sorted numbers
{
printf("%d\n",x[y]);
}
}
Looks like the answer to this has not been accepted yet. Hence trying to check if this is still an issue.
Here is what I think can be a possible implementation in Java. As #Warlord mentioned, the algorithm is to ensure that the array in concern for sorting is imagined as a vertical array. With each pass, all we are doing is check if there is a larger element below and if found that element is bubbled up to the top.
static void bubbleUpSort(int[] arr){
final int N = arr.length;
int tmp = 0;
for (int i=0; i < N; i++){
for (int j=N-1; j >= i+1; j--){
if (arr[j] < arr[j-1]){
tmp = arr[j];
arr[j] = arr[j-1];
arr[j-1] = tmp;
}
}
}
for (int k =0; k < arr.length; k++){
System.out.print(arr[k] + " ");
}
}
Called from main as:
public static void main(String[] args) {
System.out.println("Bubble Up Sort");
int[] bUp = {19, 2, 9, 4, 7, 12, 13, 3, 6};
bubbleUpSort(bUp);
}
Bubble Sort
Comparing each with the neighbor and swapping if first is greater than the next
function bubbleSort(arr){
let temp;
console.log("Input Array");
console.log(arr);
for (let i = 0; i < arr.length-1; i++) {
for (let j = 0; j < arr.length-i-1; j++) {
if (arr[j] > arr[j+1]) {
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
console.log(arr[j],"swapped with",arr[j+1])
console.log(arr);
} else {
console.log("SKIP");
}
}
}
console.log("Sorted using Bubble Sort");
return arr;
}
console.log(bubbleSort([7,6,9,8,2,1,4,3,5]));

find the max difference between j and i indices such that j > i and a[j] > a[i] in O(n)

Given an unsorted array, find the max j - i difference between indices such that j > i and a[j] > a[i] in O(n). I am able to find j and i using trivial methods in O(n^2) complexity but would like to know how to do this in O(n)?
Input: {9, 2, 3, 4, 5, 6, 7, 8, 18, 0}
Output: 8 ( j = 8, i = 0)
Input: {1, 2, 3, 4, 5, 6}
Output: 5 (j = 5, i = 0)
For brevity's sake I am going to assume all the elements are unique. The algorithm can be extended to handle non-unique element case.
First, observe that if x and y are your desired max and min locations respectively, then there can not be any a[i] > a[x] and i > x, and similarly, no a[j] < a[y] and j < y.
So we scan along the array a and build an array S such that S[i] holds the index of the minimum element in a[0:i]. Similarly an array T which holds the index of the maximum element in a[n-1:i] (i.e., backwards).
Now we can see that a[S[i]] and a[T[i]] are necessarily decreasing sequences, since they were the minimum till i and maximum from n till i respectively.
So now we try to do a merge-sort like procedure. At each step, if a[S[head]] < a[T[head]], we pop off an element from T, otherwise we pop off an element from S. At each such step, we record the difference in the head of S and T if a[S[head]] < a[T[head]]. The maximum such difference gives you your answer.
EDIT: Here is a simple code in Python implementing the algorithm.
def getMaxDist(arr):
# get minima going forward
minimum = float("inf")
minima = collections.deque()
for i in range(len(arr)):
if arr[i] < minimum:
minimum = arr[i]
minima.append((arr[i], i))
# get maxima going back
maximum = float("-inf")
maxima = collections.deque()
for i in range(len(arr)-1,0,-1):
if arr[i] > maximum:
maximum = arr[i]
maxima.appendleft((arr[i], i))
# do merge between maxima and minima
maxdist = 0
while len(maxima) and len(minima):
if maxima[0][0] > minima[0][0]:
if maxima[0][1] - minima[0][1] > maxdist:
maxdist = maxima[0][1] - minima[0][1]
maxima.popleft()
else:
minima.popleft()
return maxdist
Let's make this simple observation: If we have 2 elements a[i], a[j] with i < j and a[i] < a[j] then we can be sure that j won't be part of the solution as the first element (he can be the second but that's a second story) because i would be a better alternative.
What this tells us is that if we build greedily a decreasing sequence from the elements of a the left part of the answer will surely come from there.
For example for : 12 3 61 23 51 2 the greedily decreasing sequence is built like this:
12 -> 12 3 -> we ignore 61 because it's worse than 3 -> we ignore 23 because it's worse than 3 -> we ignore 51 because it's worse than 3 -> 12 3 2.
So the answer would contain on the left side 12 3 or 2.
Now on a random case this has O(log N) length so you can binary search on it for each element as the right part of the answer and you would get O(N log log N) which is good, and if you apply the same logic on the right part of the string on a random case you could get O(log^2 N + N(from the reading)) which is O(N). But we can do O(N) on a non-random case too.
Suppose we have this decreasing sequence. We start from the right of the string and do the following while we can pair the last of the decreasing sequence with the current number
1) If we found a better solution by taking the last of the decreasing sequence and the current number than we update the answer
2) Even if we updated the answer or not we pop the last element of the decreasing sequence because we are it's perfect match (any other match would be to the left and would give an answer with smaller j - i)
3) Repeat while we can pair these 2
Example Code:
#include <iostream>
#include <vector>
using namespace std;
int main() {
int N; cin >> N;
vector<int> A(N + 1);
for (int i = 1; i <= N; ++i)
cin >> A[i];
// let's solve the problem
vector<int> decreasing;
pair<int, int> answer;
// build the decreasing sequence
decreasing.push_back(1);
for (int i = 1; i <= N; ++i)
if (A[i] < A[decreasing.back()])
decreasing.push_back(i); // we work with indexes because we might have equal values
for (int i = N; i > 0; --i) {
while (decreasing.size() and A[decreasing.back()] < A[i]) { // while we can pair these 2
pair<int, int> current_pair(decreasing.back(), i);
if (current_pair.second - current_pair.first > answer.second - answer.first)
answer = current_pair;
decreasing.pop_back();
}
}
cout << "Best pair found: (" << answer.first << ", " << answer.second << ") with values (" << A[answer.first] << ", " << A[answer.second] << ")\n";
}
Later Edit:
I see you gave an example: I indexed from 1 to make it clearer and I print (i, j) instead of (j, i). You can alter it as you see fit.
We can avoid checking the whole array by starting from the maximum difference of j-i and comparing arr[j]>arr[i] for all the possible combinations j and i for that particular maximum difference
Whenever we get a combination of (j,i) with arr[j]>arr[i] we can exit the loop
Example : In an array of {2,3,4,5,8,1}
first code will check for maximum difference 5(5-0) i.e (arr[0],arr[5]), if arr[5]>arr[0] function will exit else will take combinations of max diff 4 (5,1) and (4,0) i.e arr[5],arr[1] and arr[4],arr[0]
int maxIndexDiff(int arr[], int n)
{
int maxDiff = n-1;
int i, j;
while (maxDiff>0)
{
j=n-1;
while(j>=maxDiff)
{
i=j - maxDiff;
if(arr[j]>arr[i])
{
return maxDiff;
}
j=j-1;
}
maxDiff=maxDiff-1;
}
return -1;
}`
https://ide.geeksforgeeks.org/cjCW3wXjcj
Here is a very simple O(n) Python implementation of the merged down-sequence idea. The implementation works even in the case of duplicate values:
downs = [0]
for i in range(N):
if ar[i] < ar[downs[-1]]:
downs.append(i)
best = 0
i, j = len(downs)-1, N-1
while i >= 0:
if ar[downs[i]] <= ar[j]:
best = max(best, j-downs[i])
i -= 1
else:
j -= 1
print best
To solve this problem, we need to get two optimum indexes of arr[]: left index i and right index j. For an element arr[i], we do not need to consider arr[i] for left index if there is an element smaller than arr[i] on left side of arr[i]. Similarly, if there is a greater element on right side of arr[j] then we do not need to consider this j for right index. So we construct two auxiliary arrays LMin[] and RMax[] such that LMin[i] holds the smallest element on left side of arr[i] including arr[i], and RMax[j] holds the greatest element on right side of arr[j] including arr[j]. After constructing these two auxiliary arrays, we traverse both of these arrays from left to right. While traversing LMin[] and RMa[] if we see that LMin[i] is greater than RMax[j], then we must move ahead in LMin[] (or do i++) because all elements on left of LMin[i] are greater than or equal to LMin[i]. Otherwise we must move ahead in RMax[j] to look for a greater j – i value. Here is the c code running in O(n) time:
#include <stdio.h>
#include <stdlib.h>
/* Utility Functions to get max and minimum of two integers */
int max(int x, int y)
{
return x > y? x : y;
}
int min(int x, int y)
{
return x < y? x : y;
}
/* For a given array arr[], returns the maximum j – i such that
arr[j] > arr[i] */
int maxIndexDiff(int arr[], int n)
{
int maxDiff;
int i, j;
int *LMin = (int *)malloc(sizeof(int)*n);
int *RMax = (int *)malloc(sizeof(int)*n);
/* Construct LMin[] such that LMin[i] stores the minimum value
from (arr[0], arr[1], ... arr[i]) */
LMin[0] = arr[0];
for (i = 1; i < n; ++i)
LMin[i] = min(arr[i], LMin[i-1]);
/* Construct RMax[] such that RMax[j] stores the maximum value
from (arr[j], arr[j+1], ..arr[n-1]) */
RMax[n-1] = arr[n-1];
for (j = n-2; j >= 0; --j)
RMax[j] = max(arr[j], RMax[j+1]);
/* Traverse both arrays from left to right to find optimum j - i
This process is similar to merge() of MergeSort */
i = 0, j = 0, maxDiff = -1;
while (j < n && i < n)
{
if (LMin[i] < RMax[j])
{
maxDiff = max(maxDiff, j-i);
j = j + 1;
}
else
i = i+1;
}
return maxDiff;
}
/* Driver program to test above functions */
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6};
int n = sizeof(arr)/sizeof(arr[0]);
int maxDiff = maxIndexDiff(arr, n);
printf("\n %d", maxDiff);
getchar();
return 0;
}
Simplified version of Subhasis Das answer using auxiliary arrays.
def maxdistance(nums):
n = len(nums)
minima ,maxima = [None]*n, [None]*n
minima[0],maxima[n-1] = nums[0],nums[n-1]
for i in range(1,n):
minima[i] = min(nums[i],minima[i-1])
for i in range(n-2,-1,-1):
maxima[i]= max(nums[i],maxima[i+1])
i,j,maxdist = 0,0,-1
while(i<n and j<n):
if minima[i] <maxima[j]:
maxdist = max(j-i,maxdist)
j = j+1
else:
i += 1
print maxdist
I can think of improvement over O(n^2), but need to verify if this is O(n) in worse case or not.
Create a variable BestSoln=0; and traverse the array for first element
and store the best solution for first element i.e bestSoln=k;.
Now for 2nd element consider only elements which are k distances away
from the second element.
If BestSoln in this case is better than first iteration then replace
it otherwise let it be like that. Keep iterating for other elements.
It can be improved further if we store max element for each subarray starting from i to end.
This can be done in O(n) by traversing the array from end.
If a particular element is more than it's local max then there is no need to do evaluation for this element.
Input:
{9, 2, 3, 4, 5, 6, 7, 8, 18, 0}
create local max array for this array:
[18,18,18,18,18,18,18,0,0] O(n).
Now, traverse the array for 9 ,here best solution will be i=0,j=8.
Now for second element or after it, we don't need to evaluate. and best solution is i=0,j=8.
But suppose array is Input:
{19, 2, 3, 4, 5, 6, 7, 8, 18, 0,4}
Local max array [18,18,18,18,18,18,18,0,0] then in first iteration we don't need to evaluate as local max is less than current elem.
Now for second iteration best solution is, i=1,j=10. Now for other elements we don't need to consider evaluation as they can't give best solution.
Let me know your view your use case to which my solution is not applicable.
This is a very simple solution for O(2n) of speed and additional ~O(2n) of space (in addition to the input array). The following implementation is in C:
int findMaxDiff(int array[], int size) {
int index = 0;
int maxima[size];
int indexes[size];
while (index < size) {
int max = array[index];
int i;
for (i = index; i < size; i++) {
if (array[i] > max) {
max = array[i];
indexes[index] = i;
}
}
maxima[index] = max;
index++;
}
int j;
int result;
for (j = 0; j < size; j++) {
int max2 = 0;
if (maxima[j] - array[j] > max2) {
max2 = maxima[j] - array[j];
result = indexes[j];
}
}
return result;
}
The first loop scan the array once, finding for each element the maximum of the remaining elements to its right. We store also the relative index in a separate array.
The second loops finds the maximum between each element and the correspondent right-hand-side maximum, and returns the right index.
My Solution with in O(log n) (Please correct me here if I am wrong in calculating this complexity)time ...
Idea is to insert into a BST and then search for node and if the node has a right child then traverse through the right sub tree to calculate the node with maximum index..
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
public static void main (String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int t1 = Integer.parseInt(br.readLine());
for(int j=0;j<t1;j++){
int size = Integer.parseInt(br.readLine());
String input = br.readLine();
String[] t = input.split(" ");
Node root = new Node(Integer.parseInt(t[0]),0);
for(int i=1;i<size;i++){
Node addNode = new Node(Integer.parseInt(t[i]),i);
insertIntoBST(root,addNode);
}
for(String s: t){
Node nd = findNode(root,Integer.parseInt(s));
if(nd.right != null){
int i = nd.index;
int j1 = calculate(nd.right);
mVal = max(mVal,j1-i);
}
}
System.out.println(mVal);
mVal=0;
}
}
static int mVal =0;
public static int calculate (Node root){
if(root==null){
return -1;
}
int i = max(calculate(root.left),calculate(root.right));
return max(root.index,i);
}
public static Node findNode(Node root,int n){
if(root==null){
return null;
}
if(root.value == n){
return root;
}
Node result = findNode(root.left,n);
if(result ==null){
result = findNode(root.right,n);
}
return result;
}
public static int max(int a , int b){
return a<b?b:a;
}
public static class Node{
Node left;
Node right;
int value;
int index;
public Node(int value,int index){
this.value = value;
this.index = index;
}
}
public static void insertIntoBST(Node root, Node addNode){
if(root.value< addNode.value){
if(root.right!=null){
insertIntoBST(root.right,addNode);
}else{
root.right = addNode;
}
}
if(root.value>=addNode.value){
if(root.left!=null){
insertIntoBST(root.left,addNode);
}else{
root.left =addNode;
}
}
}
}
A simplified algorithm from Subhasis Das's answer:
# assume list is not empty
max_dist = 0
acceptable_min = (0, arr[0])
acceptable_max = (0, arr[0])
min = (0, arr[0])
for i in range(len(arr)):
if arr[i] < min[1]:
min = (i, arr[i])
elif arr[i] - min[1] > max_dist:
max_dist = arr[i] - min[1]
acceptable_min = min
acceptable_max = (i, arr[i])
# acceptable_min[0] is the i
# acceptable_max[0] is the j
# max_dist is the max difference
Below is a C++ solution for the condition a[i] <= a[j]. It needs a slight modification to handle the case a[i] < a[j].
template<typename T>
std::size_t max_dist_sorted_pair(const std::vector<T>& seq)
{
const auto n = seq.size();
const auto less = [&seq](std::size_t i, std::size_t j)
{ return seq[i] < seq[j]; };
// max_right[i] is the position of the rightmost
// largest element in the suffix seq[i..]
std::vector<std::size_t> max_right(n);
max_right.back() = n - 1;
for (auto i = n - 1; i > 0; --i)
max_right[i - 1] = std::max(max_right[i], i - 1, less);
std::size_t max_dist = 0;
for (std::size_t i = 0, j = 0; i < n; ++i)
while (!less(max_right[j], i))
{
j = max_right[j];
max_dist = std::max(max_dist, j - i);
if (++j == n)
return max_dist;
}
return max_dist;
}
Please review this solution and cases where it might fail:
def maxIndexDiff(arr, n):
j = n-1
for i in range(0,n):
if j > i:
if arr[j] >= arr[i]:
return j-i
elif arr[j-1] >= arr[i]:
return (j-1) - i
elif arr[j] >= arr[i+1]:
return j - (i+1)
j -= 1
return -1
int maxIndexDiff(int arr[], int n)
{
// Your code here
vector<int> rightMax(n);
rightMax[n-1] = arr[n-1];
for(int i =n-2;i>=0;i--){
rightMax[i] = max(rightMax[i+1],arr[i]);
}
int i = 0,j=0,maxDis = 0;
while(i<n &&j<n){
if(rightMax[j]>=arr[i]){
maxDis = max(maxDis,j-i);
j++;
} else
i++;
}
return maxDis;
}
There is concept of keeping leftMin and rightMax but leftMin is not really required and leftMin will do the work anyways.
We are choosing rightMax and traversing from start till we get a smaller value than that!
Create Arraylist of pairs where is key is array element and value is the index. Sort this arraylist of pairs. Traverse this arraylist of pairs to get the maximum gap between(maxj-i). Also keep a track of maxj and update when new maxj is found. Please find my java solution which takes O(nlogn) time complexity and O(n) space complexity.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
class MaxDistanceSolution {
private class Pair implements Comparable<Pair> {
int key;
int value;
public int getKey() {
return key;
}
public int getValue() {
return value;
}
Pair(int key, int value) {
this.key = key;
this.value = value;
}
#Override
public int compareTo(Pair o) {
return this.getKey() - o.getKey();
}
}
public int maximumGap(final ArrayList<Integer> A) {
int n = A.size();
ArrayList<Pair> B = new ArrayList<>();
for (int i = 0 ; i < n; i++)
B.add(new Pair(A.get(i), i));
Collections.sort(B);
int maxJ = B.get(n-1).getValue();
int gaps = 0;
for (int i = n - 2; i >= 0; i--) {
gaps = Math.max(gaps, maxJ - B.get(i).getValue());
maxJ = Math.max(maxJ, B.get(i).getValue());
}
return gaps;
}
}
public class MaxDistance {
public static void main(String[] args) {
MaxDistanceSolution sol = new MaxDistanceSolution();
ArrayList<Integer> A = new ArrayList<>(Arrays.asList(3, 5, 4, 2));
int gaps = sol.maximumGap(A);
System.out.println(gaps);
}
}
I have solved this question here.
https://github.com/nagendra547/coding-practice/blob/master/src/arrays/FindMaxIndexDifference.java
Putting code here too. Thanks.
private static int findMaxIndexDifferenceOptimal(int[] a) {
int n = a.length;
// array containing minimums
int A[] = new int[n];
A[0] = a[0];
for (int i = 1; i < n; i++) {
A[i] = Math.min(a[i], A[i - 1]);
}
// array containing maximums
int B[] = new int[n];
B[n - 1] = a[n - 1];
for (int j = n - 2; j >= 0; j--) {
B[j] = Math.max(a[j], B[j + 1]);
}
int i = 0, maxDiff = -1;
int j = 0;
while (i < n && j < n) {
if (B[j] > A[i]) {
maxDiff = Math.max(j - i, maxDiff);
j++;
} else {
i++;
}
}
return maxDiff;
}

Interview - Find magnitude pole in an array

Magnitude Pole: An element in an array whose left hand side elements are lesser than or equal to it and whose right hand side element are greater than or equal to it.
example input
3,1,4,5,9,7,6,11
desired output
4,5,11
I was asked this question in an interview and I have to return the index of the element and only return the first element that met the condition.
My logic
Take two MultiSet (So that we can consider duplicate as well), one for right hand side of the element and one for left hand side of the
element(the pole).
Start with 0th element and put rest all elements in the "right set".
Base condition if this 0th element is lesser or equal to all element on "right set" then return its index.
Else put this into "left set" and start with element at index 1.
Traverse the Array and each time pick the maximum value from "left set" and minimum value from "right set" and compare.
At any instant of time for any element all the value to its left are in the "left set" and value to its right are in the "right set"
Code
int magnitudePole (const vector<int> &A) {
multiset<int> left, right;
int left_max, right_min;
int size = A.size();
for (int i = 1; i < size; ++i)
right.insert(A[i]);
right_min = *(right.begin());
if(A[0] <= right_min)
return 0;
left.insert(A[0]);
for (int i = 1; i < size; ++i) {
right.erase(right.find(A[i]));
left_max = *(--left.end());
if (right.size() > 0)
right_min = *(right.begin());
if (A[i] > left_max && A[i] <= right_min)
return i;
else
left.insert(A[i]);
}
return -1;
}
My questions
I was told that my logic is incorrect, I am not able to understand why this logic is incorrect (though I have checked for some cases and
it is returning right index)
For my own curiosity how to do this without using any set/multiset in O(n) time.
For an O(n) algorithm:
Count the largest element from n[0] to n[k] for all k in [0, length(n)), save the answer in an array maxOnTheLeft. This costs O(n);
Count the smallest element from n[k] to n[length(n)-1] for all k in [0, length(n)), save the answer in an array minOnTheRight. This costs O(n);
Loop through the whole thing and find any n[k] with maxOnTheLeft <= n[k] <= minOnTheRight. This costs O(n).
And you code is (at least) wrong here:
if (A[i] > left_max && A[i] <= right_min) // <-- should be >= and <=
Create two bool[N] called NorthPole and SouthPole (just to be humorous.
step forward through A[]tracking maximum element found so far, and set SouthPole[i] true if A[i] > Max(A[0..i-1])
step backward through A[] and set NorthPole[i] true if A[i] < Min(A[i+1..N-1)
step forward through NorthPole and SouthPole to find first element with both set true.
O(N) in each step above, as visiting each node once, so O(N) overall.
Java implementation:
Collection<Integer> magnitudes(int[] A) {
int length = A.length;
// what's the maximum number from the beginning of the array till the current position
int[] maxes = new int[A.length];
// what's the minimum number from the current position till the end of the array
int[] mins = new int[A.length];
// build mins
int min = mins[length - 1] = A[length - 1];
for (int i = length - 2; i >= 0; i--) {
if (A[i] < min) {
min = A[i];
}
mins[i] = min;
}
// build maxes
int max = maxes[0] = A[0];
for (int i = 1; i < length; i++) {
if (A[i] > max) {
max = A[i];
}
maxes[i] = max;
}
Collection<Integer> result = new ArrayList<>();
// use them to find the magnitudes if any exists
for (int i = 0; i < length; i++) {
if (A[i] >= maxes[i] && A[i] <= mins[i]) {
// return here if first one only is needed
result.add(A[i]);
}
}
return result;
}
Your logic seems perfectly correct (didn't check the implementation, though) and can be implemented to give an O(n) time algorithm! Nice job thinking in terms of sets.
Your right set can be implemented as a stack which supports a min, and the left set can be implemented as a stack which supports a max and this gives an O(n) time algorithm.
Having a stack which supports max/min is a well known interview question and can be done so each operation (push/pop/min/max is O(1)).
To use this for your logic, the pseudo code will look something like this
foreach elem in a[n-1 to 0]
right_set.push(elem)
while (right_set.has_elements()) {
candidate = right_set.pop();
if (left_set.has_elements() && left_set.max() <= candidate <= right_set.min()) {
break;
} else if (!left.has_elements() && candidate <= right_set.min() {
break;
}
left_set.push(candidate);
}
return candidate
I saw this problem on Codility, solved it with Perl:
sub solution {
my (#A) = #_;
my ($max, $min) = ($A[0], $A[-1]);
my %candidates;
for my $i (0..$#A) {
if ($A[$i] >= $max) {
$max = $A[$i];
$candidates{$i}++;
}
}
for my $i (reverse 0..$#A) {
if ($A[$i] <= $min) {
$min = $A[$i];
return $i if $candidates{$i};
}
}
return -1;
}
How about the following code? I think its efficiency is not good in the worst case, but it's expected efficiency would be good.
int getFirstPole(int* a, int n)
{
int leftPole = a[0];
for(int i = 1; i < n; i++)
{
if(a[j] >= leftPole)
{
int j = i;
for(; j < n; j++)
{
if(a[j] < a[i])
{
i = j+1; //jump the elements between i and j
break;
}
else if (a[j] > a[i])
leftPole = a[j];
}
if(j == n) // if no one is less than a[i] then return i
return i;
}
}
return 0;
}
Create array of ints called mags, and int variable called maxMag.
For each element in source array check if element is greater or equal to maxMag.
If is: add element to mags array and set maxMag = element.
If isn't: loop through mags array and remove all elements lesser.
Result: array of magnitude poles
Interesting question, I am having my own solution in C# which I have given below, read the comments to understand my approach.
public int MagnitudePoleFinder(int[] A)
{
//Create a variable to store Maximum Valued Item i.e. maxOfUp
int maxOfUp = A[0];
//if list has only one value return this value
if (A.Length <= 1) return A[0];
//create a collection for all candidates for magnitude pole that will be found in the iteration
var magnitudeCandidates = new List<KeyValuePair<int, int>>();
//add the first element as first candidate
var a = A[0];
magnitudeCandidates.Add(new KeyValuePair<int, int>(0, a));
//lets iterate
for (int i = 1; i < A.Length; i++)
{
a = A[i];
//if this item is maximum or equal to all above items ( maxofUp will hold max value of all the above items)
if (a >= maxOfUp)
{
//add it to candidate list
magnitudeCandidates.Add(new KeyValuePair<int, int>(i, a));
maxOfUp = a;
}
else
{
//remote all the candidates having greater values to this item
magnitudeCandidates = magnitudeCandidates.Except(magnitudeCandidates.Where(c => c.Value > a)).ToList();
}
}
//if no candidate return -1
if (magnitudeCandidates.Count == 0) return -1;
else
//return value of first candidate
return magnitudeCandidates.First().Key;
}

Resources