Max length increasing super array made by joining two increasing subarray - arrays

Problem:
Given an array, find two increasing subarrays(say a and b) such that when joined they produce one increasing array(say ab). We need to find max possible length of array ab.
For example:
given array = [2 3 1 2 5 4 5]
Two sub arrays are a = [2 3], b = [4, 5] and ab = [2 3 4 5]
Output: length(ab) = 4

I would solve it using brute force. By brute force I can get all the subarrays and then check if it is increasing. Then I can use a merge array and check if there are overlapping elements. If there are overlapping elements will remove them and store the length.
The time complexity for getting all the subarrays will be O(n^2) (I am assuming subarray will maintain the relative order and you do not mean all the subsets). And then will sort the subarrays using a queue and the sorting strategy would be the according to the first element. Then I will check how many can be merged with increasing property(something you use to merge already sorted array).
Then count the strictly increasing arrays after merging.
The other two approaches can be used by dynamic programming(this is same as longest contiguous increasing subarray): (Look here)
First approach:
public int lengthOfLIS(int[] nums) {
if(nums.length == 0) { return 0; }
int[] dp = new int[nums.length];
int len = 0;
for(int n: nums) {
// Find the position of it in binary tree.
int pos = Arrays.binarySearch(dp, 0, len, n);
// Convert the negative position to positive.
if(pos < 0) { pos = -1*(pos + 1); }
// assign the value to n
dp[pos] = n;
// If the length of the dp grows and becomes equal to the current len
// assign the output length to that.
if(pos == len) {
len++;
}
}
// Return the length.
return len;
}
Another method:
public int lengthOfLIS(int[] nums) {
if(nums == null || nums.length == 0) { return 0; }
int n = nums.length;
Integer lis[] = new Integer[n];
int max = 0;
/* Initialize LIS values for all indexes
for ( int i = 0; i < n; i++ ) {
lis[i] = 1;
}
/* Compute optimized LIS values in bottom up manner
for (int i = 1; i < n; i++ ) {
for ( int j = 0; j < i; j++ ) {
if ( nums[i] > nums[j] && lis[i] < lis[j] + 1) {
lis[i] = lis[j] + 1;
}
}
}
max = Collections.max(Arrays.asList(lis));
return max;
}

Idea is of brute force, By brute force I can get all the increasing sub arrays. Then I can use check if there are overlapping elements. If there are overlapping elements will calculate the length after merge and then compare and store the max length.

Related

Finding largest sorted selection

Example: Given [1 2 3 10 7 8 9], I look for an algorithm giving [1 1 1 0 1 1 1].
I have an unsorted array as input. As output I look for a largest sorted selection.
With "selection" I mean an array of the same length holding 1s and 0s (if the elements are selected or not).
With "sorted" I mean that the selected elements make a sorted array - in the above example: [1 2 3 7 8 9].
And with "a largest" I mean that there is no sorted selection that has more 1s in it.
Worst case: I have to try all 2^{0,1} possible selections. Is there a faster algorithm to do that? I dont't remember any from CS study and could not find anything online (at least with my wording).
Yes, This can be solved via Dynamic Programming.
You have to create another array of pair of length equal to the given array let us name it as arr
arr[index] will store the maximum length of the subarray such that givenArray[index] is the last element in sorted order if array is considered from givenArray[0...index] and the element after which givenArray[index] is added.
From arr you can find the maximum length of the sub sorted array and create the array.
for (int i = 0;i<givenArray.size(); i++) {
int after = -1;
int length = 0;
for(int j = 0;j<i;j++) {
if (givenArray[j] < givenArray[i] && length < arr[j].maxLengthTillNow) {
length = arr[j].maxLengthTillNow;
after = j;
}
}
arr[i].maxLengthTillNow = length + 1;
arr[i].after = j;
}
complexity: n*n
Here, I have written a method largestSortedSelection which takes vector of elements as input ( like as [1 2 3 10 7 8 9] ) and returns Boolean vector with true/false representing 1/0 indicating selection of index in answer or not ( like as [1 1 1 0 1 1 1] ).
vector< bool >largestSortedSelection( vector<int>&v ){
int n = v.size();
vector< int >selectedLen(n);
vector< int >sortedList;
int maxLen = 1;
for(int i = 0; i<n; ++i){
int lb = lower_bound(sortedList.begin(),sortedList.end(),v[i])-sortedList.begin();
if( lb!=(int)sortedList.size() ){
selectedLen[i]=lb+1;
sortedList[lb]=v[i];
}
else {
sortedList.push_back(v[i]);
selectedLen[i]=(int)sortedList.size();
}
maxLen = max( maxLen, selectedLen[i] );
}
int lst = INT_MAX;//assuming maximum element will be less than INT_MAX
int len = maxLen+1;
vector< bool >selection(n,0);
for(int i = n-1; i>=0; --i ){
if( v[i]<lst && selectedLen[i]+1 == len ){
selection[i] = 1;
lst = v[i];
len--;
}
}
return selection;
}
In this method:
selectedLen(i) : longest length of sorted list ending upto index- i.
sortedList : holds the elements in sorted increasing form.
selection : holds the answer in the form of 0/1
lower_bound function in sortedList: returns first element that is greater-or-equal.
Let me know if you feel difficulty in understanding source code.
As I have used lower_bound function ( which is of complexity logN ) N times in a loop. So, overall time complexity is : O( N logN ).
Memory complexity will be O(N) as I am using memory for holding N elements.
Thanks for everybodies help. This is the C++ implementation of the Wikipedia pseudocode I ended up with:
/// Return indice of the a longest increasing subsequence.
/// implementation of https://en.wikipedia.org/wiki/Longest_increasing_subsequence
template<class T>
std::vector<size_t> indiceOfLongesIncreasingSubsequence(const std::vector<T>& v)
{
std::vector<size_t> P(v.size()), M(v.size() + 1);
size_t L = 0;
for(size_t i = 0; i < v.size(); ++i)
{
// binary search for the largest positive j <= L such that v[M[j]] < v[i]
size_t lo = 1, hi = L;
while(lo <= hi)
{
size_t mid = (lo + hi)/2;
if(v[M[mid]] < v[i])
lo = mid+1;
else
hi = mid-1;
}
// predecessor of v[i] is the last index of the subsequence of length lo-1
P[i] = M[lo-1];
M[lo] = i;
if(lo > L)
L = lo;
}
// reconstruct the longest increasing subsequence
std::vector<size_t> ind(L);
size_t k = M[L];
for(size_t i = 0; i < L; ++i)
{
ind[L-1-i] = k;
k = P[k];
}
return ind;
}
To get the true/false vector, one needs to:
vector<bool> selection(ind.size(), false);
for(size_t i: ind)
selection[i] = true;

Most frequent element in an array

Given all numbers are in the range 0 to n-1 where n is the length of the array.
How to solve this in linear time and constant space?
You can reuse given array as a counter for numbers. Just iterate through the array and increment corresponding counter. The only trick is to increment each time by n, not by one:
for (int i = 0; i < n; ++i) {
arr[arr[i]%n] += n;
}
After this loop element arr[i] will be changed to arr[i]+n*count[i], where arr[i]<n. So this way the most frequent element is the one with the greatest value. In order to restore the original value, just take arr[i]%n.
Here is a function to achieve this. But it is not O(n) as you required, it is O(n^2). Hope this help
function getPopularElement(array) {
var count = 1, tempCount;
var popular = array[0];
var temp = 0;
for (var i = 0; i < (array.length - 1); i++) {
temp = array[i];
tempCount = 0;
for (var j = 1; j < array.length; j++) {
if (temp == array[j]) {
tempCount++;
}
}
if (tempCount > count) {
popular = temp;
count = tempCount;
}
}
return popular;
}
Heller's solution is actually similar to this: the idea is to go through the array and for each element increase a counter at that number's position in the array. Generally there's another element at that position (where Heller is keeping the information by counting in step sizes of n) but we can resolve those elements recursively and in-place. This is a linear process done at most once per element, since there can be no longer chains (trying to increase a count at a position, finding a new element) than the length of the whole array (i.e. a single permutation cycle) and once an element is processed, it can be skipped in the main loop making it O(n) overall. The trick is to decrease the counter:
//input: arr
//output: most frequent element, number of occurrences
n <- arr.length
for i = 0..n-1
val <- arr[i]
if val < 0
// this element has already been processed
continue
// set counter at i to zero (-1)
arr[i] <- -1
// resolve the chain
do
idx <- val
val <- arr[idx]
if val < 0
// arrived at a counter, end of chain
// increase the counter by one (-1)
arr[idx] <- arr[idx] - 1
break
}
// otherwise continue the chain with val
// and initialise the counter at idx to one (-2)
arr[idx] <- -2
// find the most common element
idx <- 0
for i = 1..n-1
// smaller value means larger counter
if arr[i] < arr[idx]
idx <- i
// [the most frequent element, number of occurrences]
output [idx, -(arr[idx] + 1)] // arr[i] = -1 - #occurrences
This solution also deals nicely with very large arrays where the biggest possible counter in Heller's solution (n*n-1) overflows the underlying integer (for 32bit integers that's arrays longer than 65535 elements!)
Lets suppose the array is as follows:
int arr[] = {10, 20, 10, 20, 30, 20, 20,40,40,50,15,15,15};
int max =0;
int result = 0;
Map<Integer,Integer> map = new HashMap<>();
for (int i = 0; i < arr.length; i++) {
if ( map.containsKey(arr[i]))
map.put(arr[i], map.get(arr[i]) +1);
else
map.put(arr[i], 1);
int key = map.keySet().iterator().next();
if (map.get(key) > max) {
max = map.get(key) ;
result = key;
}
}
System.out.println(result);
Explanation :
In the above code I have taken HashMap to store the elements in keys and the repetition of the elements as values.
We have initialized variable max = 0 ( max is the maximum count of repeated element)
While iterating over elements We are also getting the max count of keys.
The result variable returns the keys with the mostly repeated.

Rearrange an array so that arr[i] becomes arr[arr[i]] with O(1) extra space

The task is to rearrange an array so that arr[i] becomes arr[arr[i]] with O(1) extra space.
Example:
2 1 3 5 4 0
becomes:
3 1 5 0 4 2
I can think of an O(n²) solution. An O(n) solution was presented here:
Increase every array element arr[i] by (arr[arr[i]] % n)*n.
Divide every element by n.
But this is very limited as it will cause buffer overflow.
Can anyone come up with an improvement upon this?
If the values in the array are all positive (or all negative), one way to avoid overflow could be to run the permutation cycles and use the integer sign to mark visited indexes. (Alternatively, if the array length is smaller than 2^(number of bits for one array element - 1), rather than use the sign, we could shift all the values one bit to the left and use the first bit to mark visited indexes.) This algorithm results in both less iterations and less modifications of the original array values during run-time than the algorithm you are asking to improve.
JSFiddle: http://jsfiddle.net/alhambra1/ar6X6/
JavaScript code:
function rearrange(arr){
var visited = 0,tmp,indexes,zeroTo
function cycle(startIx){
tmp = {start: startIx, value: arr[startIx]}
indexes = {from: arr[startIx], to: startIx}
while (indexes.from != tmp.start){
if (arr[indexes.from] == 0)
zeroTo = indexes.to
if (indexes.to == visited){
visited++
arr[indexes.to] = arr[indexes.from]
} else {
arr[indexes.to] = -arr[indexes.from]
}
indexes.to = indexes.from
if (indexes.from != tmp.start)
indexes.from = arr[indexes.from]
}
if (indexes.to == visited){
visited++
arr[indexes.to] = tmp.value
} else {
arr[indexes.to] = -tmp.value
}
}
while (visited < arr.length - 1){
cycle(visited)
while (arr[visited] < 0 || visited == zeroTo){
arr[visited] = -arr[visited]
visited++
}
}
return arr
}
//Traverse the array till the end.
//For every index increment the element by array[array[index] % n]. To get //the ith element find the modulo with n, i.e array[index]%n.
//Again traverse to end
//Print the ith element after dividing the ith element by n, i.e. array[i]/n
class Rearrange
{
void rearrange(int arr[], int n)
{
for (int i = 0; i < n; i++)
arr[i] += (arr[arr[i]] % n) * n;
for (int i = 0; i < n; i++)
arr[i] /= n;
}
void printArr(int arr[], int n)
{
for (int i = 0; i < n; i++)
System.out.print(arr[i] + " ");
System.out.println("");
}
public static void main(String[] args)
{
Rearrange rearrange = new Rearrange();
int arr[] = {6, 4, 9, 2, 5, 7};
int n = arr.length;
System.out.println("Given Array is :");
rearrange.printArr(arr, n);
rearrange.rearrange(arr, n);
System.out.println("Modified Array is :");
rearrange.printArr(arr, n);
}
}

Kth smallest element in sorted matrix

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];
}

Find the number of remove-then-append operations needed to sort a given array

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.

Resources