Combining Merge Sort with Insertion Sort - java

Could someone please advise why this code is not working correctly when threshold is set to <=3? last few digits of array does not get sorted. For example:
input: {20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; output: {3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 2 1 }
public class mergesorttest{
public static void main(String[]args){
int d[]= {20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
mergeSort(d,0,d.length);
for(int x:d) System.out.print(x+" ");
System.out.println();
}
static final int THRESHOLD = 3;
static void mergeSort(int f[],int lb, int ub){
if (ub - lb <= THRESHOLD)
insertion_srt(f, lb, ub);
else
{
int mid = (lb+ub)/2;
mergeSort(f,lb,mid);
mergeSort(f,mid,ub);
merge(f,lb,mid,ub);
}
}
static void merge (int f[],int p, int q, int r){
//p<=q<=r
int i =p; int j = q;
//use temp array to store merged sub-sequence
int temp[] = new int[r-p]; int t = 0;
while(i<q && j<r){
if(f[i]<=f[j]){
temp[t] =f[i];
i++;t++;
}
else{
temp[t] = f[j];
j++;
t++;
}
//tag on remaining sequence
while(i<q){
temp[t] = f[i];
i++;
t++;
}
while(j<r){
temp[t]=f[j];
j++;
t++;
}
//copy temp back to f
i=p;t=0;
while(t<temp.length){
f[i]=temp[t];
i++;
t++;
}
}
}
public static void insertion_srt(int array[], int n, int b){
for (int i = 1; i < n; i++){
int j = i;
int B = array[i];
while ((j > 0) && (array[j-1] > B)){
array[j] = array[j-1];
j--;
}
array[j] = B;
}
}
}
P.S. code was borrowed from other post
Combining MergeSort with Insertion sort to make it more efficient

In insertion_srt() shouldn't the for loop be
for (int i = n+1; i < b; i++){
and the while loop:
while ((j > n) && (array[j-1] > B)){
merge() also needs a fix, the trailing brace for the first while loop needs to be moved up before the code to tag on remaining sequences:
while(i<q && j<r){
if(f[i]<=f[j]){
temp[t] =f[i];
i++;
t++;
}else{
temp[t] = f[j];
j++;
t++;
}
}
while(i<q){
temp[t] = f[i];
i++;
t++;
}
while(j<r){
temp[t]=f[j];
j++;
t++;
}

Related

Java find missing numbers in array

I am trying to learn Java on my own for only 3 weeks (from YouTube videos and blogs) and this is my first language. I want to write a program to find missing number (s) in an ascending integer array. I found a way, but it only works if the last number in the incrementing array is less than 10. Like 1, 2, 3, 4, 5, 6, 7, 8, 9, 10.
I also found other programs on the internet, but they all have the same problem.
I tried to write on my own with my limited 3 week knowledge and succeeded. But I think I took the long way. The code is almost 27 lines long.
Let me show you the code
I have an integer array with 9 elements:
[12, 13, 17, 18, 20, 21, 24, 25, 26]
and 14, 15, 16, 19, 22, 23 are missing
public class Exercises {
public static void main(String[] args) {
int[] arr = {12, 13, 17, 18, 20, 21, 24, 25, 26};
int len = arr.length;
System.out.println("\nArray source: \n" + Arrays.toString(arr));
//for avoiding ArrayIndexOutOfBoundsException
//error I am creating temp. array with 10 elemets
//and adding main array elements to temp. array
int[] tempArr = new int[len + 1];
for (int i = 0; i < len; i++) {
tempArr[i] = arr[i];
}
//adding last element to temp. array
int max = 0;
for (int i = 0; i < tempArr.length; i++) {
if (tempArr[i] > max) {
max = tempArr[i];
}
}
tempArr[tempArr.length - 1] = max + 1;
System.out.println("\nMissing number(S): ");
for (int i = 0; i < len - 1; i++) {
// If it comes to the last loppf main array
// this will be use temp. arrays' last element to
// compare main array
if (i == (len - 1) && (tempArr[i + 1] - arr[i]) > 1) {
System.out.println(tempArr[i]);
} else if ((arr[i + 1] - arr[i]) > 1) {
for (int a = 1; a <= (arr[i + 1] - arr[i]) - 1; a++) {
System.out.println(arr[i] + a);
}
}
}
}
}
Output:
Array source:
[12, 13, 17, 18, 20, 21, 24, 25, 26]
Missing number(S):
14
15
16
19
22
23
I got what I wanted, but is there a more optimal way to do that?
Btw if I want to make code more esthetic it becomes huge :D
public class Exercises {
public static void main(String[] args) {
int[] arr = {12, 13, 17, 18, 20, 21, 24, 25, 26};
int len = arr.length;
int[] tempArr = new int[len + 1];
int[] correctArr = new int[MathUtils.max(arr) - MathUtils.min(arr) + 1];
int countArr = (MathUtils.max(arr) - (MathUtils.max(arr) - MathUtils.min(arr)) - 1);
for (int i = 0; i < correctArr.length; i++) {
countArr++;
correctArr[i] = countArr;
}
System.out.println("\nArray source: \n" + Arrays.toString(arr));
System.out.println("Source should be: \n" + Arrays.toString(correctArr));
for (int i = 0; i < len; i++) {
tempArr[i] = arr[i];
}
int max = 0;
for (int i = 0; i < tempArr.length; i++) {
if (tempArr[i] > max) {
max = tempArr[i];
}
}
tempArr[tempArr.length - 1] = max + 1;
int count = 0;
for (int i = 0; i < len - 1; i++) {
if (i == (len - 1) && (tempArr[i + 1] - arr[i]) > 1) {
count++;
} else if ((arr[i + 1] - arr[i]) > 1) {
for (int a = 1; a <= (arr[i + 1] - arr[i]) - 1; a++) {
count++;
}
}
}
if (count == 1) {
System.out.println("\nThere is only one missing number:");
} else if (count > 1) {
System.out.println("\nThere are " + count + " missing numbers:");
}
for (int i = 0; i < len - 1; i++) {
if (i == (len - 1) && (tempArr[i + 1] - arr[i]) > 1) {
System.out.println(tempArr[i]);
} else if ((arr[i + 1] - arr[i]) > 1) {
for (int a = 1; a <= (arr[i + 1] - arr[i]) - 1; a++) {
System.out.println(arr[i] + a);
}
}
}
}
}
Output:
Array source:
[12, 13, 17, 18, 20, 21, 24, 25, 26]
Source should be:
[12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]
There are 6 missing numbers:
14
15
16
19
22
23
You look to be over complicating things since a simple nested for loop is probably all that you need. The outer loop loops through the array, up to but not including the last number, and the inner loop loops between one item in the array going to the next item, from arr[i] + up to arr[i + 1]. Note that the inner loop won't "loop" if the two array items are contiguous, and so no if blocks are needed:
public class MissingNumber {
public static void main(String[] args) {
int[] arr = {12, 13, 17, 18, 20, 21, 24, 25, 26};
System.out.println("missing numbers");
for (int i = 0; i < arr.length - 1; i++) {
for (int j = arr[i] + 1; j < arr[i + 1]; j++) {
System.out.println("" + j);
}
}
}
}
Output:
missing numbers
14
15
16
19
22
23
That's it
You can use List<Integer> to avoid repeating the same calculation.
static List<Integer> missingNumbers(int[] a) {
List<Integer> missingNumbers = new ArrayList<>();
for (int i = 1, length = a.length; i < length; ++i)
if (a[i - 1] + 1 < a[i])
for (int j = a[i - 1] + 1; j < a[i]; ++j)
missingNumbers.add(j);
return missingNumbers;
}
public static void main(String[] args) {
int[] a = {12, 13, 17, 18, 20, 21, 24, 25, 26};
List<Integer> missingNumbers = missingNumbers(a);
if (missingNumbers.size() == 1)
System.out.println("There is only one missing number:");
else
System.out.println("There are " + missingNumbers.size() + " missing numbers:");
for (int n : missingNumbers)
System.out.println(n);
}
output:
There are 6 missing numbers:
14
15
16
19
22
23
int[] arr = { 12, 13, 17, 18, 20, 21, 24, 25, 26 };
System.out.println("Array Source:");
System.out.println(Arrays.toString(arr) + "\n");
System.out.println("Missing number(s):");
int nextNumber = arr[0] + 1;
for (int i = 1; i < arr.length; i++) {
while (arr[i] > nextNumber) {
System.out.println(nextNumber);
nextNumber++;
}
nextNumber++;
}
To fill the array with all numbers from min to max you can write
int[] shouldBe = IntStream.range(min, max + 1).toArray();
and in this special case
int[] shouldBe = IntStream.range(arr[0], arr[arr.length - 1] + 1).toArray();
public class missingnumber{
public static void main(String args[]){
int arr[]={1,2,3,4,6,7,8,9};
for(int i=arr.length-1;i>0;i--){
if(arr[i]-1!=arr[i-1]){
System.out.println(arr[i]-1);
}
}
}
}

Trying to swap the maximum and the minimum numbers in an array

I'm trying to swap the maximum and minimum values in an array in my program.
Here is the code:
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int myArray[] = new int[25];
for (int i = 0; i < myArray.length; i++) {
System.out.println("Enter a number: ");
myArray[i] = in.nextInt();
}
int maximum = maxNumber(myArray);
int minimum = minNumber(myArray);
System.out.println(Arrays.toString(myArray));
}
public static int maxNumber(int[] arr) {
int maximumValue = arr[0];
//finds the maximum value in an array
for (int a = 1; a < arr.length; a++) {
if (arr[a] > maximumValue) {
maximumValue = arr[a];
}
}
return maximumValue;
}
public static int minNumber(int[] arr) {
int minimumValue = arr[0];
//finds the minimum value in an array
for (int a = 1; a < arr.length; a++) {
if (arr[a] < minimumValue) {
minimumValue = arr[a];
}
}
return minimumValue;
}
I have two separate functions to find the Maximum and Minimum values, but I'm stuck on the actual swapping of the values. The two functions work as I've used them for another program, but I'm not sure if they would work for this program.
At first I was thinking of finding them by setting them equal to each other in some way, but that led to nothing.
Any help would be appreciated.
public static void main(String... args) {
Scanner scan = new Scanner(System.in);
int[] arr = new int[25];
System.out.format("Enter array int numbers (%d in total): ", arr.length);
for (int i = 0; i < arr.length; i++)
arr[i] = scan.nextInt();
System.out.println(Arrays.toString(arr));
swamMinMax(arr);
System.out.println(Arrays.toString(arr));
}
private static void swamMinMax(int[] arr) {
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (int i = 0; i < arr.length; i++) {
min = Math.min(min, arr[i]);
max = Math.max(max, arr[i]);
}
for (int i = 0; i < arr.length; i++) {
if (arr[i] == min)
arr[i] = max;
else if (arr[i] == max)
arr[i] = min;
}
}
Output:
Enter array int numbers (25 in total): 1 2 3 4 5 6 7 8 9 10 -1 -1 -1 14 15 16 17 18 19 20 21 22 23 66 66
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -1, -1, -1, 1, 1, 1, 17, 18, 19, 20, 21, 22, 23, 66, 66]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 66, 66, 66, 1, 1, 1, 17, 18, 19, 20, 21, 22, 23, -1, -1]
You were real close. I copied some of the code and commented where the changes need to be made. You can still use your existing code to populate the array from the console.
Also, kudos for assigning the first element in the array to min or max and starting your loop at 1. A lot of folks don't think about doing that.
int myArray[] = {1,10,-5,99,48,-22,43, 44,100,2};
System.out.println(Arrays.toString(myArray)); // print original array
int maxIdx = maxNumber(myArray); // get index of max
int minIdx = minNumber(myArray); // get index of min
// now swap max and min using the returned indices.
int save = myArray[maxIdx];
myArray[maxIdx] = myArray[minIdx];
myArray[minIdx] = save;
System.out.println(Arrays.toString(myArray)); // print the altered array
public static int maxNumber(int[] arr) {
int maximumValue = arr[0];
// finds the maximum value in an array
int idx = 0; //idx = 0 to start
for (int a = 1; a < arr.length; a++) {
if (arr[a] > maximumValue) {
idx = a; //save index of current max
maximumValue = arr[a];
}
}
return idx; // return index of max
}
public static int minNumber(int[] arr) {
int minimumValue = arr[0];
// finds the minimum value in an array
int idx = 0; // idx = 0 to start
for (int a = 1; a < arr.length; a++) {
if (arr[a] < minimumValue) {
idx = a; // save index of current min
minimumValue = arr[a];
}
}
return idx; // return index of min
}
This would print
[1, 10, -5, 99, 48, -22, 43, 44, 100, 2]
[1, 10, -5, 99, 48, 100, 43, 44, -22, 2]
You can use IntStream to find indexes of the maximum and minimum elements and then swap their values:
int[] arr = {1, 3, 5, 6, 4, 2, 8, 7, 9, -1, -3};
// indexes of the maximum and minimum elements
int max = IntStream.range(0, arr.length)
.boxed().max(Comparator.comparing(i -> arr[i])).orElse(-1);
int min = IntStream.range(0, arr.length)
.boxed().min(Comparator.comparing(i -> arr[i])).orElse(-1);
// swap the values
int temp = arr[max];
arr[max] = arr[min];
arr[min] = temp;
System.out.println(Arrays.toString(arr));
// [1, 3, 5, 6, 4, 2, 8, 7, -3, -1, 9]

Wrong output while merging sorted arrays of equal length

I'm trying to merge 2 sorted arrays of equal length. However, I'm not getting the desired output.
Here is my code:
public static int[] mergeSorted(int[] arr1, int[] arr2){
int n = arr2.length;
int[] ans = new int[2*n];
int k = 0;
int i = 0;
int j = 0;
while(i < n && j < n){
if(arr1[i] <= arr2[j]){
ans[k] = arr1[i];
i++;
}
else{
ans[k] = arr2[j];
j++;
}
k++;
}
while(i < n){
ans[k] = arr1[i];
k++;
i++;
}
while(j < n){
ans[k] = arr2[j];
k++;
j++;
}
return ans;
}
public static void main(String[] args){
int[] arr1 = new int[]{1, 3, 5, 100, 34, 29};
int[] arr2 = new int[]{2, 4, 6, 9, 13, 300};
int[] ans = mergeSorted(arr1, arr2);
for(int el : ans)
System.out.print(el + " ");
}
Output:
1 2 3 4 5 6 9 13 100 34 29 300
Clearly, this is not correct. However, this code works for smaller inputs. Where am I going wrong?
EDIT: Test cases were wrong as they were not sorted. Code was fine.
For the merge operation to work, the two arrays you are merging should be in sorted order. The first array is not in sorted order:
int[] arr1 = new int[]{1, 3, 5, 100, 34, 29};
Change it to:
int[] arr1 = new int[]{1, 3, 5, 29, 34, 100};

How to put all even numbers in order first appear, and then odd numbers appear?

I having problem is how rearrange an array of int values so that all the even
values appear before all the odd values . Below is my coding:
import java.io.*;
public class EvenAppearBeforeOdd {
// function to rearrange the array in given way.
static void rearrangeEvenAndOdd(int arr[], int n)
{
// variables
int j = -1,temp;
// quick sort method
for (int i = 0; i < n; i++) {
// if array of element
// is odd then swap
if (arr[i] % 2 == 0) {
// increment j by one
j++;
// swap the element
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
// Driver code
public static void main(String args[])
{
int arr[] = { 15, 9, 1, 3, 10, 5, 4, 8 };
System.out.println("\n\nBefore\n");
System.out.println(arr[]);
try {
System.out.println(EvenAppearBeforeOdd.rearrangeEvenAndOdd(arr);
} catch (Exception e) {
System.out.println("Error!!!");
}
int n = arr.length;
rearrangeEvenAndOdd(arr, n);
System.out.println("\n\nAfter\n");
for (int i = 0; i < n; i++)
System.out.print(arr[i] + " ");
}
}
The error output show in the below:
run:
C:\Users\User\AppData\Local\NetBeans\Cache\8.0.2\executor-snippets\run.xml:48:
Cancelled by user.
BUILD FAILED (total time: 3 seconds)
Actually I want the output like the below:
run:
Before
15 9 1 3 10 5 4 8
After
10 4 8 3 15 5 9 1 BUILD SUCCESSFUL (total time: 0 seconds)
Hope anyone can help me check the coding which part I wrong? Thanks a lot.
Given below is the answer that produces the result matching your sample input and output:
public class EvenAppearBeforeOdd {
static void rearrangeEvenAndOdd(int arr[]) {
int j = 0, temp;
for (int i = 0; i < arr.length; i++) {
if (arr[i] % 2 == 0) {
temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
j++;
}
}
}
static void printArray(int arr[]) {
for(int i=0;i<arr.length;i++)
System.out.print(arr[i]+"\t");
System.out.println();
}
public static void main(String args[]) {
int arr[] = { 15, 9, 1, 3, 10, 5, 4, 8 };
System.out.println("Before:");
printArray(arr);
rearrangeEvenAndOdd(arr);
System.out.println("After:");
printArray(arr);
}
}
You can compare your answer with it and easily find the mistake. Feel free to comment if you still have any issue.
Update [06-Oct-2019 19:00]:
To solve the issue raised by WJS, rearrangeEvenAndOdd method can be written as:
static void rearrangeEvenAndOdd(int arr[]) {
int j, temp;
for (int i = 0; i < arr.length; i++) {
if (arr[i] % 2 == 0) {
temp = arr[i];
j=i-1;
while(j>=0 && arr[j]%2==1) {
arr[j+1]=arr[j];
j--;
}
arr[j+1]=temp;
}
}
}
However, it will not produce the result matching your sample input and output i.e. for the input array as { 15, 9, 1, 3, 10, 5, 4, 8 }, the result would be produced as {10, 4, 8, 15, 9, 1, 3, 5} and not as your sample output which is {10, 4, 8, 3, 15, 5, 9, 1}.
If you are bound by a requirement to not use any additional memory in your algorithm, then we would have to find a way to fix your current approach. I think the conceptually easiest approach is to use a duplicate empty array to build the output. First, iterate the input array and copy over all even values. Then, iterate again and copy over all odd values.
static int[] rearrangeEvenAndOdd(int arr[], int n) {
int[] output = new int[n];
int count = 0;
for (int i=0; i < n; ++i) {
if (arr[i] % 2 == 0) output[count++] = arr[i];
}
for (int i=0; i < n; ++i) {
if (arr[i] % 2 == 1) output[count++] = arr[i];
}
return output;
}
public static void main (String[] args) {
int[] arr = { 15, 9, 1, 3, 10, 5, 4, 8 };
System.out.println(Arrays.toString(arr));
arr = rearrangeEvenAndOdd(arr, arr.length);
System.out.println(Arrays.toString(arr));
}
This prints:
[15, 9, 1, 3, 10, 5, 4, 8]
[10, 4, 8, 15, 9, 1, 3, 5]
Note that this is a linear solution, requiring two full scans of the input array, and it also requires twice the storage of the input.
Your syntax seem wrong.
Not sure if it were a errata, but you should try compiling in the editor (eclipse).
It will show all errors and warning about the syntax.
System.out.println(arr[]);
System.out.println(EvenAppearBeforeOdd.rearrangeEvenAndOdd(arr);

Rearrange an array such that arr[i] = i

Input : arr = {-1, -1, 6, 1, 9, 3, 2, -1, 4, -1}
Output : [-1, 1, 2, 3, 4, -1, 6, -1, -1, 9]
Input : arr = {19, 7, 0, 3, 18, 15, 12, 6, 1, 8,
11, 10, 9, 5, 13, 16, 2, 14, 17, 4}
Output : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19]
Approach
1. Nav­i­gate the array.
Check if a[i] = -1, if yes then ignore it.
If a[i] != -1, Check if element a[i] is at its cor­rect posi­tion (i=A[i]). If yes then ignore it.
If a[i] != -1 and ele­ment a[i] is not at its cor­rect posi­tion (i!=A[i]) then place it to its correct posi­tion, but there are two conditions:
(i).Either A[i] is vacant, means A[i] = -1, then just put A[i] = i .
(ii).OR A[i] is not vacant, means A[i] = x, then int y=x put A[i] = i. Now, we need to place y to its cor­rect place, so repeat from step 3.
What would be the time complexity of below solution?
public static int[] fix(int[] A) {
for (int i = 0, x = A[i]; i < A.length; i++) {
if (x == -1 || x == i)
continue;
// check if desired place is not vacant
while (A[x] != -1 && A[x] != x) {
int y = A[x]; // store the value from desired place
A[x] = x; // place the x to its correct position
x = y; // now y will become x, now search the place for x
}
A[x] = x; // place the x to its correct position
// check if while loop hasn't set the correct value at A[i]
if (A[i] != i)
A[i] = -1; // if not then put -1 at the vacated place
}
return A;
}
I can offer you two algorithms.
First one: using extra array, time complexity is O(n), with O(n) additional memory
public static int[] fix(int[] arr) {
int[] res = new int[arr.length];
Arrays.fill(res, -1);
for (int i = 0; i < arr.length; i++)
if (arr[i] != -1)
res[arr[i]] = arr[i];
return res;
}
Second one: in place, time complexity is O(n^2) in worst case and O(n) in average case, without additional memory
public static int[] fix(int[] arr) {
int i;
while ((i = findIncorrectPosition(arr)) >= 0) {
while (arr[i] != -1 && arr[i] != i) {
swap(arr, i, arr[i]);
}
}
return arr;
}
...plus two private support methods:
private static int findIncorrectPosition(int[] arr) {
for (int i = 0; i < arr.length; i++)
if (arr[i] != -1 && arr[i] != i)
return i;
return -1;
}
private static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
f(n) = O(n) using swapping methodology #Swift
for i in stride(from: 0, to: array.count, by: 1){
if(array[i] >= 0 && array[i] != i){
let ele = array[array[i]]
array[array[i]] = array[i]
array[i] = ele
}
}
for k in stride(from: 0, to: array.count, by:1 ){
print(" ",array[k])
}

Categories