If we have to find 3rd highest sum of a pair of elements in an array.
E.g. Given
int arr[] = { 1, 2, 3, 4 };
then, we have these pairs:
(1,2) = 3, (1,3) = 4, (1,4) = 5, (2,3) = 5, (2,4) = 6, (3,4) = 7
Here, the answer is 5 and the pairs are (1,4) and (2,3).
The array is not necessarily sorted and duplicated values in the array can appear in pairs.
I have tried an algorithm with two nested loops. Time complexity is quadratic. How can I lower the complexity?
Now, if we need to find the kth highest pair sum. Can we go for minheap or maxheap wherein we first store the pair sums in the maxheap/minheap and then find the kth largest of them.
First try a brute for approach:
scan the array with a double loop to find the largest sum sum1;
rescan the array with a double loop to find the largest sum sum2 different from sum1;
rescan the array a third time to find the largest sum sum3 different from both sum1 and sum2;
rescan the array one final time to print all pairs that have sum sum3.
Time complexity is quadratic, but it will handle duplicates correctly.
You can then drastically reduce the complexity by filtering the array, only keeping the largest 3 numbers with at most 2 instances if there are duplicates. This can be done in linear time. You then run the quadratic algorithm on a set of at most 6 elements. Total complexity is still linear.
var a=[30,4,2,5,6,0,9];
var first=a[0];
var second="";
var third="";
// Solve it in O(n) time
for(var i=1;i<a.length;i++)
{
//Find first Max
if(a[i]>first)
{
second=first;
first=a[i];
}
//Find second Max
else if(a[i]>second && a[i]!=first )
{
third=second;
second=a[i];
}
//Find third Max
else if(a[i]>third && a[i]!=first && a[i]!=second)
third=a[i];
}
console.log(first+second+third);
public int thirdHighest()
{
int sum = 0;
List<int> number = new List<int>();
int[] array = new int[] { 1, 2, 3, 4, 6, 7 };
for (int i = 0; i < array.Length; i++)
{
for (int j = i + 1; j < array.Length; j++)
{
sum = array[i] + array[j];
if (number.Contains(sum))
{
}
else
{
number.Add(sum);
}
}
}
int[] array1 = new int[number.Count];
for (int i = 0; i < number.Count; i++)
{
array1[i] = number[i];
}
Array.Sort<int>(array1);
Array.Reverse(array1);
return array1[2];
}
you can use it this way:
int varmax1, varmax2, varmax3, varmax4, varmax5, varmax6, i, j, max=0, max2=0, max3=0;
for(i=0; i<3;i++)
{
for(j=i;j<3;j++)
{
sum=arr[i]+arr[j];
if(sum>max)
{
max3=max2;
max2=max;
max=sum;
varmax1 = varmax3;
varmax2 = varmax4;
varmax3 = varmax5;
varmax4 = varmax6;
varmax5 = i;
varmax6 = j;
}
else if(sum>max2)
{
max3=max2;
max2=sum;
varmax1 = varmax3;
varmax2 = varmax4;
varmax3=i
varmax4=j
}
else if(sum>max3)
{
max3=sum;
varmax1 = arr[i];
varmax2 = arr[j];
}
}
}
printf("elements with 3rd largest sum are %d %d", varmax1, varmax2);
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] intList = {5,4,7,8,12,16,19,5};
Set<Integer> intSumList = new HashSet<Integer>();
List<Integer> intSumList1 = new ArrayList<Integer>();
for(int i=0;i<intList.length;i++){
for(int j=(intList.length - 1);j>i;j--)
{
// System.out.println(intList[j]+" --- "+intList[i]);
intSumList.add((intList[j]+intList[i]));
}
}
for(int ele : intSumList){
intSumList1.add(ele);
}
Collections.sort(intSumList1);
for(int ele : intSumList1){
System.out.println(ele);
}
System.out.println("sum is "+intSumList1.get((intSumList1.size()-3)));
}
Related
Given 2 Arrays of Intergers (unsorted, may contains duplicate elements), e.g.:
int[] left = {1, 5, 3};
int[] right = {2, 2};
We can get sums of subset of left array by picking or not picking up each element (2^n combinations), so, all the possbile sums could be (remove the duplicate sums):
{0, 1, 3, 4, 5, 6, 8, 9}
Same thing to the right array, sums of subset of right array are:
{0, 2, 4}
Then, the max common sum of subsets of these 2 arrays is 4, because 4 = left[0] + left[2] = rihgt[0] + right[1] and it's the max.
Question: how to get max common sum and indexes to construct this sum from 2 arrays? (if there are multipe combinations could get the same max sum in one array, just need to return one combination) Any better way to get the max common sum without caculating out all the possbile sums of subset?
I think this solution using bitsets in C++ will work.
// returns maximum possible common subset sum
int fun(int left[], int right[]){
// for the given constraints, the maximum possible sum is 10^7
bitset<10000001> b, b1;
int n = // size of left array
int m = // size of right array
b[0] = b1[0] = 1;
for(int i=0;i<n;i++){
b|=b<<left[i];
}
for(int i=0;i<m;i++){
b1|=b1<<right[i];
}
// After the above loop, b and b1 contains all possible unique values of subset sum.
// Just loop from the most significant bit and find the position in which the
// bits of both, b and b1 are set.
// That position is the maximum possible common subset sum
// For indices, any standard algorithm for finding subset-sum
// for a particular sum will do.
}
Based on the method pointed out by risingStark for finding the maximum common sum and on Print all subsets with given sum for finding indexes of summands, and since the question uses Java syntax, here's an unoptimized and unbeautified Java program with some example data sets:
import java.util.Arrays;
import java.math.BigInteger;
public class _68232965
{
static int sum;
static boolean found;
public static void main(String[] args)
{
{ int[][] lr = { {1, 5, 3}, {2, 2} }; maxcommsum(lr); }
{ int[][] lr = { {1,1,2,3,4}, {2, 2} }; maxcommsum(lr); }
{ int[][] lr = { {1, 2, 3}, {2, 2} }; maxcommsum(lr); }
{ int[][] lr = { {3,3,3,10}, {9,13} }; maxcommsum(lr); }
}
static void maxcommsum(int[][] lr)
{
for (var a: lr) System.out.println(Arrays.toString(a));
var s = new BigInteger[] { BigInteger.ONE, BigInteger.ONE };
for (int j, i = 0; i < 2; ++i)
for (j = 0; j < lr[i].length; ++j) s[i] = s[i].shiftLeft(lr[i][j]).or(s[i]);
while (s[0].bitLength() != s[1].bitLength())
{ // find the maximum common sum
int larger = s[0].bitLength() < s[1].bitLength() ? 1 : 0;
s[larger] = s[larger].clearBit(s[larger].bitLength()-1);
}
sum = s[0].bitLength()-1;
System.out.println("sum = "+sum);
for (var a: lr) { found = false; f(a, 0, 0); System.out.println("<= indexes"); }
}
static void f(int[] pat, int i, int currSum)
{ // find indexes of summands
if (currSum == sum)
{
found = true;
return;
}
if (currSum < sum && i < pat.length)
{
f(pat, i+1, currSum + pat[i]); if (found) { System.out.print(i+" "); return; }
f(pat, i+1, currSum);
}
}
}
I have written a program that inputs an array of n elements and outputs the number of pair of elements that are out-of-order.
We will call a pair of elements arr[i] and arr[j] out-of-order if i < j and arr[i] > arr[j].
The running time of my program is O(n^2). It's a naive approach with two nested for loops. I was wondering if there is another way to solve this problem in less time. maybe in O(nLogn) time?
The algorithm you are looking for is called Counting inversions. Yes you can solve this problem using divide and conquer approach and the time complexity will be O(nlogn). It's similar to merge sort and additionally we need to keep track of inversions count. I am only printing the inversions count.
public class InversionsInOrderNSquared {
public static void main(String[] args) {
int array[] = { 10, 15, 2, 2, -4, 100, 99999, -10 };
System.out.println("Inversions Count: "+inversions(array));
}
private static int inversions(int[] array) {
int n = array.length;
int inversionCountLeft = 0;
int inversionCountRight = 0;
int inversionCountCross = 0;
if (n >= 2) {
int mid = n / 2;
int[] leftArray = new int[mid];
int[] rightArray = new int[n - mid];
for (int i = 0; i < n; i++) {
if (i < mid) {
leftArray[i] = array[i];
} else {
rightArray[i - mid] = array[i];
}
}
inversionCountLeft = inversions(leftArray);
inversionCountRight = inversions(rightArray);
inversionCountCross = computeInversions(array, leftArray,
rightArray);
}
return (inversionCountLeft + inversionCountRight + inversionCountCross);
}
private static int computeInversions(int[] array, int[] leftArray,
int[] rightArray) {
int n_left = leftArray.length;
int n_right = rightArray.length;
int inversionCount = 0;
int i = 0;
int j = 0;
int k = 0;
while (i < n_left && j < n_right) {
if (leftArray[i] > rightArray[j]) {
array[k] = rightArray[j];
inversionCount += (n_left - i);// logic is we are doing index
// wise element comparison
// between 2 sorted arrays thus
// for any index if any element
// in left
// sub-array is grater than
// element in right sub array
// that mean all the elements
// after that element present in
// left sub-array should be
// grater than right sub-array
// elements. Thus we are
// considering (n_left - i) in
// inversion count calculation.
j++;
} else {
array[k] = leftArray[i];
i++;
}
k++;
}
while (i < n_left) {
array[k] = leftArray[i];
i++;
k++;
}
while (j < n_right) {
array[k] = rightArray[j];
j++;
k++;
}
return inversionCount;
}
}
Execution 1:
Output:
Input array:
int array[] = { 10, 15, 2, 2, -4, 100, 99999, -10 };
Inversions Count: 15
Execution 2:
Input array:
int array[] = { 1,2,3,4,5,6 };
Output:
Inversions Count: 0
Regarding time complexity calculation:
computeInversions() method will take theta(n) time.
inversions() method is getting called 2 times with array size n/2.
Hence the recurrence relation is,
T(n) = 2T(n/2) + theta(n);
It's following Master's theorem equation format.
Hence a =2, b=2 and f(n)=theta(n)
n^log a base b = n^log 2 base 2 = n^1 = n
Thus above recurrence is matching case 2 of Master's theorem.
Thus time complexity is O(nlogn)
You can calculate such out of order pairs in o(nlogn) complexity.
For example if arr[] = {1,5,3,2,4}
Out of order pairs are : (5,3), (5,2), (5,4), (3,2).
Below is the working code for the same :
public static int countOutOfOrder(int []nums) {
int len = nums.length, index=len-1, count=0, currindex=0, total=0;
List<Integer>sorted = new ArrayList<Integer>();
while(index>=0) {
currindex = search(sorted, nums[index]);
sorted.add(currindex, nums[index]);
total+=(currindex);
index--;
}
return total;
}
private static int search(List<Integer> sorted, int value) {
int start=0, end = sorted.size()-1, mid=0;
while(start<=end) {
mid = (start+end)/2;
if(sorted.get(mid) == value && (mid==start || sorted.get(mid-1) == value)) {
return mid;
} else if(sorted.get(mid) <= value) {
start = mid+1;
} else {
end = mid-1;
}
}
return start;
}
Explanation for o(nlogn) solution based on above example :
Maintain a list of sorted elements say sorted
Start from end index
search in sorted list where we can insert the current element in
Based on position we can insert , find total number of elements before this index that will be total inversions.
Add this element in the sorted list.
Time complexity :
We are looping through all elements so complexity for this is o(n)
For each element we are searching in sorted list , search complecity is o(logn).
So, total complexity is o(n)*o(logn) = o(nlogn)
Found this interview question on Careercup
Given an array A with n integers.
Rearrange array such that
A[0]<=A[1]>=A[2]<=A[3]>=A[4]<=A[5] and so on
Edit: Array is not sorted and You have to do it in linear time O(N)
I am unable to find a solution in linear time, the closest I get is sort the array and then rearrange elements. Anyone has idea how it can be done in linear time? Can this be even done in linear time?
My proposed solution is to sort the array in nlogn time and then rearrange every odd element i with i-1 and i+1 alternatively.
Use quickselect to find the median of the array in O(n). This will allow you to divide the array in two equal (or almost equal) parts: those who are less than or equal to the median (A) up to n/2 elements, and the rest (B), that will be, by definition, greater than or equal to the median.
Arrange the array using this two halves like the following:
A B A B A B A
This will be correct, because every item A will be less than or equal to every B, by definition.
You can use this function (the code is in Swift) to arrange the array in a Wave Form in time O(n).
func wave(inout list: [Int]) {
let evenIndexes = (0..<list.count).filter { $0 % 2 == 0 }
for index in evenIndexes {
if index > 0 && list[index] > list[index-1] {
swap(&list[index], &list[index-1])
}
if index < list.count - 1 && list[index] > list[index+1] {
swap(&list[index], &list[index+1])
}
}
}
This solution is based on the algorithm described here.
Test
var test0 = [1,2,3,4,5,6]
wave(&test0)
print(test0) // [1, 3, 2, 5, 4, 6]
var test1 = [4, 6, 2, 1, 3, 7]
wave(&test1)
print(test1) // [4, 6, 1, 3, 2, 7]
var test2 = [20, 9, 4, 2, 0]
wave(&test2)
print(test2) // [9, 20, 2, 4, 0]
Time complexity
The function has a for loop executed n/2 times (only for the even indexes). So the for loop has time complexity O(n).
Inside the for loop we found a couple of if then statement, both are executed in constante time so O(1).
So the time complexity is O(n) * O(1) = O(n) where n is the number of elements in the input array.
C# implementation of O(n) solution with usage of NthElement algorithm:
public void WaveSortTest(int[] a)
{
var nthElement = NthElement(a, a.Length / 2);
var element = a[nthElement];
var odd = 1;
var even = 0;
var r = new int[a.Length];
for (int i = 0; i < a.Length; i++)
{
if (a[i] <= element)
{
r[even] = a[i];
even += 2;
}
else
{
r[odd] = a[i];
odd += 2;
}
}
PrintArray(r);
}
private static readonly Random _rnd = new Random((int)DateTime.Today.ToFileTimeUtc());
private static int NthElement(int[] arr, int k)
{
return NthElement(arr, 0, arr.Length, k);
}
private static int NthElement(int[] arr, int low, int high, int k)
{
var pos = low + _rnd.Next(high - low);
Swap(arr, pos, high - 1);
var i = Partition(arr, low, high);
if (k < i)
{
return NthElement(arr, low, i, k);
}
if (k > i)
{
return NthElement(arr, i + 1, high, k);
}
return i;
}
private static int Partition(int[] arr, int low, int high)
{
var i = low - 1;
for (var j = low; j < high; j++)
{
if (arr[j] <= arr[high - 1])
{
i++;
Swap(arr, i, j);
}
}
return i;
}
private static void Swap<T>(T[] a, int first, int second)
{
var t = a[first];
a[first] = a[second];
a[second] = t;
}
private static void PrintArray(IEnumerable<int> arr)
{
foreach (var item in arr)
{
Console.Write(item + " ");
}
Console.WriteLine();
}
This is an interview question.
Find the Kth smallest element in a matrix with sorted rows and columns.
Is it correct that the Kth smallest element is one of a[i, j] such as i + j = K ?
False.
Consider a simple matrix like this one:
1 3 5
2 4 6
7 8 9
9 is the largest (9th smallest) element. But 9 is at A[3, 3], and 3+3 != 9. (No matter what indexing convention you use, it cannot be true).
You can solve this problem in O(k log n) time by merging the rows incrementally, augmented with a heap to efficiently find the minimum element.
Basically, you put the elements of the first column into a heap and track the row they came from. At each step, you remove the minimum element from the heap and push the next element from the row it came from (if you reach the end of the row, then you don't push anything). Both removing the minimum and adding a new element cost O(log n). At the jth step, you remove the jth smallest element, so after k steps you are done for a total cost of O(k log n) operations (where n is the number of rows in the matrix).
For the matrix above, you initially start with 1,2,7 in the heap. You remove 1 and add 3 (since the first row is 1 3 5) to get 2,3,7. You remove 2 and add 4 to get 3,4,7. Remove 3 and add 5 to get 4,5,7. Remove 4 and add 6 to get 5,6,7. Note that we are removing the elements in the globally sorted order. You can see that continuing this process will yield the kth smallest element after k iterations.
(If the matrix has more rows than columns, then operate on the columns instead to reduce the running time.)
O(k log(k)) solution.
Build a minheap.
Add (0,0) to the heap. While, we haven't found the kth smallest element, remove the top element (x,y) from heap and add next two elements [(x+1,y) and (x,y+1)] if they haven't been visited before.
We are doing O(k) operations on a heap of size O(k) and hence the complexity.
This problem can be solved using binary search and optimised counting in a sorted Matrix. A binary search takes O(log(n)) time and for each search value it takes n iterations on average to find the numbers that are smaller than the searched number. The search space for binary search is limited to the minimum value in the Matrix at mat[0][0] and the maximum value mat[n-1][n-1].
For every number that is chosen from the binary search we need to count the numbers that are smaller than or equal to that particular number. And thus the smallest number can be found.
For better understanding you can refer to this video:
https://www.youtube.com/watch?v=G5wLN4UweAM&t=145s
Start traversing the matrix from the top-left corner (0,0) and use a binary heap for storing the "frontier" - a border between a visited part of the matrix and the rest of it.
Implementation in Java:
private static class Cell implements Comparable<Cell> {
private final int x;
private final int y;
private final int value;
public Cell(int x, int y, int value) {
this.x = x;
this.y = y;
this.value = value;
}
#Override
public int compareTo(Cell that) {
return this.value - that.value;
}
}
private static int findMin(int[][] matrix, int k) {
int min = matrix[0][0];
PriorityQueue<Cell> frontier = new PriorityQueue<>();
frontier.add(new Cell(0, 0, min));
while (k > 1) {
Cell poll = frontier.remove();
if (poll.y + 1 < matrix[poll.x].length) frontier.add(new Cell(poll.x, poll.y + 1, matrix[poll.x][poll.y + 1]));
if (poll.x + 1 < matrix.length) frontier.add(new Cell(poll.x + 1, poll.y, matrix[poll.x + 1][poll.y]));
if (poll.value > min) {
min = poll.value;
k--;
}
}
return min;
}
As people mentioned previously the easiest way is to build a min heap. Here's a Java implementation using PriorityQueue:
private int kthSmallestUsingHeap(int[][] matrix, int k) {
int n = matrix.length;
// This is not necessary since this is the default Int comparator behavior
Comparator<Integer> comparator = new Comparator<Integer>() {
#Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
};
// building a minHeap
PriorityQueue<Integer> pq = new PriorityQueue<>(n*n, comparator);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
pq.add(matrix[i][j]);
}
}
int ans = -1;
// remove the min element k times
for (int i = 0; i < k; i++) {
ans = pq.poll();
}
return ans;
}
Kth smallest element in the matrix :
The problem can be narrowed down as below.
if k is 20, then take k*k matrix (where answer will definitely lie.)
Now you can merge the rows in pair repeatedly to build a sorted array and then find the kth smallest number.
//int arr[][] = {{1, 5, 10, 14},
// {2, 7, 12, 16},
// {4, 10, 15, 20},
// {6, 13, 19, 22}
//};
// O(k) Solution
public static int myKthElement(int arr[][], int k) {
int lRow = 1;
int lCol = 0;
int rRow = 0;
int rCol = 1;
int count = 1;
int row = 0;
int col = 0;
if (k == 1) {
return arr[row][col];
}
int n = arr.length;
if (k > n * n) {
return -1;
}
while (count < k) {
count++;
if (arr[lRow][lCol] < arr[rRow][rCol]) {
row = lRow;
col = lCol;
if (lRow < n - 1) {
lRow++;
} else {
if (lCol < n - 1) {
lCol++;
}
if (rRow < n - 1) {
lRow = rRow + 1;
}
}
} else {
row = rRow;
col = rCol;
if (rCol < n - 1) {
rCol++;
} else {
if (rRow < n - 1) {
rRow++;
}
if (lCol < n - 1) {
rCol = lCol + 1;
}
}
}
}
return arr[row][col];
}
This is an interview question. A swap means removing any element from the array and appending it to the back of the same array. Given an array of integers, find the minimum number of swaps needed to sort the array.
Is there a solution better than O(n^2)?
For example:
Input array: [3124].
The number of swaps: 2 ([3124] -> [1243] -> [1234]).
The problem boils down to finding the longest prefix of the sorted array that appears as a subsequence in the input array. This determines the elements that do not need to be sorted. The remaining elements will need to be deleted one by one, from the smallest to the largest, and appended at the back.
In your example, [3, 1, 2, 4], the already-sorted subsequence is [1, 2]. The optimal solution is to delete the remaning two elements, 3 and 4, and append them at the back. Thus the optimal solution is two "swaps".
Finding the subsequence can be done in O(n logn) time using O(n) extra memory. The following pseudo-code will do it (the code also happens to be valid Python):
l = [1, 2, 4, 3, 99, 98, 7]
s = sorted(l)
si = 0
for item in l:
if item == s[si]:
si += 1
print len(l) - si
If, as in your example, the array contains a permutation of integers from 1 to n, the problem can be solved in O(n) time using O(1) memory:
l = [1, 2, 3, 5, 4, 6]
s = 1
for item in l:
if item == s:
s += 1
print len(l) - s + 1
More generally, the second method can be used whenever we know the output array a priori and thus don't need to find it through sorting.
This might work in O(nlogn) even if we don't assume array of consecutive values.
If we do - it can be done in O(n).
One way of doing it is with O(n) space and O(nlogn) time.
Given array A sort it (O(nlogn)) into a second array B.
now... (arrays are indexed from 1)
swaps = 0
b = 1
for a = 1 to len(A)
if A[a] == B[b]
b = b + 1
else
swaps = swaps + 1
Observation: If an element is swapped to the back, its previous position does not matter. No element needs to be swapped more than once.
Observation: The last swap (if any) must move the largest element.
Observation: Before the swap, the array (excluding the last element) must be sorted (by former swaps, or initially)
Sorting algorithm, assuming the values are conecutive: find the longest sorted subsequence of consecutive (by value) elements starting at 1:
3 1 5 2 4
swap all higher elements in turn:
1 5 2 4 3
1 5 2 3 4
1 2 3 4 5
To find the number of swaps in O(n), find the length of the longest sorted subsequence of consecutive elements starting at 1:
expected = 1
for each element in sequence
if element == expected
expected += 1
return expected-1
then the number of swaps = the length of the input - its longest sorted subsequence.
An alternative solution ( O(n^2) ) if the input is not a permutation of 1..n:
swaps = 0
loop
find the first instance of the largest element and detect if the array is sorted
if the array is sorted, return swaps.
else remove the found element from the array and increment swaps.
Yet another solution ( O(n log n) ), assuming unique elements:
wrap each element in {oldPos, newPos, value}
make a shallow copy of the array
sort the array by value
store the new position of each element
run the algorithm for permutations on the newPos' in the (unsorted) copy
If you don't want to copy the input array, sort by oldPos before the last step instead.
This can be done in O(n log n).
First find the minimum element in the array. Now, find the max element that occurs before this element. Call this max_left. You have to call swap()for all the elements before the min element of the array.
Now, find the longest increasing subsequence to the right of the min element, along with the constraint that you should skip elements whose values are greater than max_left.
The required number of swaps is size(array) - size(LIS).
For example consider the array,
7 8 9 1 2 5 11 18
Minimum element in the array is 1. So we find the max before the minimum element.
7 8 9 | 1 2 5 11 18
max_left = 9
Now, find the LIS to the right of min with elements < 9
LIS = 1,2,5
No of swaps = 8 - 3 = 5
In cases where max element is null, ie., min is the first element, find the LIS of the array and required answer is size(array)-size(LIS)
For Example
2 5 4 3
max_left is null. LIS is 2 3
No of swaps = size(array) - size(LIS) = 4 - 2 = 2
Here is the code in python for minimum number of swaps,
def find_cycles(array):
cycles = []
remaining = set(array)
while remaining:
j = i = remaining.pop()
cycle = [i]
while True:
j = array[j]
if j == i:
break
array.append(j)
remaining.remove(j)
cycles.append(cycle)
return cycles
def minimum_swaps(seq):
return sum(len(cycle) - 1 for cycle in find_cycles(seq))
O(1) space and O(N) (~ 2*N) solution assuming min element is 1 and the array contains all numbers from 1 to N-1 without any duplicate value. where N is array length.
int minimumSwaps(int[] a) {
int swaps = 0;
int i = 0;
while(i < a.length) {
int position = a[i] - 1;
if(position != i) {
int temp = a[position];
a[position] = a[i];
a[i] = temp;
swaps++;
} else {
i++;
}
}
return swaps;
}
int numSwaps(int arr[], int length) {
bool sorted = false;
int swaps = 0;
while(!sorted) {
int inversions = 0;
int t1pos,t2pos,t3pos,t4pos = 0;
for (int i = 1;i < length; ++i)
{
if(arr[i] < arr[i-1]){
if(inversions){
tie(t3pos,t4pos) = make_tuple(i-1, i);
}
else tie(t1pos, t2pos) = make_tuple(i-1, i);
inversions++;
}
if(inversions == 2)
break;
}
if(!inversions){
sorted = true;
}
else if(inversions == 1) {
swaps++;
int temp = arr[t2pos];
arr[t2pos] = arr[t1pos];
arr[t1pos] = temp;
}
else{
swaps++;
if(arr[t4pos] < arr[t2pos]){
int temp = arr[t1pos];
arr[t1pos] = arr[t4pos];
arr[t4pos] = temp;
}
else{
int temp = arr[t2pos];
arr[t2pos] = arr[t1pos];
arr[t1pos] = temp;
}
}
}
return swaps;
}
This code returns the minimal number of swaps required to sort an array inplace.
For example, A[] = [7,3,4,1] By swapping 1 and 7, we get [1,3,4,7].
similarly B[] = [1,2,6,4,8,7,9]. We first swap 6 with 4, so, B[] -> [1,2,4,6,8,7,9]. Then 7 with 8. So -> [1,2,4,6,7,8,9]
The algorithm runs in O(number of pairs where value at index i < value at index i-1) ~ O(N) .
Writing a very simple JavaScript program to sort an array and find number of swaps:
function findSwaps(){
let arr = [4, 3, 1, 2];
let swap = 0
var n = arr.length
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
if (arr[i] > arr[j]) {
arr[i] = arr[i] + arr[j];
arr[j] = arr[i] - arr[j];
arr[i] = arr[i] - arr[j]
swap = swap + 1
}
}
}
console.log(arr);
console.log(swap)
}
for(int count = 1; count<=length; count++)
{
tempSwap=0; //it will count swaps per iteration
for(int i=0; i<length-1; i++)
if(a[i]>a[i+1])
{
swap(a[i],a[i+1]);
tempSwap++;
}
if(tempSwap!=0) //check if array is already sorted!
swap += tempSwap;
else
break;
}
System.out.println(swaps);
this is an O(n) solution which works for all inputs:
static int minimumSwaps(int[] arr) {
int swap=0;
boolean visited[]=new boolean[arr.length];
for(int i=0;i<arr.length;i++){
int j=i,cycle=0;
while(!visited[j]){
visited[j]=true;
j=arr[j]-1;
cycle++;
}
if(cycle!=0)
swap+=cycle-1;
}
return swap;
}
}
def minimumSwaps(arr):
swaps = 0
'''
first sort the given array to determine the correct indexes
of its elements
'''
temp = sorted(arr)
# compare unsorted array with the sorted one
for i in range(len(arr)):
'''
if ith element in the given array is not at the correct index
then swap it with the correct index, since we know the correct
index because of sorting.
'''
if arr[i] != temp[i]:
swaps += 1
a = arr[i]
arr[arr.index(temp[i])] = a
arr[i] = temp[i]
return swaps
I think this problem can be solved in O(N) if you notice that an element in the array needs to be removed and appended if:
There is a smaller element to the right or...
There is a smaller element to his left that needs to be removed and appended.
Then it's just about identifying elements that will need to be removed and appended. Here is the code:
static int minMoves(int arr[], int n) {
if (arr.length == 0) return 0;
boolean[] willBeMoved = new boolean[n]; // keep track of elements to be removed and appended
int min = arr[n - 1]; // keep track of the minimum
for (int i = n - 1; i >= 0; i--) { // traverse the array from the right
if (arr[i] < min) min = arr[i]; // found a new min
else if (arr[i] > min) { // arr[i] has a smaller element to the right, so it will need to be moved at some point
willBeMoved[i] = true;
}
}
int minToBeMoved = -1; // keep track of the minimum element to be removed and appended
int result = 0; // the answer
for (int i = 0; i < n; i++) { // traverse the array from the left
if (minToBeMoved == -1 && !willBeMoved[i]) continue; // find the first element to be moved
if (minToBeMoved == -1) minToBeMoved = i;
if (arr[i] > arr[minToBeMoved]) { // because a smaller value will be moved to the end, arr[i] will also have to be moved at some point
willBeMoved[i] = true;
} else if (arr[i] < arr[minToBeMoved] && willBeMoved[i]) { // keep track of the min value to be moved
minToBeMoved = i;
}
if (willBeMoved[i]) result++; // increment
}
return result;
}
It uses O(N) space.
#all , the accepted solution provided by #Itay karo and #NPE is totally wrong because it doesn't consider future ordering of swapped elements...
It fails for many testcases like:
3 1 2 5 4
correct output: 4
but their codes give output as 3...
explanation: 3 1 2 5 4--->1 2 5 4 3--->1 2 4 3 5--->1 2 3 5 4--->1 2 3 4 5
PS:i cann't comment there because of low reputation
Hear is my solution in c# to solve the minimum number of swaps required to short an array
At at time we can swap only 2 elements(at any index position).
public class MinimumSwaps2
{
public static void minimumSwapsMain(int[] arr)
{
Dictionary<int, int> dic = new Dictionary<int, int>();
Dictionary<int, int> reverseDIc = new Dictionary<int, int>();
int temp = 0;
int indx = 0;
//find the maximum number from the array
int maxno = FindMaxNo(arr);
if (maxno == arr.Length)
{
for (int i = 1; i <= arr.Length; i++)
{
dic[i] = arr[indx];
reverseDIc.Add(arr[indx], i);
indx++;
}
}
else
{
for (int i = 1; i <= arr.Length; i++)
{
if (arr.Contains(i))
{
dic[i] = arr[indx];
reverseDIc.Add(arr[indx], i);
indx++;
}
}
}
int counter = FindMinSwaps(dic, reverseDIc, maxno);
}
static int FindMaxNo(int[] arr)
{
int maxNO = 0;
for (int i = 0; i < arr.Length; i++)
{
if (maxNO < arr[i])
{
maxNO = arr[i];
}
}
return maxNO;
}
static int FindMinSwaps(Dictionary<int, int> dic, Dictionary<int, int> reverseDIc, int maxno)
{
int counter = 0;
int temp = 0;
for (int i = 1; i <= maxno; i++)
{
if (dic.ContainsKey(i))
{
if (dic[i] != i)
{
counter++;
var myKey1 = reverseDIc[i];
temp = dic[i];
dic[i] = dic[myKey1];
dic[myKey1] = temp;
reverseDIc[temp] = reverseDIc[i];
reverseDIc[i] = i;
}
}
}
return counter;
}
}
int temp = 0, swaps = 0;
for (int i = 0; i < arr.length;) {
if (arr[i] != i + 1){
// System.out.println("Swapping --"+arr[arr[i] - 1] +" AND -- "+arr[i]);
temp = arr[arr[i] - 1];
arr[arr[i] - 1] = arr[i];
arr[i] = temp;
++swaps;
} else
++i;
// System.out.println("value at position -- "+ i +" is set to -- "+ arr[i]);
}
return swaps;
This is the most optimized answer i have found. It is so simple. You will probably understand in one look through the loop. Thanks to Darryl at hacker rank.