Sort with K Misplaced Elements
// "static void main" must be defined in a public class.
/**
Given a sorted n-size array, there are k elements have been changed i.e. [1, 3, 5, 6, 4, 2, 12] (it might be changed from [1, 3, 5, 6, 7, 8, 12] with k = 2). Important to know is that k is unknown and k is much smaller than n. The task is to re-sort the entire array.
The interviewer wants O(n) solution. I bombed this one. In the end, the interviewer kind of fed the solution to me. What he suggested: a. break the array into two: one sorted array and one unsorted array e.g. [1, 3, 5, 12] and [6, 4, 2]. This takes O(n) b. Sort the unsorted array. This takes O(klogk) c. Merge two sorted arrays. This takes O(n). Because k is very small, so in the end O(n) + O(klogk) ~= O(n).
Does this solution make sense to you ? In O(n) how can we split array into sorted and unsorted with unsorted arry being of size k?
*/
public class Main {
static Pair<List<Integer>, List<Integer>> getMisplacedElement(List<Integer> nums) {
List<Integer> outOfOrder = new ArrayList<>();
List<Integer> inPlace = new ArrayList<>();
inPlace.add(nums.get(0));
for (int i = 1; i < nums.size(); i++) {
if (nums.get(i) < inPlace.get(inPlace.size() - 1)) {
outOfOrder.add(nums.get(i));
} else {
inPlace.add(nums.get(i));
}
}
return new Pair<>(inPlace, outOfOrder);
}
// O(N + k log(k)), k is number of misplaced element
static List<Integer> merge(List<Integer> inPlace, List<Integer> outOfOrder) {
Collections.sort(outOfOrder);
List<Integer> sorted = new ArrayList<>();
int i = 0;
int j = 0;
while (i < inPlace.size() && j < outOfOrder.size()) {
if (inPlace.get(i) < outOfOrder.get(j)) {
sorted.add(inPlace.get(i));
i++;
} else {
sorted.add(outOfOrder.get(j));
j++;
}
}
while (i < inPlace.size()) {
sorted.add(inPlace.get(i));
i++;
}
while (j < outOfOrder.size()) {
sorted.add(outOfOrder.get(j));
j++;
}
return sorted;
}
static void test(List<Integer> nums, List<Integer> expected) {
Pair<List<Integer>, List<Integer>> res = getMisplacedElement(nums);
List<Integer> inPlace = res.getKey();
List<Integer> outOfOrder = res.getValue();
List<Integer> actual = merge(inPlace, outOfOrder);
for (int i = 0; i < expected.size(); i++) {
assert actual.get(i) == expected.get(i);
}
assert actual.toString().equals(expected.toString());
System.out.println(actual.toString());
System.out.println(expected.toString());
}
public static void main(String[] args) {
List<Pair<List<Integer>, List<Integer>>> testCases =
new ArrayList<>();
testCases.add(
new Pair(
Arrays.asList(1, 4, 5, 2, 3, 10, 12),
Arrays.asList(1, 2, 3, 4, 5, 10, 12)));
testCases.add(
new Pair(
Arrays.asList(1, 10, 5, 2, 3, 4, 12),
Arrays.asList(1, 2, 3, 4, 5, 10, 12)));
for (Pair<List<Integer>, List<Integer>> testCase: testCases) {
test(testCase.getKey(), testCase.getValue());
}
}
}
Last updated