merge sort in k parts - java

I'd really appreciate some help on this assignment.
The task is develop a merge sort algorithm that "splits" the input array recursively into k arrays. I initially coded two methods to merge sort with two parts, namely merge sort and merge. I tried to generalize this algorithm
public class MergeSort {
public static int[] mergeSort(int[] a, int p, int r) {
// p is left bound
// r is right bound
if (p < r) {
int q = (int)Math.floor((p + r) / 2);
mergeSort(a, p, q);
mergeSort(a, q + 1, r);
return merge(a, p, q, r);
} else
return a;
}
// p ist linke grenze
// r ist rechte grenze
public static int[] merge(int[] a, int p, int q, int r) {
int n1 = q - p + 1; //length of first array
int n2 = r - q; //length of second array
int[] lt = new int[n1 + 1];
int[] rt = new int[n2 + 1];
for (int i = 0; i < n1; i++) {
lt[i] = a[p + i];
}
for (int j = 0; j < n2; j++) {
rt[j] = a[q + j + 1];
}
lt[n1] = 1000000000; //sentinels
rt[n2] = 1000000000;
int i = 0;
int j = 0;
for (int k = p; k <= r; k++) { //comparing the values of the arrays and merging
if (lt[i] <= rt[j]) {
a[k] = lt[i];
i++;
} else {
a[k] = rt[j];
j++;
}
}
return a;
}
public static int[] mergeSortK(int[] a, int k, int p, int r) {
// k number of steps; p is first index of array; r is last index of array;
if (p < r) {
int[] pos = new int[k + 1]; //array for saving the indices of the "splits"
for (int i = 0; i <= k; i++) {
pos[i] = (int) Math.floor(p + (r - p) / k * i); //saving the array indices
}
for (int i = 0; i < k; i++) {
mergeSortK(a, k, pos[i], pos[i + 1]); //sorting the arrays
}
for (int i = 0; i < k - 1; i++) {
merge(a, pos[i], pos[i + 1], pos[i + 2]); //merging the arrays pairwise
}
}
return a;
}
public static void main(String[] args) {
// task 2.1.a)
// Example Values:
int[] list = { 2, 1, 5, 6, 2, 12 };
int k = 4;
// use MergeSort
int[] newlist = mergeSortK(list, k, 0, list.length);
printList(newlist);
}
// Helper function to print the elements of a list
private static void printList(int[] list) {
for(int i = 0; i < list.length; i++) {
System.out.println(list[i]);
}
}
}
The input given in the main method results in {2, 1, 2, 5, 6, 12}
Any help is immensely appreciated! Sorry if I'm doing some mistakes, I'm here to learn and I really hope you guys can help me out!

