package myArray;
// https://github.com/javadevelopcom/ArrayVsArrayList/blob/master/src/myArray/MatrixMinMax.java
public class MatrixMinMax {
public static void matrixMinMax() {
System.out.println("Matrix is a rectangular array of numbers, symbols, or expressions:" + "\n");
int[][] matrix = {
{10, 10, 10, 10, -10},
{20, 20, 20, -20, 20},
{30, 30, -30, 30, 30},
{40, -40, 40, 40, 40},
{-50, 50, 50, 50, 50}};
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix.length; j++) System.out.print(matrix[i][j] + " ");
System.out.println();
}
int min = matrix[0][0];
int max = matrix[0][0];
for (int[] ints : matrix) {
for (int i : ints) {
if (i < min) {
min = i;
}
if (i > max) {
max = i;
}
}
}
System.out.println("MIN: " + min);
System.out.println("MAX: " + max);
}
}
Matrix Array min max, Two-dimensional array
Although this is mere speculation, depending on overall context, it would be possible not to search maximum and minimum in the actual data member
int[][] matrix
but use some custom method to set entries; this method would perform some check against additional members
int maximum = Integer.MIN_VALUE;
int minimum = Integer.MAX_VALUE;
and replace them if necessary. Such a method could be implemented as follows, and maximum and minimum would be accessible in the members above.
void setEntry(int i, int j, in value)
{
matrix[i][j] = value;
minimum = Math.min(value, minimum);
maximum = Math.max(value, maximum);
}
However, this approach basically would trade the time for searching the matrix for time setting up the matrix entries.
i think you can't do better then O(n^2) ; since the numbers are not sorted , or do not have any particular property (like all of them fit into a certain range, for example), you must access every single number, to make sure if it does/doesn't modify the value of the existing maximum/minimum. accessing all the numbers gives n^2 operations
One of the approach is to convert a two dimensional array to 1D list and use Stream API to get the min and max value.
We would have use Integer array as against int array in the above code. Consider the following implementation. The number of lines of code is decreased.
Integer[][] matrix = {
{10, 10, 10, 10, -10},
{20, 20, 20, -20, 20},
{30, 30, -30, 30, 30},
{40, -40, 40, 40, 40},
{-50, 50, 50, 50, 50}};
List<Integer> list = new ArrayList<Integer>();
for (Integer[] array : matrix)
list.addAll(Arrays.asList(array));
int max = list.stream().max((p1, p2) -> p1.compareTo(p2)).get().intValue();
int min = list.stream().min((p1, p2) -> p1.compareTo(p2)).get().intValue();
System.out.println("MIN: " + min);
System.out.println("MAX: " + max);
This isn't exactly the answer to the question but I think it sheds some light and gives some theoretical improvement.
If you want a O(n) complexity time, you should change you nested iteration for-loop:
//in O(n^2)
for (int[] ints : matrix) {
for (int i : ints) {
if (i < min) {
min = i;
}
if (i > max) {
max = i;
}
}
}
To something like:
for(i = 0; i<(X*Y); i++)
In you case X = 5,Y = 5; and then iterate.
Or you can easilly use lambdas to find the min and max of your array like below :
public int getTheMaxOfRow(int matrix[][], int row) {
return Arrays.stream(matrix).skip(row).limit(1).flatMapToInt(d -> Arrays.stream(d)).max().getAsInt();
}
public int getTheMinOfRow(int matrix[][], int row) {
return Arrays.stream(matrix).skip(row).limit(1).flatMapToInt(d -> Arrays.stream(d)).min().getAsInt();
}
Related
This question already has answers here:
Finding the index number of the lowest value in an array
(4 answers)
Closed 3 years ago.
I've managed to find the lowest value in the array with my "lowest" variable, but im looking for the index which corresponds to the lowest value in the array. Any ideas?
public class Marathon {
public static void main(String[] args) {
String[] names = { "Elena", "Thomas", "Hamilton", "Suzie", "Phil",
"Matt", "Alex", "Emma", "John", "James", "Jane",
"Emily", "Daniel", "Neda", "Aaron", "Kate" };
int[] times = { 341, 273, 278, 329, 445, 402, 388, 275, 243, 334,
412, 393, 299, 343, 317, 265 };
for (int i = 0; i < names.length; i++) {
System.out.println(names[i] + ": " + times[i]);
}
lowesttime(names, times);
}
public static void lowesttime(String names[], int times[]) {
int lowest;
lowest = times[0];
for (int i = 1; i < times.length; i++) {
if (times[i] < lowest) {
lowest = times[i];
}
}
System.out.println(lowest);
// to access arrays names[?], times[?}
// System.out.println(names[lowest] + ": " + times[lowest]);
}
}
public static void lowesttime(String[] names, int[] times) {
Pair<Integer, Integer> min = IntStream.range(0, times.length)
.mapToObj(i -> new Pair<Integer, Integer>(i, times[i]))
.reduce(new Pair<>(-1, Integer.MAX_VALUE), (r, p) ->
r.getKey() == -1 || r.getValue() > p.getValue() ? p : r);
String minName = p.getKey() == -1 ? "nobody" : names[p.getKey()];
System.out.printf("Found minimum for %s at index %d, value %d%n",
minName, min.getKey(), min.getValue());
}
I wanted to show using a Stream:
IntStream.range(0, N) will give a stream of 0, 1, 2, ..., N-1. The indices.
mapToObj converts to a Stream<Pair<Integer, Integer>> where the pairs key is the index, and the pairs value is times[index].
reduce will start with an initial pair (-1, Integer.MAX_VALUE) as result,
and then for every pair in the stream whether a better minimum can be found.
Note you could just use a pair of name and time (Pair<String, Integer>); the index is not needed.
It here might be too advanced and circumstantial, but it is both very expressive and clean (using steps without needing local variables).
You can set a variable to the index of the element, instead of just getting the value of that element;
public static void lowesttime(String[] names, int[] times) {
int lowest;
int lowestIndex = 0;
lowest = times[0];
for (int i = 1; i < times.length; i++) {
if (times[i] < lowest) {
lowest = times[i];
lowestIndex = i;
}
}
System.out.println(lowest);
System.out.println(lowestIndex);
// to access arrays names[?], times[?}
// System.out.println(names[lowest] + ": " + times[lowest]);
}
If you already know your lowest value, you can use:
java.util.Arrays.asList(theArray).indexOf(lowestValue)
I recently got this question in an interview:
Given an array find two numbers that have the maximum sum which is also an element in the array.
Input: 6 10 12 34 41 16
Output: 16
[Updated]My code below:
public class Solution {
public static int findMaximumNumbers(int a[])
{
Set<Integer> set=new HashSet<>();
for(int n:a) set.add(n);
Arrays.sort(a);
int max=Integer.MIN_VALUE;
for(int i=a.length-1;i>0;i--)
{
for(int j=i;j>=0;j--)
{
int sum = a[i] + a[j];
if(set.contains(sum) && max<sum)
max=sum;
}
}
return max;
}
public static void main(String[] args) {
System.out.println( findMaximumNumbers(new int[]{ 6, 10, 12, 34, 40, 16, 41, 47, 74 }));
System.out.println( findMaximumNumbers(new int[]{ 2, 25, 35, 40, 42, 60 }));
}
}
This algorithm takes O(n^2) time complexity. Does anyone have a better algorithm for this?
This is the fastest I could come up with. Since the list is sorted, you work backwards, attempting to find if any pair adds up to the maximum remaining in the array (the i loop). It will short circuit as fast as possible, with the correct answer. In the j loop, counting down stops when you reach a value less than half of the target (no use iterating remaining values that can't add up to the target). But I am hopeful someone can do better. The OP code will do n*(n-1)/2 iterations, but this one will always do less, even when there is no solution.
public static int findMaximumNumbers(int a[])
{
Set<Integer> set=new HashSet<>();
for(int n:a) set.add(n);
Arrays.sort(a);
if (a[0] == 0)
return a[a.length-1];
for(int i=a.length-1;i>0;i--)
{
int j = i-1;
int m = a[i] / 2;
while (j >= 0 && a[j] > m) {
if (set.contains(a[i]-a[j]))
return a[i];
j--;
}
}
return -1;
}
If your numbers are integers in the range 1 to M, then you can do this in O(Mlog(M)) by:
Computing a histogram of the values
Using the fast fourier transform to perform a convolution
searching for the biggest value present in the convolution
Example Python code:
import scipy.signal
import time
def hist(X):
"""Prepare a histogram of X"""
h = [0]*(max(X)+1)
for x in X:
h[x] += 1
return h
A = [6, 10, 12, 34, 41, 16]
H = hist(A)
R = scipy.signal.fftconvolve(H,H)
for x in sorted(A,reverse=True):
if R[x] > 0.5:
print x
break
else:
print 'No solutions'
The point is that the convolution of the histograms is the histogram of all possible sums of elements.
Of course, if you have 100 numbers with values in the range 1 to 10**100, then this would be less efficient than your O(n^2) algorithm so this is only useful if the values are limited.
If you sort the array first, you can just check pair by pair in ascending order, adding two consecutive numbers and checking if it is contained in the array.
int myArray[];
Arrays.sort(myArray);
int a = -1, b, highest = Integer.MIN_VALUE;
for(int i = 0; i < myArray.length - 1; i++)
{
int sum = myArray[i] + myArray[i + 1];
int startCheck = i + 1;
while(myArray[startCheck] < sum && startCheck < myArray.length)
startCheck++;
if(myArray[startCheck] == sum && sum > highest)
{
a = i;
b = i + 1;
highest = sum;
}
}
// Found 2 elements whose sum is on the array
if(a != -1)
{
}
I'm working on an assignment and I need to perform a binary search. But somehow I think I have problems in my selection sort. Here i have an user defined class called Record. It has the following properties:
class Record{
String studentId;
int assignment;
int exam;
int total;
String grade;
}
I have getters for those properties. Now there is another class called GradeBook in which there is a an array of type Record. I manually loaded the record array via a method called loadFromTables as follows:
private void loadFromTables(){
String[] students = {
"S10","S20","S30","S40","S50", "S60",
"S08","S18","S28","S38","S48", "S58",
"S06","S16","S26","S36","S46", "S56",
};
int[] assignment = {
0, 10, 20, 30, 30, 40,
0, 10, 20, 30, 30, 40,
0, 10, 20, 30, 30, 40,
};
int[] exam = {
0, 39, 44, 44, 54, 59,
1, 40, 45, 45, 55, 60,
2, 41, 46, 46, 56, 58,
};
nrecords = students.length;
gradeBook = new Record[nrecords];
for (int i = 0; i < nrecords; i++ ) {
int t = assignment[i] + exam[i];
String g = calculateGrade(t);
Record r = new Record( students[i], assignment[i], exam[i], t, g );
gradeBook[i] = r;
}
}
Now I want to do binary search to find a Record by the property studentId. But first I'd have to sort the Record array. I am told to use Selection sort. So, I do this and I think this is where the problem lies but I can't seem to figure out where..:
private void sortById(){
//Selection Sort
for(int i=0; i<nrecords-1; i++){
int index = i;
for(int j=i+1; j<nrecords; j++){
if((gradeBook[index].studentId).compareTo(gradeBook[j].studentId) > 0){
index = j;
}
Record temp = gradeBook[i];
gradeBook[i] = gradeBook[index];
gradeBook[index] = temp;
}
}
}
And here is the code of binary search that I used although i think the binary search has been implemented correctly. Because i tried to do it with bubble sort and that did precisely what i wanted.
public Record find(String id){
//Binary Search
int low = 0;
int high = nrecords - 1;
Record record = null;
while(low <= high){
int mid = (high + low)/2;
if(id.compareTo(gradeBook[mid].studentId) == 0){
record = new Record(id, gradeBook[mid].assignment, gradeBook[mid].exam, gradeBook[mid].total, gradeBook[mid].grade);
return record;
}
else if(id.compareTo(gradeBook[mid].studentId) > 0){
low = mid + 1;
}
else if(id.compareTo(gradeBook[mid].studentId) < 0){
high = mid - 1;
}
}
return record;
}
Thanks in advance. I know the problem is in selection sort and it's eating my head. Appreciate your suggestions! :)
In selection sort, We first iterate through the sub-array and find the minimum element in the sub-array, then at last in each iteration, Swap the current and minimum element.
Problem in your code is here.
for(int j=i+1; j<nrecords; j++){
if((gradeBook[index].studentId).compareTo(gradeBook[j].studentId) > 0){
index = j;
}
Record temp = gradeBook[i];
gradeBook[i] = gradeBook[index];
gradeBook[index] = temp;
}
You have found minimum element correctly but you are doing swaps in the iterations when you find a lexicographic smaller string than the current one. So in this loop, you just need to find the minimum element and swap operation should be done after execution of this loop.
Corrected Code :
private void sortById(){
//Selection Sort
for(int i=0; i<nrecords-1; i++){
int index = i;
for(int j=i+1; j<nrecords; j++){
if((gradeBook[index].studentId).compareTo(gradeBook[j].studentId) > 0){
index = j;
}
Record temp = gradeBook[i];
gradeBook[i] = gradeBook[index];
gradeBook[index] = temp;
}
}
}
I am trying to make a code with two arrays. The second array has the same values of the first except for the smallest number. I have already made a code where z is the smallest number. Now I just want to make a new array without z, any feedback would be appreciated.
public static int Second_Tiny() {
int[] ar = {19, 1, 17, 17, -2};
int i;
int z = ar[0];
for (i = 1; i < ar.length; i++) {
if (z >ar[i]) {
z=ar[i];
}
}
}
Java 8 streams have built in functionality that can achieve what you're wanting.
public static void main(String[] args) throws Exception {
int[] ar = {19, 1, 17, 17, -2, -2, -2, -2, 5};
// Find the smallest number
int min = Arrays.stream(ar)
.min()
.getAsInt();
// Make a new array without the smallest number
int[] newAr = Arrays
.stream(ar)
.filter(a -> a > min)
.toArray();
// Display the new array
System.out.println(Arrays.toString(newAr));
}
Results:
[19, 1, 17, 17, 5]
Otherwise, you'd be looking at something like:
public static void main(String[] args) throws Exception {
int[] ar = {19, 1, 17, 17, -2, -2, -2, -2, 5};
// Find the smallest number
// Count how many times the min number appears
int min = ar[0];
int minCount = 0;
for (int a : ar) {
if (minCount == 0 || a < min) {
min = a;
minCount = 1;
} else if (a == min) {
minCount++;
}
}
// Make a new array without the smallest number
int[] newAr = new int[ar.length - minCount];
int newIndex = 0;
for (int a : ar) {
if (a != min) {
newAr[newIndex] = a;
newIndex++;
}
}
// Display the new array
System.out.println(Arrays.toString(newAr));
}
Results:
[19, 1, 17, 17, 5]
I think the OP is on wrong track seeing his this comment:
"I am trying to find out the second smallest integer in array ar[]. I
should get an output of 1 once I am done. The way I want to achieve
that is by making a new array called newar[] and make it include all
the indexes of ar[], except without -2."
This is a very inefficient way to approach this problem. You'll have to do 3 passes, Once to find to smallest indexed element, another pass to remove the element (this is an array so removing an element will require a full pass), and another one to find smallest one again.
You should just do a single pass algorithm and keep track of the smallest two integers,
or even better use a tree for efficiency. Here are the best answers of this problem:
Find the 2nd largest element in an array with minimum number of comparisons
Algorithm: Find index of 2nd smallest element from an unknown array
UPDATE: Here is the algorithm with OP's requirements,
3 passes, and no external libraries:
public static int Second_Tiny() {
int[] ar = {19, 1, 17, 17, -2};
//1st pass - find the smallest item on original array
int i;
int z = ar[0];
for (i = 1; i < ar.length; i++) {
if (z >ar[i]){
z=ar[i];
}
}
//2nd pass copy all items except smallest one to 2nd array
int[] ar2 = new int[ar.length-1];
int curIndex = 0;
for (i=0; i<ar.length; i++) {
if (ar[i]==z)
continue;
ar2[curIndex++] = ar[i];
}
//3rd pass - find the smallest item again
z = ar2[0];
for (i = 1; i < ar2.length; i++) {
if (z >ar2[i]){
z=ar2[i];
}
}
return z;
}
This grabs the index of the element specified in variable z and then sets a second array to the first array minus that one element.
Essentially this gives ar2 = ar1 minus element z
public static int Second_Tiny() {
int[] ar = {19, 1, 17, 17, -2};
int[] ar2;
int i;
int z = ar[0];
int x = 0;
for (i = 1; i < ar.length; i++) {
if (z >ar[i]){
z=ar[i];
x=i;
}
}
ar2 = ArrayUtils.remove(ar, x);
return(z);
}
below is my code which is throwing error:
Cannot invoke size() on the array type int[]
Code:
public class Example{
int[] array={1,99,10000,84849,111,212,314,21,442,455,244,554,22,22,211};
public void Printrange(){
for (int i=0;i<array.size();i++){
if(array[i]>100 && array[i]<500)
{
System.out.println("numbers with in range ":+array[i]);
}
}
Even i tried with array.length() it also throwing the same error. When i used the same with string_name.length() is working fine.
Why it is not working for an integer array?
The length of an array is available as
int l = array.length;
The size of a List is availabe as
int s = list.size();
I think you are confused between size() and length.
(1) The reason why size has a parentheses is because list's class is List and it is a class type. So List class can have method size().
(2) Array's type is int[], and it is a primitive type. So we can only use length
There is no method call size() with array. you can use array.length
Array's has
array.length
whereas List has
list.size()
Replace array.size() to array.length
public class Test {
int[] array = { 1, 99, 10000, 84849, 111, 212, 314, 21, 442, 455, 244, 554,
22, 22, 211 };
public void Printrange() {
for (int i = 0; i < array.length; i++) { // <-- use array.length
if (array[i] > 100 && array[i] < 500) {
System.out.println("numbers with in range :" + array[i]);
}
}
}
}
we can find length of array by using array_name.length attribute
int [] i = i.length;
Integer Array doesn't contain size() or length() method. Try the below code, it'll work. ArrayList contains size() method. String contains length(). Since you have used int array[], so it will be array.length
public class Example {
int array[] = {1, 99, 10000, 84849, 111, 212, 314, 21, 442, 455, 244, 554, 22, 22, 211};
public void Printrange() {
for (int i = 0; i < array.length; i++) {
if (array[i] > 100 && array[i] < 500) {
System.out.println("numbers with in range" + i);
}
}
}
}