Merge K sorted arrays - java

I am given k sorted arrays and need to merge them into one sorted array. We are assuming that n is the total number of elements in all the input arrays and that k=3.
public class Merge {
// Create a mergeklists() to merge 3 sorted arrays into one sorted array
// Input: 3 sorted arrays a1[], a2[], a3[]
// Output: one sorted array a[] that contains all the elements from input arrays
public static void merge3lists(int[] a1, int[] a2, int[] a3, int[] a)
{
int i=0;
int j=0;
int h=0;
int n = a1.length + a2.length + a3.length;
for(int k; a.length < n-1; k++){
if(a1[i] < a2[j]){
k = a1[i];
i++;
}
else if(a2[j] < a3[h]){
k = a2[j];
j++;
}
else{
k = a3[h];
h++;
}
}
}
public static void main(String[] args) {
int[] l1 = {1,5,9,10,20};
int[] l2 = {2,4,5,6,7,9,15};
int[] l3 = {3,8,13,15,22};
int[] newl = new int[l1.length+l2.length+l3.length];
merge3lists(l1,l2,l3,newl);
for(int i = 0; i< newl.length; i++)
{
System.out.print(newl[i]+ " ");
}
}
}
I know that the integers I am using (I,j,and h) are messing up the problem, but I don't think I can use i while comparing all the arrays. I need to use the declared array a, but I'm not sure how to reference it in this case.

To have to method merge an arbitrary number of arrays (k), you need to make the method use varargs.
It would also be better to have the method create the result array for you.
You then loop until the result array is filled. For each iteration, you find the smallest of the next value from each source array, and add that to the result array, and step forward in the source array you picked the value from.
Like this:
public static int[] mergeArrays(int[]... arrays) {
// Create result array
int n = 0;
for (int[] a : arrays)
n += a.length;
int[] result = new int[n];
// Start at index 0 in each source array
int[] idx = new int[arrays.length];
// Merge source arrays into result array
for (int i = 0; i < n; i++) {
// Find smallest value
int minJ = -1, minVal = 0;
for (int j = 0; j < arrays.length; j++) {
if (idx[j] < arrays[j].length) {
int val = arrays[j][idx[j]];
if (minJ == -1 || val < minVal) {
minJ = j;
minVal = val;
}
}
}
// Add to result array and step forward in appropriate source array
result[i] = minVal;
idx[minJ]++;
}
return result;
}
Test
int[] merged = mergeArrays(new int[] { 23, 39, 63, 68 },
new int[] { 11, 21, 76 },
new int[] { 5, 10, 37, 80 },
new int[] { 30, 49, 50, 94 },
new int[] { 13, 25, 48 });
System.out.println(Arrays.toString(merged));
Output
[5, 10, 11, 13, 21, 23, 25, 30, 37, 39, 48, 49, 50, 63, 68, 76, 80, 94]

Looks like a preparation exercise to motivate the introduction of array of arrays :)
Number the indices analogous to the lists to avoid confusion.
Identify the list with the smallest element at its current index. Avoid reading beyond the end of the array, as it will result in an exception.
Take this element and proceed.
int i1=0;
int i2=0;
int i3=0;
int n = a1.length + a2.length + a3.length;
for( int k = 0; k < n; k++) {
int advance = 0;
int value = Integer.MAX_VALUE;
if (i1 < a1.length && a1[i1] <= value) {
advance = 1;
value = a1[i1];
}
if (i2 < a2.length && a2[i2] <= value) {
advance = 2;
value = a2[i2];
}
if (i3 < a3.length && a3[i3] <= value) {
advance = 3;
value = a3[i3];
}
a[k] = value;
switch(advance) {
case 1: i1++; break;
case 2: i2++; break;
case 3: i3++; break;
}
}

