Ths is a question from a past paper. I have been asked to create a static method arrayMin to find the smallest value in the array arr.
I have to use a while loop and on each iteration, the variable min will return the smallest number from the first i elements.
Is there a way to do this without calling another method/for loop and strictly using the while loop, as the question is only worth 4%(including writing loop invariants and javadoc). Not sure if I am overcomplicating the problem.
public class Revision {
public static int arr[] = new int[] { 5, 8, 4, 3, 6, 2 };
public static int min = 1;
public static int arrayMin() {
int i = 0;
if (arr == null) {
return 0;
} else {
while (i < arr.length) {
// some function/method call to find smallest number of arr[i]
i++;
return min;
}
}
return min;
}
public static void main(String[] args) {
System.out.println(arrayMin());
}
}
A couple of things:
The array shouldn't be static, you should pass it as a parameter to the arrayMin method;
min should be a local arrayMin variable, not static;
min should be initialized to Integer.MAX_VALUE. If you initialize it with 1, and 2 happens to be the min value of the array, you'll never return it;
You can't return multiple times from a method. As soon as you do return min, the method ends. There's probably some confusion over the the variable min will return the smallest number from the first i elements phrase. It probably means that in each iteration, the variable min will have (not return) the smallest number from the first i elements.
Here's a refactor:
public static int arrayMin(int[] arr) {
int i = 0;
int min = Integer.MAX_VALUE;
if (arr == null) {
return 0; // What if 0 is the minimum value? What do you want to do in this case?
} else {
while (i < arr.length) {
if (arr[i] < min) {
min = arr[i];
}
i++;
}
}
return min;
}
You need to have a variable outside of the loop called min. You will use the loop to find the minimum of the array, and return min when the loop is complete.
} else {
int min = Integer.MAX_VALUE;
while(i < arr.length) {
// is arr[i] < min? If so, it's the new minimum
i++;
}
return min;
}
multiple ways to do it, but here is one.
public static int arrayMin(int[] arr) {
boolean isFirstElement = true;
int smallestNumber= 0;
int index = 0;
while(index < arr.length) {
int temp= arr[index];
index++;
if (isFirstElement) {
smallestNumber = temp;
isFirstElement = false;
} else if (smallestNumber > temp) {
smallestNumber = temp;
}
}
}
You can use a index variable to keep in track of the number of positive hits and if the corresponding numbers index value is one lesser the array size, that number is the smallest
class testtt{
static int small=0;
public static void main(String[] args) {
int arr[] = {9,2,3,4,5,6,7,8};
int i,index=0;
for(int q:arr)
{
for(i=0;i<arr.length;i++)
{
if(q<arr[i])
{
small=q;
index++;
}
}
if(index==arr.length-1)
System.out.println(small);
}
}
}
Related
I have a problem with removig duplicate elements from an array in Java. I made two extra functions, one which counts how many unique elements there are and one which checks if the integer is already in the result array. Everything seems to work, but I fail a test where 0 is supposed to be 2nd in the array, but it's always moved to the end in my code. What can I do to fix this mistake?
Tester is showing this error:
Expected :is [<100>, <0>, <3>, <4>, <562>]
Actual :[<100>, <3>, <4>, <562>, <0>]
This is my code so far:
public static int[] removeDuplicates(int[] integers) {
int count = countUniques(integers);
int counter = 0;
int[] result = new int[count];
for (int integer : integers) {
Boolean isInArray = isInArray(result, integer);
if (!isInArray) {
result[counter] = integer;
counter++;
}
}
return result;
}
public static int countUniques(int[] integers) {
int i, j;
int count = 0;
for (i = 0; i < integers.length; ++i) {
for (j = 0; j < i; j++)
if (integers[i] == integers[j])
break;
if (i == j)
count++;
}
return count;
}
public static Boolean isInArray(int[] integers, int targetInteger) {
for (int integer : integers) {
if (targetInteger == integer) {
return true;
}
}
return false;
}
When you create a primitive int array it is by default filled with 0s. You can change your code to use an Integer object array. That way the default value for each element will be null.
You would then need to null check each element inside your isInArray():
public static Boolean isInArray(Integer[] integers, int targetInteger) {
for (Integer integer : integers) {
if (integer != null && targetInteger == integer) {
return true;
}
}
return false;
}
And change your result array to Integer[] result = new Integer[count]; and return Integer[] instead of int[].
If you want to return primitive array you can use streams and map Integer to int.
something like
return Arrays.stream(result).mapToInt(i-> i).toArray();
You haven't filled up the result array yet, so the end of it will be filled with zeros. You only want to loop over the part that you have filled. One way to achieve this is to pass the value of counter to your isInArray method.
public static int[] removeDuplicates(int[] integers) {
int count = countUniques(integers);
int counter = 0;
int[] result = new int[count];
for (int integer : integers) {
Boolean isInArray = isInArray(result, counter, integer);
if (!isInArray) {
result[counter] = integer;
counter++;
}
}
return result;
}
public static int countUniques(int[] integers) {
int i, j;
int count = 0;
for (i = 0; i < integers.length; ++i) {
for (j = 0; j < i; j++)
if (integers[i] == integers[j])
break;
if (i == j)
count++;
}
return count;
}
public static Boolean isInArray(int[] integers, int integersLength, int targetInteger) {
for (int i = 0; i < integersLength; i++) {
if (targetInteger == integers[i]) {
return true;
}
}
return false;
}
If you need to remove duplicates from an array, probably the simplest thing to do is to convert the array to a java.util.Set and then convert the set back to an array.
public int[] removeDups(int[] arr) {
Set<Integer> noDups = new HashSet<>(Arrays.stream(arr).boxed().collect(Collectors.toList()));
int[] newArr = noDups.stream().mapToInt(Integer::intValue).toArray();
return newArr;
}
This simplifies the process and eliminates additional issues like the one you are having with creating an array padded with zeros for the unused array index locations.
To count "unique", call this method and then return the created collection's size:
public int countUnique(int[] arr) {
return removeDups(arr).length;
}
This solution does not require the method isInArray; which by the way, should not be a public method. In my opinion, public methods should not invoke other public methods. The reason being is that requirement's change might cause the method with the dependency to break.
I have been tasked with writing a class with a non-empty array 'temperatures' which stores the temperatures of 365 days of a year.
My task is to write a method returning the day of the year with the lowest temperature.
For example, if the array temperatures = {0,0,-10,-10,0,......,0}. The corresponding result should be 3, despite there being two equal values with the lowest temperature of the set, as the 3rd day (second index) was the first to have the lowest value.
I have correctly written out the code, however, I'm unsure as to why, in my second If statement, it returns only the day with the lowest value and not all the days with the lowest value.
Here's my code
public static int coldest(double[] temperatures) {
double minimum = temperatures[0];
for (double temp : temperatures) {
if (temp < minimum) {
minimum = temp;
}
}
for (int i = 0; i < temperatures.length; i++) {
if (Math.abs(minimum - temperatures[i]) < 0.000000001) {
return i + 1;
}
}
return -1;
}
For example, if I define double[] a = {-5,2,-5,2,-5,......2};, surely within the second For Loop, it will return 1,3,5,7... as all those days satisfy the If criteria, rather than just 1.
I apologise if I haven't written my question very clear, this is my first time asking here.
My task is to write a method returning the day of the year with the
lowest temperature.
If it is the case, your logic is flawed e.g. the following condition doesn't make any sense:
if (Math.abs(minimum - temperatures[i]) < 0.000000001)
Do it as follows:
public class Main {
public static void main(String args[]) {
System.out.println(coldest(new double[] { 0, 0, -10, -10, 0, 0 }));
}
public static int coldest(double[] temperatures) {
if (temperatures == null || temperatures.length == 0) {
return -1;
}
double minimum = temperatures[0];
for (double temp : temperatures) {
if (temp < minimum) {
minimum = temp;
}
}
for (int i = 0; i < temperatures.length; i++) {
if (minimum == temperatures[i]) {
return i + 1;
}
}
return -1;
}
}
Output:
3
If your requirement is to get the list of all days with the minimum temperature, you need to return an array instead of a single value e.g.
import java.util.Arrays;
public class Main {
public static void main(String args[]) {
// Test
System.out.println(Arrays.toString(coldestDays(new double[] { 0, 0, -10, -10, 0, 0 })));
}
public static int[] coldestDays(double[] temperatures) {
if (temperatures == null || temperatures.length == 0) {
return new int[0];
}
double minimum = temperatures[0];
int count = 0;// To store the required size of the array
for (double temp : temperatures) {
if (temp < minimum) {
minimum = temp;
}
}
for (double t : temperatures) {
if (t == minimum) {
count++;
}
}
int[] minTemps = new int[count];// Create the array
int index = 0;
for (int i = 0; i < temperatures.length; i++) {
if (minimum == temperatures[i]) {
minTemps[index++] = i + 1;// Store the (index +1 ) of the minimum temperatures
}
}
return minTemps;
}
}
Output:
[3, 4]
I am not sure if you have reached to the level of using Java collections. If yes, you can use an ArrayList and in that case, you won't need to find the count of days with the minimum temperatures first in order to create an array of appropriate size.
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String args[]) {
// Test
System.out.println(coldestDays(new double[] { 0, 0, -10, -10, 0, 0 }));
}
public static List<Integer> coldestDays(double[] temperatures) {
if (temperatures == null || temperatures.length == 0) {
return new ArrayList<Integer>();
}
double minimum = temperatures[0];
List<Integer> days = new ArrayList<Integer>();
for (double temp : temperatures) {
if (temp < minimum) {
minimum = temp;
}
}
for (int i = 0; i < temperatures.length; i++) {
if (minimum == temperatures[i]) {
days.add(i + 1);// Store the (index +1 )of the minimum temperatures
}
}
return days;
}
}
Output:
[3, 4]
I think you might be confused about what the `return' statement actually does.
Its primary action is 'exit from this function', or more specifically, 'exit from the current invocation of this function'. From that, it should be clear enough that you can only do that once. Once you've exited, you've exited.
Its secondary action is to provide the value of the function invocation, i.e., what value is to be 'returned' to the caller. The function is declared to return some 'int' value (int coldest(...)) and the return statement provides that (single) int value.
Reason is return in second if statement breaks your for loop. I am suggesting you to this kind of solution. Instead of returning one int value, You can return list of Integer values:
public static List<Integer> coldest(double[] temperatures) {
double minimum = temperatures[0];
List<Integer> arrayList = new ArrayList<>();
for (double temp : temperatures) {
if (temp < minimum) {
minimum = temp;
}
}
for (int i = 0; i < temperatures.length; i++) {
if (Math.abs(minimum - temperatures[i]) < 0.000000001) {
arrayList.add((i + 1));
}
}
return arrayList;
}
I need to write a recursive method which looks through an array and finds the smallest index, however I am having a bizarre issue, for some reason my given test array seems to return a result of 10. I have tried debugging in eclipse and something very odd happens, my findMinAux method does indeed find -10 to be the smallest value and when I press the "step into" button it does seem as if it is about to return -10 but then it goes into some weird loop and startIndex starts increasing for some reason. If anyone has any advice as to where I am going wrong it would be greatly appreciated, thank you.
Here is my code:
public class Q1 {
public static void main(String[] args) {
int[] testArr = {12,32,45,435,-1,345,0,564,-10,234,25};
findMin(testArr);
}
public static int findMin(int[] arr) {
int result = findMinAux(arr,arr.length-1,arr.length-1);
System.out.println(result);
return result;
}
public static int findMinAux(int[] arr, int startIndex, int smallest) {
if(arr[startIndex]<smallest) {
smallest = arr[startIndex];
}
startIndex--;
if(startIndex>=0) {
findMinAux(arr,startIndex,smallest);
}
return smallest;
}
}
Two problems:
First, you should initiate smallest with the last element if you want to search from the end of array:
int result = findMinAux(arr,arr.length-1,arr[arr.length - 1]);
Secondly, you should reassign smallest:
if(startIndex>=0) {
smallest = findMinAux(arr,startIndex,smallest);
}
class Minimum {
int minelem;
int minindex;
Minimum() {
minelem = Integer.MAX_VALUE;
minindex = -1;
}
}
public class Q1 {
public static void main(String[] args) {
int[] testArr = {12,32,45,435,-1,345,0,564,-10,234,25};
findMin(testArr);
}
public static int findMin(int[] arr) {
Minimum m = new Minimum();
m = findMinAux(arr,arr.length-1,m);
System.out.println(m.minindex);
return m.minindex;
}
public static Minimum findMinAux(int[] arr, int lastindex, Minimum m) {
if(lastindex < 0) {
return m;
}
if(m.minelem > arr[lastindex]) {
m.minelem = arr[lastindex];
m.minindex = lastindex;
}
return findMinAux(arr,lastindex - 1, m);
}
}
I have used another class here for simplification. Please check if this solved your problem meanwhile I am explaining why and how it is working.
Actually, this implementation works fine
public static int findMinAux(int[] arr, int startIndex, int smallest) {
if(startIndex < 0)
return smallest;
if(arr[startIndex] < smallest){
smallest = arr[startIndex];
}
return findMinAux(arr, startIndex - 1, smallest);
}
And also you has a typo in calling this funtion, the last parameter must be an value from array, in your case the last value, not the last index.
int result = findMinAux(arr,arr.length-1, arr.length - 1);
change to
int result = findMinAux(arr,arr.length-2, arr[arr.length - 1]);
This approach works with a single method and an overloaded version so you don't have to pass the initial values
public static int findMin(int[] arr) {
int index = 0;
int min = Integer.MAX_VALUE;
min = Math.min(arr[index], min);
return findMin(arr,index+1,min);
}
private static int findMin(int[] arr, int index, int min) {
if(index < arr.length)
{
min = Math.min(arr[index], min);
return findMin(arr,index+1,min);
}
System.out.println(min);
return min;
}
The second method is private so from outside the class, only the first/default method can be called.
See this code. In every iteration, elements are compared with current element and index in increased on the basis of comparison. This is tail recursive as well. So it can be used in large arrays as well.
public class Q1 {
public static void main(String[] args) {
int[] testArr = {12, 32, 45, 435, -1, 345, 0, 564, -10, 234, 25};
System.out.println();
System.out.println(find(testArr, 0, testArr.length - 1, testArr[0]));
}
public static int find(int[] arr, int currPos, int lastPos, int elem) {
if (currPos == lastPos) {
return elem;
} else {
if (elem < arr[currPos]) {
return find(arr, currPos + 1, lastPos, elem);
} else {
return find(arr, currPos + 1, lastPos, arr[currPos]);
}
}
}
}
I'm trying to find the index of the smallest number but only after a certain point in the array.
The method that I'm working on is indexOfTheSmallestStartingFrom.
I'm doing mooc.fi exercise 104.3, if you need more information go to http://mooc.cs.helsinki.fi/programming-part1/material-2013/week-6?noredirect=1 and scroll down to exercise 104.
My question is, how do I start from, from example, index 2 in an array and ignore everything before it. I'm trying to find the smallest number in the array after the certain index.
My code
import java.util.Arrays;
public class Main {
public static int smallest(int[] array) {
int[] sorted = new int[array.length];
for (int i = 0; i < array.length; i++) {
sorted[i] = array[i];
}
Arrays.sort(sorted);
return sorted[0];
}
public static int indexOfTheSmallest(int[] array) {
for (int i = 0; i < array.length; i++) {
if (array[i] == smallest(array)) {
return i;
}
}
return 0;
}
// This is the method here.
public static int indexOfTheSmallestStartingFrom(int[] array, int index) {
for (int i = index; i < array.length; i++) {
if (array[i] == smallest(array)) {
return indexOfTheSmallest(array);
}
}
return 27;
}
public static void main(String[] args) {
// indexes: 0 1 2 3 4
int[] values = {-1, 6, 9, 8, 12};
System.out.println(indexOfTheSmallestStartingFrom(values, 1));
System.out.println(indexOfTheSmallestStartingFrom(values, 2));
System.out.println(indexOfTheSmallestStartingFrom(values, 4));
}
}
You can't use your smallest method when implementing indexOfTheSmallestStartingFrom, since the smallest element returned by smallest may be in the beginning of the array (i.e. in an index smaller than the passed index).
A much simpler implementation would be :
public static int indexOfTheSmallestStartingFrom(int[] array, int index) {
int minIndex = index;
for (int i = index; i < array.length; i++) {
if (array[i] < array[minIndex]) {
minIndex = i;
}
}
return minIndex;
}
indexOfTheSmallest is returning the index of the smallest element, while you are comparing it with the element value in indexOfTheSmallestStartingFrom.
==EDIT==
See #Eran 's answer for a better implementation.
I've tried to fix your code with as few as possible changes.
public class Main {
public static int smallestFrom(int[] array, int index) {
int[] sorted = new int[array.length-index];
for (int i = index; i < array.length; i++) {
sorted[i-index] = array[i];
}
Arrays.sort(sorted);
return sorted[0];
}
// This is the method here.
public static int indexOfTheSmallestStartingFrom(int[] array, int index) {
int smallest = smallestFrom( array, index);
for (int i = index; i < array.length; i++) {
if (array[i] == smallest ) {
return i;
}
}
return 27;
}
public static void main(String[] args) {
// indexes: 0 1 2 3 4
int[] values = {-1, 6, 9, 8, 12};
System.out.println(indexOfTheSmallestStartingFrom(values, 1));
System.out.println(indexOfTheSmallestStartingFrom(values, 2));
System.out.println(indexOfTheSmallestStartingFrom(values, 4));
}
}
smallest method has been changed to smallestFrom. smallestFrom computes the smallest value starting from index. Does that by making a copied array which contains only the values from index till end of the array.
indexOfTheSmallestStartingFrom first calls smallestFrom to get the smalles value in that subArray; then it iterates the array from index till it finds said smallest value. The index when the value is found is the one returned.
Eran's solution is way better. Less code and more efficient. This code exists only to help you get a better undestanding.
If an array contains 1,7,7,3,6 and if user asks what 2nd largest element is the output should be 7(not 6) since duplicate values are treated as distinct.
This is my code.
I am using Deterministic search to find the suitable pivot .
Its complexity is O(n).
I am stuck at the error generated by my code .
Please do help me.
import java.util.Random;
import java.util.Scanner;
public class deven {
public static void main(String args[]){
Scanner in=new Scanner(System.in);
int len=in.nextInt();
int n=in.nextInt();
int array[]=new int[len];
for (int i = 0; i < len; i++) {
array[i]=in.nextInt();
}
System.out.println(select(array,len,n));
}
static int below[];
static int above[];
static int pivot;
static int i;
static int j;
static int x;
static int y;
static int index;
static Random rand=new Random();
static int select(int array[],int len,int n){
if(len==1)
return array[0];
pivot=pivot(array, len);
below=new int[len];
above=new int[len];
//System.out.println("Block");
x=0;
y=0;
int temp=0;
for(i=0;i<len;i++){
if(array[i]>pivot){
below[x++]=array[i];
}
else if(array[i]<pivot){
above[y++]=array[i];
}
else {
if(temp!=0){
below[x++]=array[i];
}
temp=1;
}
}
i = x;
j = len - y;
if(n<i) return select(below,x,n);
else if(n>=j) return(select(above,y,n-j));
else return(pivot);
}
static int pivot(int array[],int len){
if(len==1){
return array[0];
}
int numOfGroups=len/5;
if(len%5!=0){
numOfGroups++;
}
int setOfMedians[]=new int[numOfGroups];
for (int i = 0 ; i < numOfGroups ; i++)
{
int[] subset;
if(array.length % 5 > 0)
{
if (i == numOfGroups - 1)
{
subset = new int[array.length % 5];
}
else
{
subset = new int[5];
}
}
else
{
subset = new int[5];
}
for (int j = 0; j < subset.length ; j++)
{
subset[j] = array[5*i+j];
}
setOfMedians[i] = median(subset);
}
int goodpivot=select(setOfMedians, numOfGroups,numOfGroups/2 );
return goodpivot;
}
static int median(int[] array)
{
if (array.length == 1)
{
return array[0];
}
int smallerCount = 0;
for (int i = 0 ; i < array.length ; i++)
{
for (int j = 0 ; j < array.length ; j++)
{
if (array[i] < array[j])
{
smallerCount++;
}
}
if (smallerCount == (array.length - 1)/2)
{
return array[i];
}
smallerCount = 0;
}
return -1;
}
}
Input
6
3
1 2 3 1 2 3
Output
Exception in thread "main" java.lang.StackOverflowError
at deven.pivot(deven.java:99)
at deven.select(deven.java:34)
at deven.pivot(deven.java:102)
at deven.select(deven.java:34)
at deven.select(deven.java:59)
at deven.select(deven.java:59)
at deven.select(deven.java:59)
If you maintained an equalsCount in addition to your smallerCount, you should be able to detect whether your candidate value is the median when it is also a duplicate.
(Explanation)
You appear to be deliberately returning -1 as an invalid value when your median method fails unexpectedly. It would be more proper to throw an exception of some sort, but what you really want is for it to never reach that point.
Your algorithm fails when the median is a duplicate. In the set { 1, 2, 2, 2, 3 }, for example, 2 is the obvious median, but there's never a point where there are exactly 2 values "smaller than" any of the values being verified.
If you count both smaller and equal values, then you can know your candidate to be a median if either your current test passes, or if the smaller count is less than the midpoint AND the smaller + equal count is greater than the midpoint.
The problem is your median method. It should not return -1. In the last line of the median method, instead of
return -1;
change it to
return array[rand.nextInt(array.length)];
Please note that this fix is just an attempt to fix the error you have. It's not a good fix in the sense that median method does not return the median. I think the application should be refactored. The idea of the fix is actually in the pivot method. A good pivot is the median. But if you cannot find the median efficiently, then a pivot can be a random choice among the array.
Update:
Let's fix the median method:
static int median(int[] array) {
if (array.length == 0) {
throw new IllegalArgumentException("array cannot be empty.");
}
int mid = array.length / 2;
for (int candidate : array) {
int lower = 0;
int higher = 0;
for (int value : array) {
if (value < candidate) {
lower++;
}
else if (value > candidate) {
higher++;
}
}
if (lower <= mid && higher <= mid) {
return candidate;
}
}
throw new IllegalStateException();
}