Print only the numbers, which have been changed - java

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]);
}
}

Related

How to find first 5 highest value in a two dimensional array?

I have a two dimensional integer array. Row and Column information (locations of numbers) is important for me. So, I don't want to sort an array (matrix actually). How can I find the highest 5 value from this two dimensional array?
Here is my code:
for (int row = 0; row < matirx.length; row++) {
for (int col = 0; col < matirx[row].length; col++) {
if (matirx[row][col] > maxValue) {
maxValue = matirx[row][col];
}
}
}
First, I went for a streams solution that is very similar to other Answers. I didn't like the boxing and unboxing variations, but since IntStream doesn't have a fancy method that makes sorting with a Comparator straight out of the box, the IntStream has to be converted into a Stream in order to sort the values in reverse order. I didn't think it was important to return an int[] array, since we're only really interested in the values.
public static Integer[] streamIt(int[][] matrix, int n){
Integer[] result =
Arrays.stream(matrix) // stream the arrays
// This is the same as using .flatMaptoInt(..) and then .boxed()
.flatMap(a -> Arrays.stream(a) // stream the array in arrays
.mapToObj(i -> Integer.valueOf(i))) // turn the ints into Integers
.sorted(Comparator.reverseOrder()) // sort by higest values
.limit(n) // only pick n
.toArray(i -> new Integer[i]); // put then in Integer array
return result;
}
If you want them in an int[] array instead, look at the Answer by shadow.sabre that uses mapToInt() do to that.
While the streams solution is very neat and clean looking, I felt that the problem was really just to get the set of highest values, so inserting them into a standard java sorted Set made sense to me. I start off by inserting the values into the set until there are 5 elements in there. Then I check to see if the new value is higher than the lowest value, and if so, I just remove the lowest value while inserting the new one. Finding the lowest value is easy when using TreeSet as it's a sorted set.
The trick is to also check that the new value isn't already in the set. If there's already 5, 4, 3, 2, 1 in the set, and the new value is 5, then I don't want to remove the lowest value 1, since adding the new value wouldn't actually add any new elements to the Set. Remember a Set cannot contain duplicate values:
public static Set<Integer> useSet(int[][] matrix, int n){
TreeSet<Integer> max = new TreeSet<>(Comparator.<Integer>naturalOrder().reversed());
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
// Keep adding values until there's n elements in the Set
if (max.size() < n) {
max.add(matrix[i][j]);
} else {
// if the new value is higher than the lowest value
// ..and the new values isn't already there.
if (max.last() < matrix[i][j] && !max.contains(matrix[i][j])) {
max.pollLast();
max.add(matrix[i][j]);
}
}
}
}
return max;
}
Note that this solution obviously never contains the same values, but always the top distinct ones.
Looking at the set solution it was easy to add the additional functionality of keeping track of where in the matrix the values were found. I created a class, Element, to contain the value and its location. Every element in the matrix that's to be inserted into the TreeSet is created as an Element.
The Element needs to either implement Comparable or the TreeSet has to be initialized with a Comparator in order to sort the elements. This example of Element has both, and I just used the static Comparator in the implementation of compareTo(Element that) to make it a Comparable<Element>. Normally you'd implement the class with private fields using getters to fetch the values, but for this purpose is seemed a little verbose. Making the fields final also ensures the class is immutable so I have no scruples about it.
Since the comparison is done using both the value and the location, every element from the matrix will be distinct:
class Element implements Comparable<Element> {
final int value;
final int x;
final int y;
static Comparator<Element> comparator =
Comparator.comparing((Element e) -> e.value)
.thenComparing((Element e) -> e.x)
.thenComparing((Element e) -> e.y)
.reversed();
Element(int value, int x, int y) {
this.value = value;
this.x = x;
this.y = y;
}
public int compareTo(Element that){
return comparator.compare(this, that);
}
public String toString(){
return value + " at [" + x + "][" + y + "]";
}
}
If the Element didn't implement the Comparable interface, this would be the initialization of the TreeSet:
TreeSet<Element> maxElement = new TreeSet<>(Element.comparator);
But since Element does implement the Comparable interface, the set implementation can be initialized without it:
public static Set<Element> useSetElements(int[][] matrix, int n){
TreeSet<Element> maxElement = new TreeSet<>();
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
if (maxElement.size() < n) {
maxElement.add(new Element(matrix[i][j],i,j));
} else {
if (maxElement.last().value < matrix[i][j]) {
maxElement.pollLast();
maxElement.add(new Element(matrix[i][j],i,j));
}
}
}
}
return maxElement;
}
Note that because every element is distinct, there's no need to also check that the new value isn't already in the set.
Running the three solutions with given input:
int n = 5;
int[][] matrix = {{16, -20, 22, 19},
{ 2, 5, 6, 8},
{17, 25, 16, 19},
{ 7, 18, 4, 17}};
System.out.println("streamIt: \n "
+ Arrays.toString(streamIt(matrix,n)));
System.out.println("useSet: \n "
+ useSet(matrix,n));
System.out.println("useSetElements: \n "
+ useSetElements(matrix,n));
..gives this:
streamIt:
[25, 22, 19, 19, 18]
useSet:
[25, 22, 19, 18, 17]
useSetElements:
[25 at [2][1], 22 at [0][2], 19 at [2][3], 19 at [0][3], 18 at [3][1]]
But what about Performance..?
The three different implementations had me wondering about the performance, so I added a method to time the execution:
static void timeMethod(Runnable toRun){
long start = System.nanoTime();
try{
toRun.run();
} finally {
long end = System.nanoTime();
System.out.println(" Time: " + (end - start)/1.0e6 + " miliseconds");
}
}
And ran the three solutions:
timeMethod(() -> System.out.println("streamIt: \n "
+ Arrays.toString(streamIt(matrix,n))));
timeMethod(() -> System.out.println("useSet: \n "
+ useSet(matrix,n)));
timeMethod(() -> System.out.println("useSetElements: \n "
+ useSetElements(matrix,n)));
..giving this result:
streamIt:
[25, 22, 19, 19, 18]
Time: 1.2759 miliseconds
useSet:
[25, 22, 19, 18, 17]
Time: 0.9343 miliseconds
useSetElements:
[25 at [2][1], 22 at [0][2], 19 at [2][3], 19 at [0][3], 18 at [3][1]]
Time: 1.16 miliseconds
It seems that the three solutions have roughly the same performance. The streams solution seems slightly slower. The Set solution looks promising, expect the solution using Element seems to take a toll. But to look at it more deeply I decided to run them on a much larger matrix, which I build using random integers:
Random random = new Random();
int[][] largerMatrix =
IntStream.range(0,10000) // 10000 on the first dimension
.mapToObj(i -> random.ints(0,128) // values between 0 and 128 (not included)
.limit(10000) // 10000 on the second dimension
.toArray()) // make the second 1D arrays
.toArray(int[][]::new); // put them into a 2D array
Running the test with a 10000 by 10000 matrix:
timeMethod(() -> System.out.println("streamIt: \n "
+ Arrays.toString(streamIt(largerMatrix,n))));
timeMethod(() -> System.out.println("useSet: \n "
+ useSet(largerMatrix,n)));
timeMethod(() -> System.out.println("useSetElements: \n "
+ useSetElements(largerMatrix,n)));
..gave this result:
streamIt:
[127, 127, 127, 127, 127]
Time: 90374.6995 miliseconds
useSet:
[127, 126, 125, 124, 123]
Time: 2465.2448 miliseconds
useSetElements:
[127 at [0][310], 127 at [0][277], 127 at [0][260], 127 at [0][81], 127 at [0][61]]
Time: 1839.7323 miliseconds
Here the streams solution seems incredibly slow! The Element solution is the winner of the two Set solutions. I expect it's due to the fact that Elements are only created when they're needed for inserting into the Set and it's doing a straight up int comparison, while the other Set solution is unboxing every time the values are compared. I didn't further test my hypothesis though.
My curiosity of the other solutions in this thread got me testing out those as well. The solutions tested were:
Answer by Arvind Kumar Avinash
Answer by Anurag Jain
Answer by Michael Chatiskatzi
Running the tests on both the small and the large array:
System.out.println("--- Testing performance ---");
timeMethod(() -> System.out.println("ArvindKumarAvinash: \n "
+ Arrays.toString(ArvindKumarAvinash(matrix,n))));
timeMethod(() -> System.out.println("AnuragJain: \n "
+ AnuragJain(matrix,n)));
timeMethod(() -> System.out.println("MichaelChatiskatzi: \n "
+ Arrays.toString(MichaelChatiskatzi(matrix,n))));
System.out.println();
System.out.println("--- Testing performance with largeMatrix---");
timeMethod(() -> System.out.println("ArvindKumarAvinash: \n "
+ Arrays.toString(ArvindKumarAvinash(largerMatrix,n))));
timeMethod(() -> System.out.println("AnuragJain: \n "
+ AnuragJain(largerMatrix,n)));
timeMethod(() -> System.out.println("MichaelChatiskatzi: \n "
+ Arrays.toString(MichaelChatiskatzi(largerMatrix,n))));
..gave these results:
--- Testing performance ---
ArvindKumarAvinash:
[25, 22, 19, 19, 18]
Time: 0.9076 miliseconds
AnuragJain:
[25, 22, 19, 19, 18]
Time: 6.2277 miliseconds
MichaelChatiskatzi:
[18, 19, 19, 22, 25]
Time: 1.2204 miliseconds
--- Testing performance with largeMatrix---
ArvindKumarAvinash:
[127, 127, 127, 127, 127]
Time: 3381.1387 miliseconds
AnuragJain:
[127, 127, 127, 127, 127]
Time: 120244.7063 miliseconds
MichaelChatiskatzi:
[127, 127, 127, 127, 127]
Time: 51.4259 miliseconds
It seems that solutions using streams are not very performant at all. Michael Chatiskatzi's solution is by far the better performant one.
All the code
If you want to run it yourself, here a complete class for copy'n'paste'n'run:
import java.util.Arrays;
import java.util.Comparator;
import java.util.stream.IntStream;
import java.util.Set;
import java.util.TreeSet;
import java.util.Comparator;
import java.util.Random;
import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;
public class GettingTheTopN {
public static void main(String[] args) {
int n = 5;
int[][] matrix = {{16, -20, 22, 19},
{ 2, 5, 6, 8},
{17, 25, 16, 19},
{ 7, 18, 4, 17}};
System.out.println("streamIt: \n "
+ Arrays.toString(streamIt(matrix,n)));
System.out.println("useSet: \n "
+ useSet(matrix,n));
System.out.println("useSetElements: \n "
+ useSetElements(matrix,n));
System.out.println();
System.out.println("--- Testing performance ---");
timeMethod(() -> System.out.println("streamIt: \n "
+ Arrays.toString(streamIt(matrix,n))));
timeMethod(() -> System.out.println("useSet: \n "
+ useSet(matrix,n)));
timeMethod(() -> System.out.println("useSetElements: \n "
+ useSetElements(matrix,n)));
timeMethod(() -> System.out.println("ArvindKumarAvinash: \n "
+ Arrays.toString(ArvindKumarAvinash(matrix,n))));
timeMethod(() -> System.out.println("AnuragJain: \n "
+ AnuragJain(matrix,n)));
timeMethod(() -> System.out.println("MichaelChatiskatzi: \n "
+ Arrays.toString(MichaelChatiskatzi(matrix,n))));
System.out.println();
System.out.println("--- Testing performance with largeMatrix---");
Random random = new Random();
int[][] largerMatrix =
IntStream.range(0,10000) // 10000 on the first dimension
.mapToObj(i -> random.ints(0,128) // values between 0 and 128 (not included)
.limit(10000) // 10000 on the second dimension
.toArray()) // make the second 1D arrays
.toArray(int[][]::new); // put them into a 2D array
timeMethod(() -> System.out.println("streamIt: \n "
+ Arrays.toString(streamIt(largerMatrix,n))));
timeMethod(() -> System.out.println("useSet: \n "
+ useSet(largerMatrix,n)));
timeMethod(() -> System.out.println("useSetElements: \n "
+ useSetElements(largerMatrix,n)));
timeMethod(() -> System.out.println("ArvindKumarAvinash: \n "
+ Arrays.toString(ArvindKumarAvinash(largerMatrix,n))));
timeMethod(() -> System.out.println("AnuragJain: \n "
+ AnuragJain(largerMatrix,n)));
timeMethod(() -> System.out.println("MichaelChatiskatzi: \n "
+ Arrays.toString(MichaelChatiskatzi(largerMatrix,n))));
}
public static Integer[] streamIt(int[][] matrix, int n){
Integer[] result =
Arrays.stream(matrix) // stream the arrays
// This is the same as using .flatMaptoInt(..) and then .boxed()
.flatMap(a -> Arrays.stream(a) // stream the array in arrays
.mapToObj(i -> Integer.valueOf(i))) // turn the ints into Integers
.sorted(Comparator.reverseOrder()) // sort by higest values
.limit(n) // only pick n
.toArray(i -> new Integer[i]); // put then in Integer array
return result;
}
public static Set<Integer> useSet(int[][] matrix, int n){
TreeSet<Integer> max = new TreeSet<>(Comparator.<Integer>naturalOrder().reversed());
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
// Keep adding values until there's n elements in the Set
if (max.size() < n) {
max.add(matrix[i][j]);
} else {
// if the new value is higher than the lowest value
// ..and the new values isn't already there.
if (max.last() < matrix[i][j] && !max.contains(matrix[i][j])) {
max.pollLast();
max.add(matrix[i][j]);
}
}
}
}
return max;
}
public static Set<Element> useSetElements(int[][] matrix, int n){
TreeSet<Element> maxElement = new TreeSet<>();
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
if (maxElement.size() < n) {
maxElement.add(new Element(matrix[i][j],i,j));
} else {
if (maxElement.last().value < matrix[i][j]) {
maxElement.pollLast();
maxElement.add(new Element(matrix[i][j],i,j));
}
}
}
}
return maxElement;
}
// ----------------- Performance
static void timeMethod(Runnable toRun){
long start = System.nanoTime();
try{
toRun.run();
} finally {
long end = System.nanoTime();
System.out.println(" Time: " + (end - start)/1.0e6 + " miliseconds");
}
}
// [Answer to "How to find first 5 highest value in a two dimensional array?"](https://stackoverflow.com/a/65374950/12695027) by [Arvind Kumar Avinash](https://stackoverflow.com/users/10819573/arvind-kumar-avinash)
static int[] ArvindKumarAvinash(int[][] matrix, int MAX_N) {
// Find count as the total number of elements
int count = 0, row, col;
for (row = 0; row < matrix.length; row++) {
count += matrix[row].length;
}
// Create flattened = new int[count] and fill it with all elements of matrix[][]
int[] flattened = new int[count];
int i = 0;
for (row = 0; row < matrix.length; row++) {
for (col = 0; col < matrix[row].length; col++) {
flattened[i++] = matrix[row][col];
}
}
// Create max = new int[MAX_N] to store maximum n numbers.
// Also, create maxPos = new int[MAX_N] to store the position of the maximum numbers.
int[] max = new int[MAX_N];
int[] maxPos = new int[MAX_N];
// Loop MAX_N times. In each iteration, assume flattened[0] is the largest number.
for (i = 0; i < max.length; i++) {
max[i] = flattened[0];
for (int j = 1; j < flattened.length; j++) {
// If flattened[j] >= max[i], check if the position, j has already been
// processed. If not assign flattened[j] to max[i] and j to maxPos[i].
if (flattened[j] >= max[i]) {
boolean posAlreadyProcessed = false;
for (int k = 0; k <= i; k++) {
if (maxPos[k] == j) {
posAlreadyProcessed = true;
break;
}
}
if (!posAlreadyProcessed) {
max[i] = flattened[j];
maxPos[i] = j;
}
}
}
}
return max;
// System.out.println("Largest " + MAX_N + " values: " + Arrays.toString(max));
}
// [Answer to "How to find first 5 highest value in a two dimensional array?"](https://stackoverflow.com/a/65380541/12695027) by [Anurag Jain](https://stackoverflow.com/users/5825625/anurag-jain)
static List<Integer> AnuragJain(int[][] matrix, int n) {
List<Integer> allVal = new ArrayList<>();
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
allVal.add(matrix[i][j]);
}
}
allVal = allVal.stream()
.sorted(Comparator.reverseOrder())
.limit(n).collect(Collectors.toList());
return allVal;
// System.out.println(allVal);
}
// [Answer to "How to find first 5 highest value in a two dimensional array?"](https://stackoverflow.com/a/65379921/12695027) by [Michael Chatiskatzi](https://stackoverflow.com/users/11263320/michael-chatiskatzi)
static int[] MichaelChatiskatzi(int[][] matrix, int n) {
// int[] highestNumbers = new int[5];
int[] highestNumbers = new int[n];
Arrays.fill(highestNumbers, Integer.MIN_VALUE);
for (int row = 0; row < matrix.length; row++) {
for (int column = 0; column < matrix[row].length; column++) {
int currentEntry = matrix[row][column];
if (currentEntry > highestNumbers[0]) {
highestNumbers[0] = currentEntry;
Arrays.sort(highestNumbers);
}
}
}
return highestNumbers;
// System.out.println(Arrays.toString(highestNumbers));
}
}
// -------------------------------------------
// -------------------------------------------
class Element implements Comparable<Element> {
final int value;
final int x;
final int y;
static Comparator<Element> comparator =
Comparator.comparing((Element e) -> e.value)
.thenComparing((Element e) -> e.x)
.thenComparing((Element e) -> e.y)
.reversed();
Element(int value, int x, int y) {
this.value = value;
this.x = x;
this.y = y;
}
public int compareTo(Element that){
return comparator.compare(this, that);
}
public String toString(){
return value + " at [" + x + "][" + y + "]";
}
}
Let MAX_N = 5.
Find count as the total number of elements in matrix[][].
Create flattened = new int[count] and fill it with all elements of matrix[][].
Create max = new int[MAX_N] to store maximum n numbers. Also, create maxPos = new int[MAX_N] to store the position of the maximum numbers.
Loop MAX_N times and in each iteration, assume flattened[0] is the largest number.
If flattened[j] >= max[i], check if the position, j has already been processed. If not assign flattened[j] to max[i] and j to maxPos[i].
Demo:
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
final int MAX_N = 5;
int[][] matrix = {
{16, -20, 11, 19},
{2, 5, 6, 8},
{17, 25, 16, 19},
{7, 17, 4, 17}};
// Find count as the total number of elements
int count = 0, row, col;
for (row = 0; row < matrix.length; row++) {
count += matrix[row].length;
}
// Create flattened = new int[count] and
// fill it with all elements of matrix[][]
int[] flattened = new int[count];
int i = 0;
for (row = 0; row < matrix.length; row++) {
for (col = 0; col < matrix[row].length; col++) {
flattened[i++] = matrix[row][col];
}
}
// Create max = new int[MAX_N] to store maximum
// n numbers. Also, create maxPos = new int[MAX_N]
// to store the position of the maximum numbers.
int[] max = new int[MAX_N];
int[] maxPos = new int[MAX_N];
// Loop MAX_N times. In each iteration,
// assume flattened[0] is the largest number.
for (i = 0; i < max.length; i++) {
max[i] = flattened[0];
for (int j = 1; j < flattened.length; j++) {
// If flattened[j] >= max[i], check if the
// position, j has already been processed.
// If not assign flattened[j] to max[i]
// and j to maxPos[i].
if (flattened[j] >= max[i]) {
boolean posAlreadyProcessed = false;
for (int k = 0; k <= i; k++) {
if (maxPos[k] == j) {
posAlreadyProcessed = true;
break;
}
}
if (!posAlreadyProcessed) {
max[i] = flattened[j];
maxPos[i] = j;
}
}
}
}
System.out.println("Largest " + MAX_N +
" values: " + Arrays.toString(max));
}
}
Output:
Largest 5 values: [25, 19, 19, 17, 17]
With Java8 streams it can be done with this (one) line of code. It will leave the original matrix untouched.
Arrays.stream(matrix) // create a stream of the matrix
.flatMapToInt(Arrays::stream) //Reduce 2d matrix to 1d
.boxed() //Convert int to Integer so we can sort reversed order
.sorted(Collections.reverseOrder()) //sort array in reversed order highest first
.limit(5) //Limit stream to 5 entries, the five top results
.forEach(System.out::println); //Print the result
Now that the question is open again, I will present my comment as an answer.
Instead of iterating over the same matrix multiple times I fill the int[] highestNumbers with Integer.MIN_VALUE, iterate over the matrix once, and replace the smallest entry of max each time the current integer is greater, by updating the first entry of highestNumbers and sort it.
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[][] matrix = {
{10, -5, 15},
{8, 20, 12},
{27, -3, 14},
{7, 17, 4}};
int[] highestNumbers = new int[5];
Arrays.fill(highestNumbers, Integer.MIN_VALUE);
for (int row = 0; row < matrix.length; row++) {
for (int column = 0; column < matrix[row].length; column++) {
int currentEntry = matrix[row][column];
if (currentEntry > highestNumbers[0]) {
highestNumbers[0] = currentEntry;
Arrays.sort(highestNumbers);
}
}
}
System.out.println(Arrays.toString(highestNumbers));
}
}
Output:
[14, 15, 17, 20, 27]
Without sorting array itself, you can make sorted the stream over this array. Or you can implement a kind of selection sort in descending order. These two code examples do the same thing - find the first 5 highest distinct values in 2D array, if they are present:
int[][] arr = {
{1, 4, 7, 7},
{2, 5, 8, 3},
{5, 5, 1, 2},
{3, 6, 0, 9}};
int[] max = Arrays.stream(arr)
.flatMapToInt(Arrays::stream)
.boxed().sorted(Comparator.reverseOrder())
.mapToInt(Integer::intValue)
.distinct()
.limit(5)
.toArray();
System.out.println(Arrays.toString(max)); // [9, 8, 7, 6, 5]
int[][] arr = {
{1, 4, 7, 7},
{2, 5, 8, 3},
{5, 5, 1, 2},
{3, 6, 0, 9}};
int[] max = new int[5];
for (int m = 0; m < max.length; m++) {
int prev_max = m > 0 ? max[m - 1] : Integer.MAX_VALUE;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
if (arr[i][j] > max[m] && prev_max > arr[i][j]) {
max[m] = arr[i][j];
}
}
}
}
System.out.println(Arrays.toString(max)); // [9, 8, 7, 6, 5]
See also: Selection sort of array
You can use below way this will give you below benefits:
Keeping very simple logic, As you want highest 5 values and you will not loose any index location/order for existing array,
Using this you will get better performance,
Clean Code.
public static void main(String[] args) {
int[][] matrix = {
{10, -5, 15},
{8, 20, 12},
{27, -3, 14},
{7, 17, 4}};
List<Integer> allVal = new ArrayList<>();
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
allVal.add(matrix[i][j]);
}
}
allVal = allVal.stream()
.sorted(Comparator.reverseOrder())
.limit(5)
.collect(Collectors.toList());
System.out.println(allVal);
}
Output:
[27, 20, 17, 15, 14]