There are a few problems in your code:
there is no need for Math.floor() to truncate the results of integer division, unlike Javascript, Java uses different semantics for / for int arguments and floating point arguments. (p + r) / 2 is the integral quotient, But you might want to write p + (r - p) / 2 to avoid potential overflow on p + r.
the upper index is excluded as you pass list.length from main(). This is actually a very convenient convention to avoid the need for +1 adjustments when computing slice sizes. Remove those erroneous adjustments and rely on the included/excluded convention.
don't use sentinels: using sentinels prevents you from correctly sorting arrays containing values greater or equal to the sentinel value 1000000000. This approach is not necessary and should be banned. Just compare the index variables to the slice lengths and copy the remaining elements when one of the slices is exhausted.
your computation for the slice boundaries in mergeSortK is incorrect: p + (r - p) / k * i is computed with integer arithmetics so (r - p) / k is rounded before the multiplication. The last slice ending index will not equal r if r - p is not a multiple of k. Multiplying before the division would solve this issue but might overflow the range of type int.
mergeSortK does not perform k-way merging, but a series of partial merges that are insufficient for k > 2.
your test set is a bit small.
Here is a corrected version:
public class MergeSort {
public static int[] mergeSort(int[] a, int p, int r) {
// p is left bound (included)
// r is right bound (excluded)
if (r - p >= 2) {
int q = p - (r - p) / 2;
mergeSort(a, p, q);
mergeSort(a, q, r);
return merge(a, p, q, r);
} else {
return a;
}
}
// p is left bound (included)
// q is start of right slice
// r is end of right slice (excluded)
public static int[] merge(int[] a, int p, int q, int r) {
int n1 = q - p; // length of first array
int n2 = r - q; // length of second array
int[] lt = new int[n1];
for (int i = 0; i < n1; i++) {
lt[i] = a[p + i];
}
int i = 0; // index into lt
int j = q; // index into a for right slice
int k = p; // index into a for merged list
while (i < n1 && j < r) { //comparing the values of the arrays and merging
if (lt[i] <= a[j]) {
a[k] = lt[i];
i++;
k++;
} else {
a[k] = a[j];
j++;
k++;
}
}
while (i < n1) { // copy remaining elements from right slice
a[k] = lt[i];
i++;
k++;
}
// remaining elements from right slice are already in place
return a;
}
public static int[] mergeSortK(int[] a, int k, int p, int r) {
// k amount of steps; p is first index of slice; r is last index of slice (excluded);
if (r - p >= 2) {
if (k > r - p)
k = r - p;
int[] pos = new int[k + 1]; //array for saving the indices of the "splits"
for (int i = 0; i <= k; i++) {
pos[i] = p + (r - p) * i / k; //saving the array indices
}
for (int i = 0; i < k; i++) {
mergeSortK(a, k, pos[i], pos[i + 1]); //sorting the arrays
}
while (k > 1) {
int i, n = 1;
for (i = 0; i < k - 1; i += 2) {
// merge slices 2 at a time: this will produce the expected output
// but is not a direct k-way merge.
merge(a, pos[i], pos[i + 1], pos[i + 2]);
pos[n++] = pos[i + 2];
}
if (i < k)
pos[n++] = pos[i + 1];
k = n - 1;
}
}
return a;
}
public static void main(String[] args) {
// task 2.1.a)
// Example Values:
int[] list = {
64, 36, 46, 31, 45, 52, 4, 48, 74, 59,
12, 16, 70, 67, 71, 26, 73, 34, 46, 84,
60, 16, 26, 68, 56, 57, 97, 6, 39, 74,
25, 69, 29, 69, 77, 26, 44, 53, 20, 6,
77, 31, 71, 91, 28, 6, 24, 75, 26, 33,
3, 20, 55, 94, 17, 81, 88, 32, 94, 32,
3, 90, 76, 69, 9, 96, 76, 53, 78, 14,
97, 32, 17, 15, 61, 63, 21, 0, 16, 14,
61, 4, 81, 86, 29, 29, 27, 57, 85, 5,
91, 54, 6, 68, 40, 88, 41, 9, 90, 51 };
int k = 4; // must be at least 2
// use MergeSort
int[] newlist = mergeSortK(list, k, 0, list.length);
printList(newlist);
}
// Helper function to print the elements of a list
private static void printList(int[] list) {
for (int i = 0; i < list.length; i++) {
System.out.println(list[i]);
}
}
}
I did not write a correct k-way merging phase at the end of mergeSortK, the code above should work but will merge the k slices in ceil(log2(k)) passes. Direct one pass k-way merging is tricky and usually not worth it.

Related

Print only the numbers, which have been changed

