Index of the smallest number starting from a certain index - java

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.

Related

Finding multiple occcurances of the same value within a linear search on an array

How can I make it so if the value appears more than once in an array the code can then say the value appears in index: 0, 1, etc?
I'm working on a homework assignment that asks to write a method called linearSearch that performs a linear search on an integer array: searches starting at index 0, then 1, 2, 3…. It should return the index of the array that contains the target or a -1 if it is not found in the array. I have done that, but an issue that I am seeing is if the target appears more than once in the array the print statement will only print where it's located first. For Example, if my array is [6, 3, 9, 2, 7, 6]. The print statement says "6 is found at index: 0". Is there a way to change it when the value appears more than once so the print statement will then say "6 is found at index: 0 and 5"?
import java.util.Arrays;
import java.util.Random;
public class Q6 {
public static void main(String[] args) {
Random random = new Random();
int x = random.nextInt(10);
int[] y = createRandomIntArray(x);
int z = x;
System.out.println(Arrays.toString(y));
System.out.println(z + " is found at index: " + linearSearch(y, z));
}
public static int[] createRandomIntArray(int n) {
Random random = new Random();
int[] result = new int[n];
for (int i = 0; i < result.length; i++)
result[i] = random.nextInt(10);
return result;
}
public static int linearSearch(int[] array, int target) {
for (int i = 0; i < array.length; i++) {
if (array[i] == target) {
return i;
}
}
return -1;
}
}
Output:
[6, 3, 9, 2, 7, 6]
6 is found at index: 0
I would use a list to store each index where the target number is found, then add them all together into one string before returning them:
public static String linearSearch(int[] array, int target) {
List<Integer> indices = new ArrayList<Integer>();
for (int i = 0; i < array.length; i++) {
if (array[i] == target) {
indices.add(i);
}
}
return indices.stream().map(String::valueOf).collect(Collectors.joining(" and "));
}
But I imagine that your professor does not want you using lists yet, let alone streams. So, here is another method which creates a new array to store the indices in, making it the same size as the source array, and uses a variable matches to keep track of how many indices are stored in that array:
public static String linearSearch(int[] array, int target) {
int[] indices = new int[array.length];
int matches = 0;
for (int i = 0; i < array.length; i++) {
if (array[i] == target) {
indices[matches++] = i;
}
}
if (matches == 1) {
return String.valueOf(indices[0]);
} else {
String builder = String.valueOf(indices[0]);
for (int i = 1; i < matches; i++) {
builder += " and " + indices[i];
}
return builder;
}
}
Rather than modify the return value of your linearSearch method to handle multiple matches you could instead add a start position for the search.
public static int linearSearch(int[] array, int target, int off) {
for (int i = off; i < array.length; i++) {
if (array[i] == target) {
return i;
}
}
return -1;
}
You would then make (potentially) multiple calls, using the position of the previously identified match as the starting point of the next search. You quit when you fail to find a match.
public static void main(String[] args)
{
int x = 6;
int[] y = {6, 3, 9, 2, 7, 6};
int off = 0;
while(true)
{
off = linearSearch(y, x, off);
if(off < 0) break;
System.out.println("Found at index: " + off);
off += 1;
}
}
Output:
Found at index: 0
Found at index: 5

Can't understand why loop is not updating variable value