A more efficient algorithm is to use a min-heap.
The algorithm is roughly described as follows:
First, construct a min-heap of size k (in this case size 3 for the three lists) taking the minimum elements in each list. You would then delete then the minimum element from the heap (noting which list it came from), add it to your newly constructed list, and then insert the next element from that same list which it was initially drawn from.
The time complexity would drop from O(n * k) to O(n * log(k)). Where n is the total number of elements in the final sorted list.
https://cs.stackexchange.com/questions/12853/heap-give-an-on-lg-k-time-algorithm-to-merge-k-sorted-lists-into-one-so

Related

How to find numbers that appear only once in a matrix?

I have a given matrix called m and its dimensions are n by n and it contains whole numbers. I need to copy the numbers that appear just once to a new array called a.
I think the logic would be to have a for loop for each number in the matrix and compare it to every other number, but I don't know how to actually do that with code.
I can only use loops (no maps or such) and this is what I've come up with:
public static void Page111Ex14(int[][] m) {
int previous = 0, h = 0;
int[] a = new int[m.length*m[0].length];
for (int i = 0; i < m.length; i++) {
for (int j = 0; j < m[0].length; j++) {
previous = m[i][j];
if (m[i][j] != previous) {
a[h] = m[i][j];
h++;
}
}
}
It's probably not correct though.
Loop through it again to see if there's any repeated one. Assuming you can use labels, the answer might look a bit like that:
public static int[] getSingleInstanceArrayFromMatrix(int[][] m) {
int[] a = new int[m.length * m[0].length];
// Main loop.
for (int x = 0; x < m.length; x++) {
for (int y = 0; y < m[0].length; y++) {
// Gets the current number in the matrix.
int currentNumber = m[x][y];
// Boolean to check if the variable appears more than once.
boolean isSingle = true;
// Looping again through the array.
checkLoop:
for (int i = 0; i < m.length; i++) {
for (int j = 0; j < m[0].length; j++) {
// Assuring we are not talking about the same number in the same matrix position.
if (i != x || j != y) {
// If it is equal to our current number, we can update the variable and break.
if (m[i][j] == currentNumber) {
isSingle = false;
break checkLoop;
}
}
}
}
if (isSingle) {
a[(x * m.length) + y] = currentNumber;
}
}
}
return a;
}
Not sure if it's the most efficient, but I think it will work. It's somewhat hard to form your final array without the help of Lists or such. Since the unassigned values will default to 0, any actual zero (i.e. it's "supposed" to be there based on the matrix) will be undetected if you look up the returned array. But if there's such limitations I imagine that it's not crucially important.
This is one of those problems you can just throw a HashMap at and it just does your job for you. You traverse the 2d array, use a HashMap to store each element with its occurence, then traverse the HashMap and add all elements with occurence 1 to a list. Then convert this list to an array, which is what you're required to return.
This has O(n*n) complexity, where n is one dimension of the square matrix m.
import java.util.*;
import java.io.*;
class GetSingleOccurence
{
static int[] singleOccurence(int[][] m)
{
// work with a list so that we can append to it
List<Integer> aList = new ArrayList<Integer>();
HashMap<Integer, Integer> hm = new HashMap<>();
for (int row = 0; row < m.length; row++) {
for (int col = 0; col < m[row].length; col++) {
if (hm.containsKey(m[row][col]))
hm.put(m[row][col], 1 + hm.get(m[row][col]));
else
hm.put(m[row][col], 1);
}
}
for (Map.Entry entry : hm.entrySet())
{
if (Integer.parseInt(String.valueOf(entry.getValue())) == 1)
a.add(Integer.parseInt(String.valueOf(entry.getKey())));
}
// return a as an array
return a.toArray(new int[a.size()]);
}
public static void main(String args[])
{
// A 2D may of integers with some duplicates
int[][] m = { { 1, 2, 3, 4, 5 },
{ 6, 7, 8, 9, 10 },
{ 11, 12, 12, 14, 15 },
{ 16, 17, 18, 18, 20 },
{ 21, 22, 23, 24, 25 } };
a = singleOccurence(m);
}
}
It may be better to use a boolean array boolean[] dups to track duplicated numbers, so during the first pass this intermediate array is populated and the number of singles is counted.
Then create the resulting array of appropriate size, and if this array is not empty, in the second iteration over the dups copy the values marked as singles to the resulting array.
public static int[] getSingles(int[][] arr) {
int n = arr.length;
int m = arr[0].length;
boolean[] dups = new boolean[n * m];
int singles = 0;
for (int i = 0; i < dups.length; i++) {
if (dups[i]) continue; // skip the value known to be a duplicate
int curr = arr[i / m][i % m];
boolean dup = false;
for (int j = i + 1; j < dups.length; j++) {
if (curr == arr[j / m][j % m]) {
dup = true;
dups[j] = true;
}
}
if (dup) {
dups[i] = true;
} else {
singles++;
}
}
// debugging log
System.out.println("singles = " + singles + "; " + Arrays.toString(dups));
int[] res = new int[singles];
if (singles > 0) {
for (int i = 0, j = 0; i < dups.length; i++) {
if (!dups[i]) {
res[j++] = arr[i / m][i % m];
}
}
}
return res;
}
Test:
int[][] mat = {
{2, 2, 3, 3},
{4, 2, 0, 3},
{5, 4, 2, 1}
};
System.out.println(Arrays.toString(getSingles(mat)));
Output(including debugging log):
singles = 3; [true, true, true, true, true, true, false, true, false, true, true, false]
[0, 5, 1]
Your use of previous is merely an idea on the horizon. Remove it, and fill the one dimensional a. Finding duplicates with two nested for-loops would require n4 steps. However if you sort the array a, - order the values - which costs n² log n², you can find duplicates much faster.
Arrays.sort(a);
int previous = a[0];
for (int h = 1; h < a.length; ++h) {
if (a[h] == previous)...
previous = a[h];
...
It almost looks like this solution was already treated in class.
It doesn't look good:
previous = m[i][j];
if (m[i][j] != previous) {
a[h] = m[i][j];
h++;
}
you assigned m[i][j] to previous and then you check if if (m[i][j] != previous)?
Are there any limitations in the task as to the range from which the numbers can come from?

Indexing array by loop from two or more arrays with different length

Hy, i want to make a method that gives me one array from three different arrays with different length indexing like:
[number of element in array][number of array]
[0][0],
[0][1],
[0][2],
[1][0],
[1][2]
So i made this:
int a = 0;
for (int i = 0; i < collections[a].length; i++) {
for (int k = 0; k < collections.length; k++) {
result[p] = collections[i][k];
p++;
}
}
return result;
but it only works when arrays are the same size and I have no idea what condition should be added to avoid "out of bounds" when it comes to from second element of the first array to second element of the third array excluding second element of the second array which does not even exist.
int[] array3 = { 10, 20, 30, };
int[] array4 = { 40, 50, };
int[] array5 = { 60, 70, 80, 90 };
A.method(array3, array4, array5);
and the result what i want to get is:
10,40,60,20,50,70,30,80,90
First, I find which array has the max length. Then I start two loops. The "outer" loop index j is used to access the individual arrays' elements, which I increment only after I've cycled through all the individual arrays once. I stop incrementing j once j has reached the max length calculated in first step.
private static int[] combine(int[]... arrays) {
int maxArrayLen = Arrays.stream(arrays).mapToInt(array -> array.length).max().getAsInt();
List<Integer> list = new ArrayList<Integer>();
for (int j = 0; j < maxArrayLen; j++) {
for (int i = 0; i < arrays.length; i++) {
if (arrays[i].length > j) {
list.add(arrays[i][j]);
}
}
}
return list.stream().mapToInt(i -> i).toArray();
}
To invoke this: combine(array3, array4, array5);
Running demo: https://ideone.com/F2yxKh

How to get a sequence of 5 numbers from an array

I want to get a sequence of 5 numbers from an array.
For example :
int arr1[] = {3,88,99,5,4,6,22,32,7,45}; // array where there is the sequence 3,4,5,6,7
Vector<Integer> myVec = new Vector<Integer>(); // vector wehre to save the sequence
Now what do I have to do to get the sequence from that array?
I have a code here but it does not work properly:
for(int i = 0; i < arr1.length -1; i++) {
int a = arr1[i];
int b = arr1[i+1];
int c = b - a;
if(c == 1) {
myvec.add(arr1[i]);
}
}
How should I change my code to solve this?
This program will print all the sequence in the array WITHOUT SORTING THE ARRAY. You could select the list with size.. Say if you want match 5 sequence get the list with size 5. Hope this help. (Modify as per your need.)
import java.util.ArrayList;
import java.util.List;
public class Sequence {
private static int arr1[] = { 3, 88, 99, 5, 4, 6, 22, 32, 7, 45 };
private static int findNextInSequence(int start) {
int next = -1;
for(int i = 0; i < arr1.length; i++){
if((start - arr1[i]) == -1){
next = arr1[i];
}
}
return next;
}
public static void main(String[] args) {
for (int i = 0; i < arr1.length; i++) {
List<Integer> sequence = new ArrayList<Integer>();
int nextSequence = arr1[i];
do{
sequence.add(nextSequence);
nextSequence = findNextInSequence(nextSequence);
} while(nextSequence != -1);
System.out.println(sequence);
}
}
}
Your code checks the difference between two successive values from arr1 array. Because it is not sorted, it works like this:
88-3 !=1 (value not added)
99-88 !=1 (value not added)
5-99 !=1 (value not added)
...
45-7 !=1 (value not added).
You have to ensure that values in your array are sorted first. Use Arrays.sort() and apply the method on sorted array. This should add values: 3,4,5,6, but it WON'T add 7 (because it'll be your arr[i+1] value at the time of loop execution.
4-3 ==1 (value added)
5-4 ==1 (value added)
6-5 ==1 (value added)
7-6 ==1 (value added, but it is only number 6 that is added!)
You should count successive count upto 5 and put the result into ArrayList instead of Vector. Because, ArrayList is more efficient than Vector. Try,
int arr1[] = {3, 88, 99, 5, 4, 6, 22, 32, 7, 45, 11, 12, 13, 14, 15};
List<Integer> myVec = new ArrayList<>();
Arrays.sort(arr1);
int count = 0;
int lastValue = 0;
for (int i = 0; i < arr1.length - 1; i++) {
if (arr1[i + 1] - arr1[i] == 1) {
count++;
System.out.println(arr1[i]);
lastValue = arr1[i + 1];
} else {
System.out.println(count);
if (count >= 4) {
for (int j = 0; j <= count; j++) {
myVec.add(lastValue - 4 + j);
}
}
count = 0;
}
}
System.out.println(myVec);

int[] array (sort lowest to highest)

So I am not sure why this is becoming so hard for me, but I need to sort high to low and low to high.
For high to low I have:
int a, b;
int temp;
int sortTheNumbers = len - 1;
for (a = 0; a < sortTheNumbers; ++a) {
for (b = 0; b < sortTheNumbers; ++b) {
if (array[b] < array[b + 1]) {
temp = array[b];
array[b] = array[b + 1];
array[b + 1] = temp;
}
}
}
However, I can't for the life of me get it to work in reverse (low to high), I have thought the logic through and it always returns 0's for all the values.
Any help appreciated!
The bigger picture is that I have a JTable with 4 columns, each column with entries of numbers, names, or dates. I need to be able to sort those back and forth.
Thanks!
Unless you think using already available sort functions and autoboxing is cheating:
Integer[] arr =
{ 12, 67, 1, 34, 9, 78, 6, 31 };
Arrays.sort(arr, new Comparator<Integer>()
{
#Override
public int compare(Integer x, Integer y)
{
return x - y;
}
});
System.out.println("low to high:" + Arrays.toString(arr));
Prints low to high:[1, 6, 9, 12, 31, 34, 67, 78]
if you need high to low change x-y to y-x in the comparator
You are never visiting the last element of the array.
Also, you should be aware that bubble sort is pretty inefficent and you could just use Arrays.sort().
public class sorting {
public static void main(String arg[])throws Exception{
int j[]={1,28,3,4,2}; //declaring array with disordered values
for(int s=0;s<=j.length-1;s++){
for(int k=0;k<=j.length-2;k++){
if(j[k]>j[k+1]){ //comparing array values
int temp=0;
temp=j[k]; //storing value of array in temp variable
j[k]=j[k+1]; //swaping values
j[k+1]=temp; //now storing temp value in array
} //end if block
} // end inner loop
}
//end outer loop
for(int s=0;s<=j.length-1;s++){
System.out.println(j[s]); //retrieving values of array in ascending order
}
}
}
You just need to write one string Arrays.sort(arr) for low to high for Java 8.
Arrays.sort(arr, Collections.reverseOrder()) for high to low
The only thing you need to do to change the sort order is change
if (array[b] < array[b + 1])
to
if (array[b] > array[b + 1])
Although, as others have noted, it's very inefficient! :-)
In java8 you can do something like this:
temp.stream()
.sorted((e1, e2) -> Integer.compare(e2, e1))
.forEach(e -> System.out.println(e));
You need a more efficient sort. like mergesort. try www.geekviewpoint.com and go to sort
If you just want sort the int array: Use the quicksort... It's not a lot of code and it's N*lgN in avarage or N^2 in worst-case.
To sort multiple data, use the Java Compare (as above) or a stable sorting algorithm
static void quicksort(int[] a,int l, int r){
if(r <= l) return;
int pivot = partition(a,l,r);
//Improvement, sort the smallest part first
if((pivot-l) < (r-pivot)){
quicksort(a,l,pivot-1);
quicksort(a,pivot+1,r);
}else{
quicksort(a,pivot+1,r);
quicksort(a,l,pivot-1);
}
}
static int partition(int[] a,int l,int r){
int i = l-1;
int j = r;
int v = a[r];
while(true){
while(less(a[++i],v)); //-> until bigger
while((less(v,a[--j]) && (j != i))); //-> until smaller and not end
if(i >= j){
break;
}
exch(a,i,j);
}
exch(a,i,r);
return i;
}
If you want to apply same logic as what you have done...by not using Arrays.sort...then following will help
int[] intArr = {5, 4, 3, 8, 9, 11, 3, 2, 9, 8, 7, 1, 22, 15, 67, 4, 17, 54};
//Low to high
for(int j=0; j<intArr.length-1; j++){
for(int i=0; i<intArr.length-1; i++){
if (intArr[i] > intArr[i+1]){
int temp = intArr[i+1];
intArr[i+1] = intArr[i];
intArr[i] = temp;
}
}
}
//High to low
for(int j=0; j<intArr.length-1; j++){
for(int i=0; i<intArr.length-1; i++){
if (intArr[i] < intArr[i+1]){
int temp = intArr[i+1];
intArr[i+1] = intArr[i];
intArr[i] = temp;
}
}
}
for(int ars : intArr){
System.out.print(ars+",");
}
Let me know if this works:
public class prog1 {
public static void main (String args[]){
int a[] = {1,22,5,16,7,9,12,16,18,30};
for(int b=0; b<=a.length;b++){
for(int c=0; c<=a.length-2;c++){
if(a[c]>a[c+1]){
int temp=0;
temp=a[c];
a[c]=a[c+1];
a[c+1]=temp;
}
}
}
for(int b=0;b<a.length;b++){
System.out.println(a[b]);
}
}
}
You can try with bubble sort: Example shown below
int[] numbers = { 4, 7, 20, 2, 56 };
int temp;
for (int i = 0; i < numbers.length; i++)
{
for(int j = 0; j < numbers.length; j++)
{
if(numbers[i] > numbers[j + 1])
{
temp = numbers [j + 1];
numbers [j + 1]= numbers [i];
numbers [i] = temp;
}
}
}
for (int i = 0; i < numbers.length; i++)
{
System.out.println(numbers[i].toString());
}

Delete item from array in Java

What is wrong here? I want delete an item from an array, but it shows me
error ArrayIndexOutBound exception
public class delete {
public static void main(String[]args) {
int i;
//delete item from array
int k[] = new int[]{77,99,44,11,00,55,66,33,10};
//delete 55
int searchkey=55;
int nums=k.length;
for ( i=0;i<nums;i++)
if (k[i]==searchkey)
break;
for (int t=i;t<nums;t++)
k[t]=k[t+1];
nums--;
for (int m=0;m<nums;m++) {
System.out.println(k[m]);
}
}
}
for (int t=i;t<nums-1;t++) //Should be -1 here, as k[t+1] will be out of bounds if t = nums-1
Or another variant to nums-- before you move the numbers
nums--;
for (int t=i;t<nums;t++)
k[t]=k[t+1];
The following rewriting should be instructive:
public class Delete {
static int search(int key, int[] arr) {
for (int i = 0; i < arr.length; i++)
if (arr[i] == key) {
return i;
}
return -1;
}
static void print(int[] arr, final int L) {
for (int i = 0; i < L; i++) {
System.out.println(arr[i]);
// try this also:
// System.out.format("%02d ", arr[i]);
}
}
public static void main(String[] args) {
int nums[] = { 77, 99, 44, 11, 00, 55, 66, 33, 10 };
final int N = nums.length;
int searchKey = 55;
int pos = search(searchKey, nums);
for (int t = pos; t < N-1; t++) {
nums[t] = nums[t + 1];
}
print(nums, N-1);
// prints 77, 99, 44, 11, 0, 66, 33, 10
System.out.println(010 == 8); // prints "true"
System.out.println(00000); // prints "0
}
}
Here are some key observations:
Break apart logic into helper methods. This makes the logical components easier to test and reuse, and the overall logic easier to understand.
It makes the code easier to understand if you use final local variables like N to denote the initial size of int[] nums, and define the rest of the logic in terms of N, N-1, etc.
The more non-final variables there are, the harder it is to understand what's going on as their values changes over time
Follow coding convention. In particular, class names starts with uppercase.
Do be careful with the 00 in the array. The 0 prefix is for octal literals. That is, 010 == 8.
Do note that 00 is printed as simple 0. Numerically, 00 = 000 = 0000 = 0. If you need this to be zero-padded, then that's a formatting issue.
See also
On octal literals
09 is not recognized where as 9 is recognized
Integer with leading zeroes
On zero-padding
Left padding integers with zeros in Java
in the following loop
for (int t=i;t<nums;t++)
k[t]=k[t+1];
when t is pointing to the last element then k[t+1] operation will throw an exception which is what you are getting now.
On k[t]=k[t+1]; you got error es k[t+1] tries to access 10th element with index 9, but your array contains 9 elements. So you got data out of bounds.
It works if you use it as Draco Ater said:
for (int t=i;t<nums-1;t++) {
k[t]=k[t+1];
}
nums--;
Output is then:
77
99
44
11
0
66
33
10
which should be correct. ;-)
for (int t=i;t<nums;t++)
k[t]=k[t+1];
just replace nums with nums-1 because you have already deleted(skipped) one element.
I find it to work best in the following way:
Make sure the iteration does not go beyond the second last element (array.length-1) so it can have an element to compare to:
for(int i=elementPosition-1;i<array.length-1;i++){array[i]=array[i+1];}
import java.util.ArrayList;
import java.util.Arrays;
public class Sort {
public static void main(String a[]) {
int swap;
int length;
int[] unsorted = { 1, 2, 4, 3, 6, 5, 7, 8, 18, 17, 65, 46, 2, 4, 5, 3,
4 };
length = unsorted.length;
for (int i = 0; i < length; i++) {
for (int j = i + 1; j < length; j++) {
if (unsorted[i] > unsorted[j]) {
swap = unsorted[i];
unsorted[i] = unsorted[j];
unsorted[j] = swap;
} else if (unsorted[i] == unsorted[j]) {
for (int k = j; k < length - 1; k++) {
unsorted[k] = unsorted[k + 1];
}
length -= 1;
}
}
}
for (int i = 0; i < length; i++) {
System.out.println(" " + i + "th element " + unsorted[i]);
}
}
}

Categories

Resources