I got curious about a Merge-sorting code.
Description:
This code creates two auxillary arrays left and right and store alternate array elements in them and then copying all elements of left and right subarrays back to original array and printing them. So instead of printing back to the original array, how would it be possible to only print the moved numbers?
class Project {
static void join(int arr[], int left[], int right[],int l, int m, int r){
int i;
for (i = 0; i <= m - l; i++)
arr[i] = left[i];
for (int j = 0; j < r - m; j++)
arr[i + j] = right[j];
}
static void split(int arr[], int left[], int right[],int l, int m, int r) {
for (int i = 0; i <= m - l; i++)
left[i] = arr[i * 2];
for (int i = 0; i < r - m; i++)
right[i] = arr[i * 2 + 1];
}
static void generateWorstCase(int arr[], int l, int r) {
if (l < r) {
int m = l + (r - l) / 2;
int[] left = new int[m - l + 1];
int[] right = new int[r - m];
split(arr, left, right, l, m, r);
generateWorstCase(left, l, m);
generateWorstCase(right, m + 1, r);
join(arr, left, right, l, m, r);
}
}
public static void main (String[] args) {
int arr[] = { 10, 11, 12, 13, 14, 15, 16 };
int n = arr.length;
System.out.println("Sorted array is");
System.out.println(Arrays.toString(arr));
generateWorstCase(arr, 0, n - 1);
System.out.println("\nInput array that will result in worst case of merge sort is: \n");
System.out.println(Arrays.toString(arr));
}
}
Here's the output:
System.out.println(Arrays.toString(arr));
My question is..
I would ask, can you, based on the code, only have the output as, like the numbers being moved, and not the entire array?
Example:
The input is:
{ 10 20 30 40 50 }
The output is:
{ 10 50 30 20 40 }
My Desired Output:
{ 50 20 40 }
(The number of inputs varies according to the number of output)..
How would this happen?
Do it as follows:
public static void main(String[] args) {
int arr[] = { 10, 11, 12, 13, 14, 15, 16 };
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < arr.length; i++) {
map.put(arr[i], i);
}
int n = arr.length;
System.out.println("Sorted array is");
System.out.println(Arrays.toString(arr));
generateWorstCase(arr, 0, n - 1);
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < arr.length; i++) {
if (map.get(arr[i]) != i) {
list.add(arr[i]);
}
}
System.out.println("\nInput array that will result in worst case of merge sort is: \n" + list);
}
Output:
Sorted array is
[10, 11, 12, 13, 14, 15, 16]
Input array that will result in worst case of merge sort is:
[14, 16, 11, 13]
Another solution:
public static void main(String[] args) {
int arr[] = { 10, 11, 12, 13, 14, 15, 16 };
int[] original = Arrays.copyOf(arr, arr.length);
int n = arr.length;
System.out.println("Sorted array is");
System.out.println(Arrays.toString(arr));
generateWorstCase(arr, 0, n - 1);
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < arr.length; i++) {
if (original[i] != arr[i]) {
list.add(arr[i]);
}
}
System.out.println("\nInput array that will result in worst case of merge sort is: \n" + list);
}
Output:
Sorted array is
[10, 11, 12, 13, 14, 15, 16]
Input array that will result in worst case of merge sort is:
[14, 16, 11, 13]
[Update]
You have requested to change the format of the output so that the numbers are not bounded by []. Note that this is how Arrays.toString or List::toString returns the string. If you do not want an array or a List, you can do it simply as:
public static void main(String[] args) {
int arr[] = { 10, 11, 12, 13, 14, 15, 16 };
int[] original = Arrays.copyOf(arr, arr.length);
int n = arr.length;
System.out.println("Sorted array is");
System.out.println(Arrays.toString(arr));
generateWorstCase(arr, 0, n - 1);
StringBuilder s = new StringBuilder();
int i;
for (i = 0; i < arr.length; i++) {
if (original[i] != arr[i]) {
s.append(arr[i]).append(", ");
}
}
String output = s.substring(0, s.lastIndexOf(","));
System.out.println("\nInput array that will result in worst case of merge sort is: \n" + output);
}
Output:
Sorted array is
[10, 11, 12, 13, 14, 15, 16]
Input array that will result in worst case of merge sort is:
14, 16, 11, 13
If you want to change the format of the output while keeping the List, you can do it as follows:
public static void main(String[] args) {
int arr[] = { 10, 11, 12, 13, 14, 15, 16 };
int[] original = Arrays.copyOf(arr, arr.length);
int n = arr.length;
System.out.println("Sorted array is");
System.out.println(Arrays.toString(arr));
generateWorstCase(arr, 0, n - 1);
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < arr.length; i++) {
if (original[i] != arr[i]) {
list.add(arr[i]);
}
}
System.out.println("\nInput array that will result in worst case of merge sort is: \n"
+ list.toString().replace("[", "").replace("]", ""));
}
Output:
Sorted array is
[10, 11, 12, 13, 14, 15, 16]
Input array that will result in worst case of merge sort is:
14, 16, 11, 13
Iterate over both arrays simultaneously. If input[i] is not equal to output[i] then it has been moved.
List<Integer> moved = new ArrayList<>();
for (int i = 0; i < input.length; i++) {
if (input[i] != output[i]) {
moved.add(input[i]);
}
}