To Find Leaders in an array

Write a program to print all the LEADERS in the array. An element is leader if it is greater than all the elements to its right side. And the rightmost element is always a leader. For example int the array {16, 17, 4, 3, 5, 2}, leaders are 17, 5 and 2.
Let the input array be arr[] and size of the array be size.
o/p what i am getting is 2 5 17
Note: i want o/p in reverse order , also one below other(line break).
class LeadersInArray
{
/* Java Function to print leaders in an array */
void printLeaders(int arr[], int size)
{
int max_from_right = arr[size-1];
/* Rightmost element is always leader */
System.out.print(max_from_right + " ");
for (int i = size-2; i >= 0; i--)
{
if (max_from_right < arr[i])
{
max_from_right = arr[i];
System.out.print(max_from_right + " ");
}
}
}
public static void main(String[] args)
{
LeadersInArray lead = new LeadersInArray();
int arr[] = new int[]{16, 17, 4, 3, 5, 2};
int n = arr.length;
lead.printLeaders(arr, n);
}
}
Expected output:
17
5
2
Intead of printing those within the loop, add those to a list, and then print those separately.
Following are the changes in your code.
class LeadersInArray {
List<Integer> printLeaders(int[] arr, int size) {
List<Integer> list = new ArrayList<>();
int max_from_right = arr[size - 1];
list.add(max_from_right);
for (int i = size - 1; i >= 0; i--) {
if (max_from_right < arr[i]) {
max_from_right = arr[i];
list.add(max_from_right);
}
}
return list;
}
public static void main(String[] args) {
LeadersInArray lead = new LeadersInArray();
int arr[] = new int[]{16, 17, 4, 3, 5, 2};
List<Integer> integers = lead.printLeaders(arr, arr.length);
for(int i = integers.size()-1; i>=0 ;i--){
System.out.println(integers.get(i));
}
}
}

