1. QUESTION: Given an int array which might contain duplicates, find the largest subset of it which form a sequence.
Eg. {1,6,10,4,7,9,5}
then ans is 4,5,6,7
answer
1. Create an array 'TempArray' of O(max(Array)) initialized with 0's
2. Pass through the 'Array' and element 'i' set TempArray[Array[i]] = 1
3. Pass through the 'Array' again and for each element 'i' check if neighbours are set
import java.util.Arrays;
public class MaxSequence {
public static void switchElement(int[] input, int x, int y) {
int z = input[x];
input[x] = input[y];
input[y] = z;
}
public static void search(int[] input) {
int size = input.length;
if (size == 0)
return;
int max = input[0];
int min = input[0];
// search the min and max elements
for (int i = 0; i < input.length; i++) {
if (input[i] > max) {
max = input[i];
}
if (input[i] < min) {
min = input[i];
}
}
int[] bitmap = new int[max - min + 1];
for (int i = 0; i < bitmap.length; i++) {
bitmap[i] = 0;
}
for (int i : input) {
bitmap[i-min] = 1;
}
System.out.println(Arrays.toString(bitmap));
int maxStart = 0, maxLength = 0, start = -1, length=0;
for (int i = 0; i < bitmap.length; i++) {
if (bitmap[i] == 1) {
if (start == -1) {
start = i;
length = 1;
} else {
length++;
}
if (length > maxLength) {
maxStart = start;
maxLength = length;
}
} else if (start != -1) {
start = -1;
}
}
for(int i=0; i<maxLength; i++) {
if(i!=0) {
System.out.print(",");
}
System.out.print(i+maxStart+min);
}
System.out.println();
}
public static void main(String[] args) {
int[] input = {1,6,10,4,7,9,5 };
search(input);
}
}
2. QUESTION: Given an int array which might contain duplicates, find if it is a sequence.
Eg. {45,50,47,46,49,48}
is a sequence 45, 46,47,48,49,50
answer:
1) find min and max
2) set the min value at position 0, max to the last, others follow the pattern
3) check if there is a[i]==a[a[i]-min], if exists, then not
import java.util.Arrays;
public class SequenceIdentify {
public static void switchElement(int[] input, int x, int y) {
int z = input[x];
input[x] = input[y];
input[y] = z;
}
public static boolean identify(int[] a) {
int size = a.length;
if (size == 0)
return false;
int max = a[0];
int min = a[0];
// search the min and max elements
for (int i = 0; i < a.length; i++) {
if (a[i] > max) {
max = a[i];
}
if (a[i] < min) {
min = a[i];
}
}
//check if the count of array is correct
if(size!=max-min+1)
return false;
for (int i = 0; i < size; ) {
if(a[i]==min+i) {
//the element is in placed already
i++;
} else {
if(a[i]==a[a[i]-min]){
//the element is duplicated
return false;
} else {
switchElement(a, i, a[i]-min);
}
}
}
return true;
}
public static void main(String[] args) {
int[] input = {45,50,47,46,49,48};
System.out.println("Is sequence: " + identify(input));
}
}
QUESTION: You are given an unsorted array with both positive and negative elements. You have to find the smallest positive number missing from the array in O(n) time using constant extra space.
Eg:
Input = {2, 3, 7, 6, 8, -1, -10, 15}
Output = 1
Input = { 2, 3, -7, 6, 8, 1, -10, 15 }
Output = 4
ANSWER(1): Inefficient Solution
1) Go through the array once and map everything to a hash table. Also keep track of the largest positive vale you find - O(n)
2) Start a second loop from 0 or 1 (depending on your definition of smallest positive integer). - O(n)
3) In every iteration, check if value exists in hash table. If it does not, that is your value
Total time: O(n) runtime, O(n) space.
ANSWER(2): Solution
Instead of using the hash table, you can shift the wrong values towards the end of the array and decrease end.
eg: int[] a = {12, 2, 1, -5, 6, 18}
Keep a pointer at the start and another at the end of the array.
a[0] = 12 and 12 > a.length() so swap 12 with a[end] and do end--
so my a[] becomes {18, 2, 1, -5, 6}
similarly, 18 is also out of bounds so I repeat and a[] = {6, 2, 1, -5} and then {-5, 2, 1} and then {2, 1}
Now, in this step we see a[start] <= end so what I do is swap a[start] with a[a[start]]
Thus, a[] = {1, 2}
lastly, I have to loop only till whenever a[start] = a[a[start]], in this case till 3 (which is our answer).
Total time: O(n) runtime, O(1) space.
QUESTION:Given an Array With random 0s and non 0 numbers, shift all the 0s to the beginning and non 0s to the rear.
Eg: 1,9,8,4,0,0,2,7,0,6,0
Out put 0,0,0,0,1,9,8,4,2,7,6
i.e order of numbers not to change. Do it in place
answer: scan from the end then replace 0 with next non-zero
import java.util.Arrays;
public class ArrangeTwoArrays {
public static void exchange(int[] a, int i, int j) {
a[i] = a[i] ^ a[j];
a[j] = a[i] ^ a[j];
a[i] = a[i] ^ a[j];
}
public static void arrange(int[] a) {
// point to the last zero
int i = -1;
for (int j = a.length - 1; j >= 0; j--) {
if (a[j] == 0) {
if (i == -1) {
i = j;
}
} else if (i != -1) {
exchange(a, i--, j);
}
}
}
public static void main(String[] args) {
int[] a = new int[] { 1, 9, 8, 4, 0, 0, 2, 7, 0, 6, 0 };
System.out.println(Arrays.toString(a));
arrange(a);
System.out.println(Arrays.toString(a));
}
}