MergeSort index

I made a mergesort algorithm in java. It works, but it I don't know why.
Here's the problem:
for(int k = 0; k < r; k++)
If i write the for loop like that, the code will not work. However, if I change the 0 to "p-1", it will. The value of p is 1, which means that p-1 is 0. Why does p-1 work when 0 doesn't?
Here's the rest of my code:
public class MergeSort {
public static void main(String args[]){
Random rand = new Random();
int[] array = new int[10];
for(int i = 0; i <array.length; i++){
array[i] = rand.nextInt(11);
}
System.out.println(Arrays.toString(array));
mergeSort(array, 1, array.length);
System.out.println(Arrays.toString(array));
}
public static void merge(int[] A, int p, int q, int r){
//
//length of subarray 1
int n1 = q-p+1;
//length of subarray 2
int n2 = r-q;
int[] L = new int[n1+1];
int[] R = new int[n2+1];
for(int i = 0; i < n1; i++){
L[i] = A[p+i-1];
}
for(int j=0; j< n2; j++){
R[j] = A[q+j];
}
L[n1] = Integer.MAX_VALUE;
R[n2] = Integer.MAX_VALUE;
int i = 0;
int j = 0;
for(int k = p-1; k < r; k++){
if(L[i] <= R[j]){
A[k] = L[i];
i++;
}
else{
A[k] = R[j];
j++;
}
}
}
public static void mergeSort(int[] A, int p, int r){
if (p<r){
int q = (int) Math.floor((r+p)/2);
mergeSort(A, p, q);
mergeSort(A, q+1, r);
merge(A, p, q, r);
}
}
Consider the following example
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
and the code that you have provided
public static void mergeSort(int[] A, int p, int r){
if (p<r){
int q = (int) Math.floor((r+p)/2);
mergeSort(A, p, q);
mergeSort(A, q+1, r);
merge(A, p, q, r);
}
}
Your list is partitioned into left and right sections each with different indices.
Therefore, in this particular example, you will get
mergeSort(A, 1, 5)
mergeSort(A, 6, 10)
For the first method call, it will be processing [1, 2, 3, 4, 5, 6, 7, 8, 9]
while the second method call, it will be processing [1, 2, 3, 4, 5, 6, 7, 8, 9]
These operations are performed on the same array. In the subsequent call of merge Sort in mergeSort(A, 6, 9)
you will get
mergeSort(A, 6, 7)
mergeSort(A, 8, 9)
You can see that your indices clearly doesn't start from 0. Therefore processing it from 0 will give you the wrong result.
Here is a nice resource for you to learn about merge sort developed by the University that I am currently studying in.
visualgo-sorting

MergeSort java Graphical representation

Hi I have got merge Sort class I want to plot histogram of sorting array and when try to retrieve data from sorting class on screen appearing only unsorted array and then sorted array. How I have to restructure my sorting class so the full array will be returned on every occurrence of sorting or how I can retrieve merge(array, left, right) (I think this is the part I have to use to create histogram)
package mergeSort;
import java.util.*;
public class MergeSort {
public static void main(String[] args) {
int[] list = {14, 32, 67, 76, 23, 41, 58, 85};
System.out.println("before: " + Arrays.toString(list));
mergeSort(list);
System.out.println("after: " + Arrays.toString(list));
}
public static void mergeSort(int[] array) {
if (array.length > 1) {
// split array into two halves
int[] left = leftHalf(array);
int[] right = rightHalf(array);
// recursively sort the two halves
mergeSort(left);
mergeSort(right);
// merge the sorted halves into a sorted whole
merge(array, left, right);
}
}
// Returns the first half of the given array.
public static int[] leftHalf(int[] array) {
int size1 = array.length / 2;
int[] left = new int[size1];
for (int i = 0; i < size1; i++) {
left[i] = array[i];
}
return left;
}
// Returns the second half of the given array.
public static int[] rightHalf(int[] array) {
int size1 = array.length / 2;
int size2 = array.length - size1;
int[] right = new int[size2];
for (int i = 0; i < size2; i++) {
right[i] = array[i + size1];
}
return right;
}
public static void merge(int[] result, int[] left, int[] right) {
int i1 = 0; // index into left array
int i2 = 0; // index into right array
for (int i = 0; i < result.length; i++) {
if (i2 >= right.length || (i1 < left.length &&
left[i1] <= right[i2])) {
result[i] = left[i1]; // take from left
i1++;
} else {
result[i] = right[i2]; // take from right
i2++;
}
}
}
}
Also when I call for example bubble sort everything working fine so I think I must restructure the mergeClass
Please share if you have an idea thank you
This is my printing method
int Value = 100;
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int edge= 50;
for (int i = 0; i < array.length; i++) {
g.drawLine(i + offSet, Value + edge, i + edge,
Value + edge- array[i]);
}
}
Bubble sort
public void bubbleSort(int[] a) throws InterruptedException {
for (int i = 0; i < a.length; i++) {
for (int j = 1; j < (a.length - i); j++) {
if (a[j - 1] > a[j])
swap(a, j - 1, j);
}
}
}
Would keeping a record of each step (rather than returning it each step) suffice? If so the following would give you a List of int[] arrays, each storing the value at each step of the sorting process. You could then iterate over the list and display it at your leisure.
The following:
package mergeSort;
import java.util.*;
public class MergeSort {
public static void main(String[] args) {
int[] list = {14, 32, 67, 76, 23, 41, 58, 85};
List<int[]> listOfLists = new ArrayList<int[]>();
System.out.println("before: " + Arrays.toString(list));
mergeSort(list,listOfLists);
System.out.println("after: " + Arrays.toString(list));
System.out.println("Each step:");
for(int[] arrList : listOfLists)
System.out.println(Arrays.toString(arrList));
}
public static void mergeSort(int[] array, List<int[]> listOfLists) {
if (array.length > 1) {
// split array into two halves
int[] left = leftHalf(array);
int[] right = rightHalf(array);
// recursively sort the two halves
mergeSort(left,listOfLists);
mergeSort(right,listOfLists);
// merge the sorted halves into a sorted whole
merge(array, left, right);
listOfLists.add(array);
}
}
// Returns the first half of the given array.
public static int[] leftHalf(int[] array) {
int size1 = array.length / 2;
int[] left = new int[size1];
for (int i = 0; i < size1; i++) {
left[i] = array[i];
}
return left;
}
// Returns the second half of the given array.
public static int[] rightHalf(int[] array) {
int size1 = array.length / 2;
int size2 = array.length - size1;
int[] right = new int[size2];
for (int i = 0; i < size2; i++) {
right[i] = array[i + size1];
}
return right;
}
public static void merge(int[] result, int[] left, int[] right) {
int i1 = 0; // index into left array
int i2 = 0; // index into right array
for (int i = 0; i < result.length; i++) {
if (i2 >= right.length || (i1 < left.length &&
left[i1] <= right[i2])) {
result[i] = left[i1]; // take from left
i1++;
} else {
result[i] = right[i2]; // take from right
i2++;
}
}
}
}
Would return this:
before: [14, 32, 67, 76, 23, 41, 58, 85]
after: [14, 23, 32, 41, 58, 67, 76, 85]
Each step:
[14, 32]
[67, 76]
[14, 32, 67, 76]
[23, 41]
[58, 85]
[23, 41, 58, 85]
[14, 23, 32, 41, 58, 67, 76, 85]
Ok, I think I understand the problem you have. Does this work for you? Where I've put the println statement you can instead render the current array.
package mergeSort;
import java.util.Arrays;
public class MergeSort {
public static void main(String[] args) {
int[] list = { 14, 32, 76, 67, 41, 23, 58, 85 };
System.out.println("before: " + Arrays.toString(list));
mergeSort(list, 0, list.length - 1);
System.out.println("after: " + Arrays.toString(list));
}
public static void mergeSort(int[] array, int left, int right) {
int mid = 0;
if (right > left) {
mid = (right + left) / 2;
// sort left
mergeSort(array, left, mid);
// sort right
mergeSort(array, mid + 1, right);
// merge them
merge(array, left, mid+1, right);
// PUT YOUR HOOK TO DRAW THE ARRAY HERE
System.out.println("during: " + Arrays.toString(array));
}
}
public static void merge(int[] numbers, int left, int mid, int right) {
int[] temp = new int[numbers.length];
int i, left_end, num_elements, tmp_pos;
left_end = (mid - 1);
tmp_pos = left;
num_elements = (right - left + 1);
while ((left <= left_end) && (mid <= right)) {
if (numbers[left] <= numbers[mid])
temp[tmp_pos++] = numbers[left++];
else
temp[tmp_pos++] = numbers[mid++];
}
while (left <= left_end)
temp[tmp_pos++] = numbers[left++];
while (mid <= right)
temp[tmp_pos++] = numbers[mid++];
for (i = 0; i < num_elements; i++){
numbers[right] = temp[right];
right--;
}
}
}
The output that is produced is this:
before: [14, 32, 76, 67, 41, 23, 58, 85]
during: [14, 32, 76, 67, 41, 23, 58, 85]
during: [14, 32, 67, 76, 41, 23, 58, 85]
during: [14, 32, 67, 76, 41, 23, 58, 85]
during: [14, 32, 67, 76, 23, 41, 58, 85]
during: [14, 32, 67, 76, 23, 41, 58, 85]
during: [14, 32, 67, 76, 23, 41, 58, 85]
during: [14, 23, 32, 41, 58, 67, 76, 85]
after: [14, 23, 32, 41, 58, 67, 76, 85]