When I create this method to find the index of the smallest number in an array starting from a specific index, it keeps returning 0 no matter which numbers are in the array. It seems that index = i in the for loop is not updating the value of the index variable, even if the array contains other numbers lower than the 0 spot. Why?
public static int indexOfSmallestFrom(int[] array, int startIndex) {
int smallest = array[startIndex];
int index = 0;
for (int i = startIndex; i < array.length; i++) {
int each = array[i];
if (each < smallest) {
smallest = each;
index = i;
}
}
return index;
}
edit: Here's the main method:
public static void main(String[] args) {
// write your test code here
int[] array = {99, 3, 1, 7, 4, 5, 2, 4};
System.out.println("Smallest: " + indexOfSmallestFrom(array, 1));
}
It works correctly every time EXCEPT when the startIndex variable passed to the method call is 2! When a 1 is passed as above, it correctly returns 2, when 3 is passed, it correctly returns 6, etc. ???
Because when you pass startIndex = 2 into the function, we have smallest = array[startIndex] = 1 in this case, and your code initializes int index = 0;. However, in your for loop, you have:
for (int i = startIndex; i < array.length; i++) {
int each = array[i];
if (each < smallest) {
smallest = each;
index = i;
}
}
Since your smallest was initialized to the number at position startIndex but not your index, and the fact that startIndex happened to be the index of the smallest number, your if (each < smallest) will never be entered, meaning that index will stay at 0.
To fix this, either change int index = 0; to int index = startIndex; OR you can change the condition in the if statement to if (each <= smallest) and your code should work fine (note that if you do this, it will return the last index if multiple minimums are present in the array).
Your code works for me, may be the smallest value is in 0 place in your case. But you should change index = startingIndex. Because that is where you are comparing items from.
public static int indexOfSmallestFrom(int[] array, int startIndex) {
int smallest = array[startIndex];
int index = startIndex;
for (int i = startIndex; i < array.length; i++) {
int each = array[i];
if (each < smallest) {
smallest = each;
index = i;
}
}
return index;
}
Or change < to <=
public static int indexOfSmallestFrom(int[] array, int startIndex) {
int smallest = array[startIndex];
int index = 0;
for (int i = startIndex; i < array.length; i++) {
int each = array[i];
if (each <= smallest) {
smallest = each;
index = i;
}
}
return index;
}
Because the value in position 2 is the SMALLEST value (it's 1), hence the if condition is never entered :).

This Code of mine should return the frequency of the most common element

Arrays.sort(arr);
int max=1,m=1;
for(int i=1;i<arr.length;i++){
if(arr[i]==arr[i-1]){
max++;
}
else{
if(max>m){
m=max;
max=1;
}
}
}
if(max>m){
m=max;
}
return m;
This is a function that I have made. This should return the number of times the most frequent element occurs. E.g if the array is 1,2,2,3,3,3 , then it should return 3. But it fails in many cases, e.g for the input 1 2 3 1 2 3 3 3, this code fails and returns 5, which is the wrong output.
I can code it up for you to answer your question using the map interface. I will check each value and if there is already a key for that value, it will increment the value by 1. If not, then it will create the key and assign it a value of 1.
When finished, I only need to ask the map what the largest value was which is what I think you are after. And I can also return the value that was the most frequent, if you want.
Here is the tested code. One class for the working method and then the driver class with main method
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
public class FindMostFrequent {
public static Integer returnFromArrayHighestFrequency(int[] inArray) {
HashMap<Integer, Integer> hashMap = new HashMap<Integer, Integer>();
for (int i = 0; i < inArray.length; i++) {
if (hashMap.containsKey(inArray[i])) {
hashMap.put(inArray[i], hashMap.get(inArray[i]) + 1);
} else {
hashMap.put(inArray[i], 1);
}
}
Integer maxValue = Collections.max(hashMap.values());
return maxValue;
}
}
And here is the driver class:
public static void main(String[] args) {
int[] testArray = { 1, 2, 2, 3, 3, 3 };
Integer max = FindMostFrequent.returnFromArrayHighestFrequency(testArray);
System.out.println("highest frequency is: " + max);
}
I like this technique because it allows you to easily get the minimum or another other value and its key that you want.
Sorting the array first and counting runs of the same number is a good idea. Your logic doesn't quite make sense through.
You need to keep track of the length of the current run, and the length of the longest run. Your current run should get reset when the value in the array is different to the previous value; and your longest run should be updated when the current run is longer than it.
Something like this:
if (arr.length==0) {
return 0;
}
Arrays.sort(arr);
int currentRun = 1;
int longestRun = 1;
for (int i = 1; i < arr.length; i++){
if (arr[i]==arr[i-1]){
++currentRun;
if (currentRun > longestRun) {
longestRun = currentRun;
}
} else {
currentRun = 1;
}
}
return longestRun;
Another way using streams, which basically uses a map to track the frequency of occurrences and grabs the highest value after sorting that map.
public static Long getMostFrequentCount( int ... values ) {
return Arrays.stream(values).boxed().collect(Collectors.groupingBy(Function.identity(),
Collectors.counting())).values().stream().max(Long::compareTo).orElse( null );
}
EDIT: Made better thanks to #saka1029 's excellent suggestion
This might be what you want...
All of the numbers you want to use is contained inside of the array a.
public class Main {
public static void main(String[] args) {
int[] a = {1,2,3,4,5,6,7,7,7,7};
int count = 1, tempCount;
int popular = a[0];
int temp = 0;
for (int i = 0; i < (a.length - 1); i++) {
temp = a[i];
tempCount = 0;
for (int j = 1; j < a.length; j++) {
if (temp == a[j])
tempCount++;
}
if (tempCount > count) {
popular = temp;
count = tempCount;
}
}
System.out.println(popular);
}
}
your logic is totally correct except one line. ==> if(max>m).
In this case you are not resetting the value of max if max == m.
replace if(max>m){ with if(max>=m){
You need to check max against m for each iteration. And the use of continue here simplifies the logic. Prints -1 on an empty array.
int[] arr = {1, 2, 3, 1, 2, 3, 3, 3};
Arrays.sort(arr);
int max = 1;
int m = arr.length == 0 ? -1 : 1;
for (int i = 1; i < arr.length; i++) {
if (arr[i] == arr[i - 1]) {
max++;
if (max > m) {
m = max;
}
continue;
}
max = 1;
}
System.out.println(m);
Prints
4

How do I get values from an array without counting its duplicates?

I know the title is really bad but I spent like 10 minutes thinking of a way to describe my problem in a concise way and couldn't.
This program is supposed to create a numUnique() static method that returns the amount of unique numbers in an array. So, for example, if I have an array with {2, 4, 2, 7, 16, 4} the amount of unique numbers would be 4 (2, 4, 7 and 16).
I was writing the code to find the duplicates in my array, then I realized that I didn't know what to do with it when I had the duplicates, and I've been breaking my head trying to think of a solution but I can't.
Here is the code so far:
public class Unique {
public static void main(String[] args) {
int[] numbers = {1, 6, 2, 14, 6, 8, 2, 1, 23};
numUnique(numbers);
}
public static void numUnique(int[] array){
Arrays.sort(array);
for (int i = 0; i < array.length; i++) {
for (int j = i + 1; j < array.length; j++) {
if (array[i] == array[j])
//code here
}
}
}
}
My understanding is you to count (not return them all) the number of unique elements in the array. You are attempting to look all the way down, but it's enough to track the number of duplicates as you go. This code looks back to see if the current entry duplicates the previuos one (which works because you sorted, which was a good step).
import java.util.Arrays;
public class Unique {
public static void main(String[] args) {
int[] numbers = {
1,
6,
2,
14,
6,
8,
2,
1,
23
};
System.out.println(numUnique(numbers));
}
public static int numUnique(int[] array) {
Arrays.sort(array);
int dups = 0;
for (int i = 1; i < array.length; i++) {
if (array[i] == array[i - 1]) {
dups++;
}
}
return (array.length - dups);
}
}
If you want to keep the code that you have so far and sort the list, there are two options that seem to make sense. Where one is to return the number of unique integers, and the other is to return a list of the unique integers.
Returning the number of unique numbers:
public static int numUnique(int[] array) {
ArrayList<Integer> uniques = new ArrayList<>();
Arrays.sort(array);
uniques.add(array[0]);
int prev = array[0];
for (int i = 1; i < array.length; i++) {
if(array[i] != prev){
uniques.add(array[i]);
prev = array[i]
}
}
return uniques.size();
}
Returning the list of unique numbers, would simply require you to return the uniques list, without the .size().
If you want a array instead of a list, you will need to return the following:
return uniques.toArray(new Integer[list.size()]);
If you're using Arrays why not explore it further
private static long numUnique(int[] numbers) {
return Arrays.stream(numbers).distinct().count();
}
Keeping your code as it is:
If You want to know how many non-duplicates are in you array:
public static void numUnique(int[] array) {
Arrays.sort(array);
// Here, make a variable that keeps size of an array
int arrayLenght = array.length;
// Here is our counter:
int duplicates = 0;
for (int i = 0; i < array.length; i++) {
for (int j = i + 1; j < array.length; j++) {
if (array[i] == array[j])
// when you find duplicate, add 1 to our counter:
duplicates++;
}
}
//at the end you can count how many non-duplicates are in the array:
arrayLenght -= duplicates;
System.out.println("There are " + arrayLenght + " non duplicates in our array.");
}
Edit
This solution do not work in every situation.
I know this is not the most optimal way to do this, but the only i know hah:
public static void numUnique(int[] array) {
Arrays.sort(array);
int arrayLenght = array.length;
int duplicates = 0;
for (int i = 0; i < array.length; i++) {
//a little change in our second for-loop:
for (int j = 0; j < array.length; j++) {
if (array[i] == array[j]) {
//Here i'm just summing up the duplicates
duplicates ++;
}
}
// Aaand here, on a console, i print the value (array[i]) and how many duplicates does it have.
//to be exact, if the duplcicates rise only once so it's equal to 1, it means that there is no duplicate of this value (it found itself in the loop).
if (duplicates == 1) {
duplicates = 0;
}
System.out.println(array[i] + " have " + duplicates + "duplicates");
// And what is imporatnt We have to reset our duplication-container!
// so in further loops it will count duplicates for each value in array
duplicates = 0;
}
}
If you find another issue, ask me right away

Array not registering added ints

I'm working on a problem on leetcode (Two Sum):
Given an array of integers, return indices of the two numbers such
that they add up to a specific target.
You may assume that each input would have exactly one solution, and
you may not use the same element twice.
Example: Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9, return [0, 1].
I tried my own solution and the array always showed [0,0]. So I tried a solution that they had after several tweeks and that still showed [0,0] when I put it in and it was the highest ranked solution. Is it me or is it leetcode?
Original Solution:
import java.util.Arrays;
public class Solution {
public int[] twoSum(int[] nums, int target) {
int[] indices = new int[2];
for(int i = 0; i < nums.length-1; i++)
{
for(int j = i+1; j < nums.length-1; j++)
{
if(target == (nums[i] + nums[j]))
{
indices[0] = i+1;
indices[1] = j+1;
}
}
}
return indices;
}
}
Leetcode Solution:
public class Solution {
public int[] twoSum(int[] nums, int target) {
int[] indices = new int[2];
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for(int i = 0; i < nums.length-1; i++)
{
if(map.containsKey(target - nums[i]))
{
indices[1] = i + 1;
indices[0] = map.get(target - nums[i]);
return indices;
}
map.put(nums[i], i + 1);
}
return indices;
}
}
I don't understand why neither of these will register ints in the indices array, it continually returns [0,0] for both solutions.
In my understanding your innerloop must not start with i+1, cause you have to check each index in your array. only if the index of the inner and outer loop match, you should skip it, cause you won't add the index with itself.
you must loop your array to the end (so i removed the -1 in the for-statement)
why are you returning i+1 and j+1 if you found a match? (so i removed this)
see my code. maybe it will be more clear, what im trying to say :-)
public class Solution {
public static void main(String[] args) {
Solution solution = new Solution();
int[] result = solution.twoSum(new int[] { 2, 7, 11, 15 }, 17);
System.out.println(result[0] + "/" + result[1]);
}
public int[] twoSum(int[] nums, int target) {
int[] indices = new int[2];
for (int i = 0; i < nums.length; i++) {
for (int j = 0; j < nums.length; j++) {
if (i == j) {
//do not use the same index for sum
continue;
}
if (target == (nums[i] + nums[j])) {
indices[0] = i;
indices[1] = j;
}
}
}
return indices;
}
}
The simplest way to loop through combinations of two within an array can be done as follows:
for(int i=0 ; i<nums.length-1 ; i++)
for(int j=i+1 ; j<nums.length ; j++)
if(nums[i]+nums[j]==target)
return new int[] {i, j};
return null; //in case there's no such case

Categories