Inserting numbers from one array to an exact position on another one, (Java)

My goal is to insert array B[] into array A[] after the element with index K.
I don't need to lengthen the A[], the last 5 elements should just disappear.
This is what I got so far. Dont really mind the beginning of the program, thats just some extra requirements I had to do determine the arrays.
For example :
If I insert Kas 2, than array A is
0 2 4 6 8 10 12 14 16 18 0 0 0 0 0, and array B is 20 40 60 80 100.
The final array A should look like this:
0 2 4 20 40 60 80 100 6 8 10 12 14 16 18
public static void main(String[] args) {
int A[] = new int [15];
int B[] = new int [5];
int K, i, j;
Scanner sc = new Scanner(System.in);
Random r = new Random();
for (i=10; i<=14; i++) {
A[i] = 0;
}
System.out.println("Matīss Lavrinovičs RDBD0 171RDB075");
System.out.print("K=");
if (sc.hasNextInt())
K = sc.nextInt();
else {
System.out.println("input-output error");
sc.close();
return;
}
sc.close();
if (K<0 || K>9) {
for (i=0; i<=9; i++)
A[i] = r.nextInt(50);
for (j=0; j<=4; j++)
B[j] = r.nextInt(100 - 50) + 50; }
else
for (i=0; i<=9; i++)
A[i] = i*K;
for (j=0;j<=4;j++)
B[j] = 10*(j+1)*K;
System.out.print("A: ");
i = 0;
while (i < 15) {
System.out.print(" " + A[i]);
if (i==14) System.out.println();
i = i + 1;
}
System.out.print("B: ");
j = 0;
while (j < 5) {
System.out.print(" " + B[j]);
j = j + 1;
}
do {
} while;
You can use System.arrayCopy:
int[] a = new int[] { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 0, 0, 0, 0, 0 };
int[] b = new int[] { 20, 40, 60, 80, 100 };
int k = 2;
System.arraycopy(a, k + 1, a, k + 1 + b.length, a.length - b.length - k - 1);
System.arraycopy(b, 0, a, k + 1, b.length);
What happens is that we first copy the values after index #2 b.length places to the right (which is five). Then we copy the values of b into array a at the correct positions.
Alternative approach:
List<Integer> list = asList(a).subList(0, a.length - b.length);
list.addAll(k + 1, asList(b));
And a little helper method:
private static List<Integer> asList(int... ints) {
return IntStream.of(ints)
.boxed()
.collect(Collectors.toList());
}
You should take the following into consideration:
You should stick to the Java Naming Conventions: variable names start with a lowercase letter.
Omitting curling brackets {} like that often leads to bugs in the code. You should always use them.
One way to use System.arrayCopy to copy from array b[] to array a[] from position k
int[] a = new int[] { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 0, 0, 0, 0, 0 };
int[] b = new int[] { 20, 40, 60, 80, 100 };
int k = 1;
int length = (a.length - k) > b.length ? b.length : (a.length - k);
System.arraycopy(b, 0, a, k, length);
Take care: In case array b[] does not fit in the remaining space in array a[] and as you said you don't want to lengthen array a[], only copy until there is space left (calculate int length with the ternary conditional operator).

JAVA array concatenation from two different arrays

How to concatenate each and every number from 2 arrays and then give the output individually of the new no. formed?
Example:
arr1[1,2,3]
arr2[2,3,5]
output: [12,13,15,22,23,25,32,33,33,35]
Here's another way of doing it that doesn't involve using String.
public static void main(String[] args)
{
int[] arr1 = { 1, 2, 3 };
int[] arr2 = { 2, 3, 5 };
int[] arr = concat(arr1, arr2);
System.out.println(Arrays.toString(arr));
}
static int[] concat(int[] arr1, int[] arr2)
{
int i = 0;
int[] arr = new int[arr1.length * arr2.length];
for (int n2 : arr2)
{
int pow10 = (int) Math.pow(10, nDigits(n2));
for (int n1 : arr1)
{
arr[i++] = n1 * pow10 + n2;
}
}
return arr;
}
static int nDigits(int n)
{
return (n == 0) ? 1 : 1 + (int) Math.log10(n);
}
Output:
[12, 22, 32, 13, 23, 33, 15, 25, 35]
Use a for loop inside of a for loop. Then concatenate the item from arr and the item from arr2. I used an ArrayList but you could use a normal array if you know the resultant length of the array.
String[] arr = new String[]{"1", "2", "3"};
String[] arr2 = new String[]{"2", "3", "5"};
List<String> res = new ArrayList<>();
for (int i = 0; i < arr.length; i++){
for (int j = 0; j < arr2.length; j++) {
res.add(arr[i] + arr2[j]);
}
}
System.out.println(res.toString());
The result is:
[12, 13, 15, 22, 23, 25, 32, 33, 35]
If you just want to display the contents of the two array in the form you have given above you can always try doing this instead of concatinating it.
public class ArrayQuestion {
public static void main(String[] args) {
int arr1[] = {1,2,3};
int arr2[] = {2,3,5};
for(int i=0;i<arr1.length;i++) {
for(int j=0;j<arr2.length;j++) {
System.out.print(arr1[i]);
System.out.print(arr2[j]);
System.out.println();
}
}
}
}
Output :
12
13
15
22
23
25
32
33
35

Arrays-odds and evens to determine how many of the values in the array are odd and how many are even

I'm trying to find the evens and odds of an array for practice.
Sample Data :
2 4 6 8 10 12 14
1 2 3 4 5 6 7 8 9
2 10 20 21 23 24 40 55 60 61
Sample Output :
Odds - []
Evens - [2, 4, 6, 8, 10, 12, 14]
Odds - [1, 3, 5, 7, 9]
Evens - [2, 4, 6, 8]
Odds - [21, 23, 55, 61]
Evens - [2, 10, 20, 24, 40, 60]
And here is my code so far:
import java.util.Scanner;
public class OddsAndEvens
{
private static int countEm(int[] array, boolean odd)
{
int count = 0;
int dum = 0;
for(int i=0; i< array.length; i++)
{
dum = array[i] / 2;
if(dum == 0 )
{
count++;
}
}
return count;
}
public static int[] getAllEvens(int[] array)
{
int numberEvens=0;
for(int i =0; i<array.length; i++)
{
if(array[i]%2 ==0)
{
numberEvens++;
}
}
int[] evens = new int[array.length - countEm(array,false)];
int count=0;
for(int i=0; i<array.length; i++)
{
if(array[i]%2==0)
{
evens[count] = array[i];
count++;
}
}
return evens;
}
public static int[] getAllOdds(int[] array)
{
int numberEvens = 0;
for (int i = 0; i < array.length; i++)
{
if (array[i] % 2 == 0)
{
numberEvens++;
}
}
return null;
}
}
But I been getting errors in my output. These errors are the fact I am getting zeros in my output .
I'm just starting out and I'm hoping anyone can help me.
Your main problem comes from your countEm method. It is also the reason for all the extra zeroes behind your array. By doing minimal changes can solve these problems and make your program work.
One of the major careless mistake is that you used / instead of % for checking evens and odds in your countEm method.
Your countEm method is incomplete
Using wrong operator to count even/odd
Your incomplete countEm method now only counts the number of even number no matter the Boolean value is true or false. I've helped you implemented the complete countEm:
private static int countEm(int[] array, boolean odd)
{
int numEven = 0;
int numOdd = 0;
for(int i=0; i< array.length; i++)
if(array[i] % 2 == 0 ) //You used / instead of % earlier!
numEven++;
else
numOdd++;
if(odd)
return numOdd;
else
return numEven;
}
Make the above changes, I am sure it will work. Of course, you haven't complete your method for getting getAllOdds yet. Above changes will make your getAllEvens work properly.
Alternatively, for myself, I like to write it this way. I prefer shorter codes:
private static int countEm(int[] array, boolean odd)
{
int numEven = 0;
for(int i=0; i< array.length; i++)
if(array[i] % 2 == 0 )
numEven++;
return odd?array.length-numEven:numEven;
}
I prevent using data structures like array list because when I see such questions, I know what are the only things you are allowed to use.
I think this would be the best way to do that:
import java.util.ArrayList;
import java.util.List;
public class EvensAndOdds {
public static List<Integer> getOdds(int[] numbers){
List<Integer> odds = new ArrayList<>();
for(int i = 0; i < numbers.length; i++){
if((numbers[i]%2) != 0){
odds.add(numbers[i]);
}
}
return odds;
}
public static List<Integer> getEvens(int[] numbers){
List<Integer> evens = new ArrayList<>();
for(int i = 0; i < numbers.length; i++){
if((numbers[i]%2) == 0){
evens.add(numbers[i]);
}
}
return evens;
}
public static void main(String[] args){
int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
List<Integer> evens = getEvens(numbers);
List<Integer> odds = getOdds(numbers);
System.out.println("Evens: ");
for(Integer even: evens){
System.out.print(even.toString() + " ");
}
System.out.println("");
System.out.println("Odds: ");
for(Integer odd: odds){
System.out.print(odd.toString() + " ");
}
}
}
What about ;):
public class EvenOddSorter {
public void sort(int[] numbers) {
Arrays.sort(numbers,new Comparator<int>() {
#Override
public int compare(int i, int y) {
if(i % 2 == 0)
return -1;
if(y % 2 == 0)
return 1;
return 0;
}
});
}
}
then extract odds and evens from your array by finding the first odd number and using
int[] evens = Arrays.copyOfRange(numbers, 0, numberOfFirstOdd);
int[] odds = Arrays.copyOfRange(numbers, numberOfFirstOdd, numbers.length)
;)
You are creating a new array with too many initial items - hence the zeros at the end. Your getAllEvens() method could look more like:
public static int[] getAllEvens(int[] array)
{
int numberEvens = 0;
for (int i = 0; i < array.length; i++)
{
if (array[i] % 2 == 0)
{
numberEvens++;
}
}
int[] evens = new int[numberEvens]; // This has changed
int count = 0;
for (int i = 0; i < array.length; i++)
{
if (array[i] % 2 == 0)
{
evens[count] = array[i];
count++;
}
}
return evens;
}
This creates a new array with exactly the number of items you are about to populate it with.
Edit: To address your comment, here is my main() method and the output from the method above.
public static void main(String[] args)
{
int[] input =
{
2, 4, 6, 8, 10, 12, 14,
1, 2, 3, 4, 5, 6, 7, 8, 9,
2, 10, 20, 21, 23, 24, 40, 55, 60, 61
};
int[] evens = getAllEvens(input);
System.out.println(Arrays.toString(evens));
}
Which gives
[2, 4, 6, 8, 10, 12, 14, 2, 4, 6, 8, 2, 10, 20, 24, 40, 60]

Categories

Resources