Optimize code for Nth largest element in sorted matrix

I have a code for nth largest element in a sorted matrix (sorted row and column wise increasing order)
I had some problem doing the (findNextElement) part in the code
i.e if the row is exhausted, then go up one row and get the next element in that.
I have managed to do that, but the code looks kind of complex. (My code does work and produces the output correctly) I will post my code here
k is the Kth largest element
m, n are matrix dimensions (right now it just supports NxN matrix but can be modified to support MxN)
public int findkthLargestElement(int[][] input, int k, int m, int n) {
if (m <=1 || n <= 1 || k > m * n) {
return Integer.MIN_VALUE;
}
int i = 0;
int j = 0;
if (k < m && k < n) {
i = m - k;
j = n - k;
}
PriorityQueue<Element> maxQueue = new PriorityQueue(m, new Comparator<Element>() {
#Override
public int compare(Element a, Element b) {
return b.value - a.value;
}
});
Map<Integer, Integer> colMap = new HashMap<Integer, Integer>();
for (int row = i; row < m; row++) {
Element e = new Element(input[row][n - 1], row, n - 1);
colMap.put(row, n - 1);
maxQueue.add(e);
}
Element largest = new Element(0, 0, 0);
for (int l = 0; l < k; l++) {
largest = maxQueue.poll();
int row = largest.row;
colMap.put(row, colMap.get(row) - 1);
int col = colMap.get(row);
while (col < j && row > i) {
row = row - 1;
colMap.put(row, colMap.get(row) - 1);
col = Math.max(0, colMap.get(row));
}
Element nextLargest = new Element(input[row][Math.max(0, col)], row, Math.max(0, col));
maxQueue.add(nextLargest);
}
return largest.value;
}
I need some help in the for loop specifically, please suggest me a better way to accomplish the task.
I have my code running here
http://ideone.com/wIeZSo
Ok I found a a simple and effective way to make this work, I changed my for loop to ths
for (int l = 0; l < k; l++) {
largest = maxQueue.poll();
int row = largest.row;
colMap.put(row, colMap.get(row) - 1);
int col = colMap.get(row);
if (col < j) {
continue;
}
Element nextLargest = new Element(input[row][Math.max(0, col)], row, Math.max(0, col));
maxQueue.add(nextLargest);
}
If we are exhausted with a column then we do not add anymore items till we reach an element from some other column.
This will also work for matrix which are only sorted row wise but not column wise.
In response to the comment: Even if there are duplicate elements, I don't think that it is necessary to use sophisticated data structures like priority queues and maps, or even inner classes. I think it should be possible to simply start at the end of the array, walk to the beginning of the array, and count how often the value changed. Starting with the value "infinity" (or Integer.MAX_VALUE here), after the kth value change, one has the kth largest element.
public class KthLargestElementTest
{
public static void main (String[] args) throws java.lang.Exception
{
testDistinct();
testNonDistinct();
testAllEqual();
}
private static void testDistinct()
{
System.out.println("testDistinct");
int[][] input = new int[][]
{
{1, 2, 3, 4},
{8, 9, 10, 11},
{33, 44, 55, 66},
{99, 150, 170, 200}
};
for (int i = 1; i <= 17; i ++)
{
System.out.println(findkthLargestElement(input, i, 4, 4));
}
}
private static void testNonDistinct()
{
System.out.println("testNonDistinct");
int[][] input = new int[][]
{
{ 1, 1, 1, 4 },
{ 4, 4, 11, 11 },
{ 11, 11, 66, 66 },
{ 66, 150, 150, 150 }
};
for (int i = 1; i <= 6; i++)
{
System.out.println(findkthLargestElement(input, i, 4, 4));
}
}
private static void testAllEqual()
{
System.out.println("testAllEqual");
int[][] input = new int[][]
{
{ 4, 4, 4, 4 },
{ 4, 4, 4, 4 },
{ 4, 4, 4, 4 },
{ 4, 4, 4, 4 }
};
for (int i = 1; i <= 2; i++)
{
System.out.println(findkthLargestElement(input, i, 4, 4));
}
}
public static int findkthLargestElement(
int[][] input, int k, int m, int n)
{
int counter = 0;
int i=m*n-1;
int previousValue = Integer.MAX_VALUE;
while (i >= 0)
{
int value = input[i/n][i%n];
if (value < previousValue)
{
counter++;
}
if (counter == k)
{
return value;
}
previousValue = value;
i--;
}
if (counter == k)
{
return input[0][0];
}
System.out.println("There are no "+k+" different values!");
return Integer.MAX_VALUE;
}
}

I'm having trouble getting MergeSort to work correctly

So far I have the following code:
public class MergeSort {
int[] theList;
int counter; //required for analysis later
double time; //required for analysis later
MergeSort(int[] n){
int len = n.length;
this.theList = mergeSort(n, 0, len);
}
int[] mergeSort(int[] n, int p, int r){
if((p + 1 )<r){
int q = (r + p)/2;
mergeSort(n, p, q);
mergeSort(n, q+1, r);
merge(n, p, q, r);
}
return n;
}
public void merge(int[] input, int p, int q, int r){
int lefti = q - p;
int righti = r - q;
int[] left = new int[lefti+1];
int[] right = new int[righti+1];
for(int i = 0; i < lefti; i++){
this.counter++;
left[i] = input[p+i];
}
for(int i = 0; i < righti; i++){
this.counter++;
right[i] = input[q+i];
}
left[left.length - 1] = 1000000;
right[right.length - 1] = 1000000;
int i = 0;
int j = 0;
for(int k = p; k < r; k++){
this.counter++;
if(left[i] < right[j]){
input[k] = left[i];
i++;
}
else{
input[k] = right[j];
j++;
}
}
}
}
I think I've been staring at this too long.I would appreciate if someone would be able to steer me in a better direction.
Right now, with the input of MergeSort([9, 8, 7, 6, 5, 4, 3, 2, 1, 0]), theList equals[4, 1, 0, 2, 3, 7, 5, 6, 8, 9].
I'm thankful for any help that I may receive.
It looks like you need a base case for your mergeSort method. If (p+1) >= r then sort the sub-array (i.e. the sub-array should have a size of 1 or 2, if it has a size of 1 then do nothing and if it has a size of 2 then swap the two values if they are out of order)

Categories

Resources