Generate an array containing unique Random ints, check for duplicates - java

This is an assignment for school that I am really close to completing, but I don't have it exactly. I am supposed to generate an array of integer Nodes with 100 random numbers without duplicates by checking for duplicates.
I'm not allowed to use a Set.
I'm not allowed to just shuffle an array of numbers 1-1000.
Here is the code I have in my client class so far but it still creates duplicates:
for (int i = 0; i < SIZE; i++) {
int j = (int)(Math.random()*1999);
//put a random number in the first index.
if (i == 0) {
Node newNode = new Node(j);
nodeArray[i] = newNode;
}
for (int k = 0; k < i; k++) {
if (nodeArray[k].getInt() == j) {
j = (int)(Math.random()*1999);
break;
} else {
Node newNode = new Node(j);
nodeArray[i] = newNode;
}
}
}

The way i would do this would be to use a List to store all the random numbers in. Then when you generate a number you can check if it already exists in the list, and get another number (this is done via recursion, or a while loop). You keep going with this until your list is full. Then go through the list creating the Nodes for your array.
List<Integer> numbers = new ArrayList<Integer>(SIZE);
for (int i = 0;i<SIZE; i++) {
addUniqueRandomNumber(numbers, SIZE*2);
}
for (int i =0;i<numbers.size; i++) {
Node newNode = new Node(numbers.get(i));
nodeArray[i] = newNode;
}
The addUniqueRandomNumber method:
public static void addUniqueRandomNumber(List<Integer> numbers, int range) {
int j = (int)(Math.random()*range);
if (numbers.contains(j)) {
addUniqueRandomNumber(numbers, range);
} else {
numbers.add(j);
}
}

Because when you are assigning a new random if the first random is a duplicate in your second if statement it never checks if that random could be also a duplicate. You need to redo the loop and check if that number is a duplicate as well.
for (int k = 0; k < i; k++) {
if (nodeArray[k].getInt() == j) {
j = (int)(Math.random()*1999); //You must check if this random is also a dup
break;
} else {
Node newNode = new Node(j);
nodeArray[i] = newNode;
}
Here's what I would do:
int i = 0;
while (i < SIZE) {
int j = (int)(Math.random()*1999);
//put a random number in the first index.
if (i == 0) {
Node newNode = new Node(j);
nodeArray[i] = newNode;
i++;
}
for (int k = 0; k < i; k++) {
if (nodeArray[k].getInt() == j) {
//Do nothing
} else {
Node newNode = new Node(j);
nodeArray[i] = newNode;
i++;
}
}
}
Basically only increment i if the number is not duplicate, otherwise go through and try to find another random that is not a duplicate.

Solution algorithm which check after each generated number exist is or no:
int[] nodeArray = new int[100];
int currentIndex = 0;
while(currentIndex < 100) {
int currentValue = (int) (Math.random() * 199);
int i = 0;
while(i < currentIndex) {
if(currentValue == nodeArray[i]) {
break;
}
i++;
}
if(i == currentIndex) {
nodeArray[currentIndex++] = currentValue;
}
}
Then you can sort ant print random numbers
Arrays.sort(nodeArray); // Sort to be easy find duplicates
for (Integer i : nodeArray) {
System.out.print(i + ", ");
}

I suggest to use a helper boolean array to keep track of which numbers were already added to the array. Review this code, it is short and concise:
boolean[] used = new boolean[2000];
int[] randomUniqueIntegers = new int[SIZE];
for (int i = 0; i < SIZE; i++) {
int num = (int) (Math.random() * 1999);
if (!used[num]) {
used[num] = true;
randomUniqueIntegers[i] = num;
} else {
while (used[num]) {
num = (int) (Math.random() * 1999);
if (!used[num]) {
used[num] = true;
randomUniqueIntegers[i] = num;
break;
}
}
}
}
As you see the implementation above doesn't use Set or shuffling. However, you can use the test code below to see it works correctly.
Set<Integer> set = new HashSet<Integer>();
for (int i : randomUniqueIntegers)
set.add(i);
System.out.println(set.size());
You will see that the size of the set is equal to SIZE constant in each run which indicates we have all unique elements in our array.

Related

randomly generate 100 unique numbers using Math.random [duplicate]

my intend is to use simplest java (array and loops) to generate random numbers without duplicate...but the output turns out to be 10 repeating numbers, and I cannot figure out why.
Here is my code:
int[] number = new int[10];
int count = 0;
int num;
while (count < number.length) {
num = r.nextInt(21);
boolean repeat = false;
do {
for (int i=0; i<number.length; i++) {
if (num == number[i]) {
repeat = true;
} else if (num != number[i] && i == count) {
number[count] = num;
count++;
repeat = true;
}
}
} while (!repeat);
}
for (int j = 0; j < number.length; j++) {
System.out.print(number[j] + " ");
}
How about you use a Set instead? If you also want to keep track of the order of insertion you can use a LinkedHashSet.
Random r = new Random();
Set<Integer> uniqueNumbers = new HashSet<>();
while (uniqueNumbers.size()<10){
uniqueNumbers.add(r.nextInt(21));
}
for (Integer i : uniqueNumbers){
System.out.print(i+" ");
}
A Set in java is like an Array or an ArrayList except it handles duplicates for you. It will only add the Integer to the set if it doesn't already exist in the set. The class Set has similar methods to the Array that you can utilize. For example Set.size() is equivalent to the Array.length and Set.add(Integer) is semi-equivalent to Array[index] = value. Sets do not keep track of insertion order so they do not have an index. It is a very powerful tool in Java once you learn about it. ;)
Hope this helps!
You need to break out of the for loop if either of the conditions are met.
int[] number = new int[10];
int count=0;
int num;
Random r = new Random();
while(count<number.length){
num = r.nextInt(21);
boolean repeat=false;
do{
for(int i=0; i<number.length; i++){
if(num==number[i]){
repeat=true;
break;
}
else if(i==count){
number[count]=num;
count++;
repeat=true;
break;
}
}
}while(!repeat);
}
for(int j=0;j<number.length;j++){
System.out.print(number[j]+" ");
}
This will make YOUR code work but #gonzo proposed a better solution.
Your code will break the while loop under the condition: num == number[i].
This means that if the pseudo-generated number is equal to that positions value (the default int in java is 0), then the code will end execution.
On the second conditional, the expression num != number[i] is always true (otherwise the code would have entered the previous if), but, on the first run, when i == count (or i=0, and count=0) the repeat=true breaks the loop, and nothing else would happen, rendering the output something such as
0 0 0 0 0 0...
Try this:
int[] number = new int[10];
java.util.Random r = new java.util.Random();
for(int i=0; i<number.length; i++){
boolean repeat=false;
do{
repeat=false;
int num = r.nextInt(21);
for(int j=0; j<number.length; j++){
if(number[j]==num){
repeat=true;
}
}
if(!repeat) number[i]=num;
}while(repeat);
}
for (int k = 0; k < number.length; k++) {
System.out.print(number[k] + " ");
}
System.out.println();
Test it here.
I believe the problem is much easier to solve. You could use a List to check if the number has been generated or not (uniqueness). Here is a working block of code.
int count=0;
int num;
Random r = new Random();
List<Integer> numbers = new ArrayList<Integer>();
while (count<10) {
num = r.nextInt(21);
if(!numbers.contains(num) ) {
numbers.add(num);
count++;
}
}
for(int j=0;j<10;j++){
System.out.print(numbers.get(j)+" ");
}
}
Let's start with the most simple approach, putting 10 random - potentially duplicated - numbers into an array:
public class NonUniqueRandoms
{
public static void main(String[] args)
{
int[] number = new int[10];
int count = 0;
while (count < number.length) {
// Use ThreadLocalRandom so this is a contained compilable unit
number[count++] = ThreadLocalRandom.current().nextInt(21);
}
for (int j = 0; j < number.length; j++) {
System.out.println(number[j]);
}
}
}
So that gets you most of the way there, the only thing you know have to do is pick a number and check your array:
public class UniqueRandoms
{
public static void main(String[] args)
{
int[] number = new int[10];
int count = 0;
while (count < number.length) {
// Use ThreadLocalRandom so this is a contained compilable unit
int candidate = ThreadLocalRandom.current().nextInt(21);
// Is candidate in our array already?
boolean exists = false;
for (int i = 0; i < count; i++) {
if (number[i] == candidate) {
exists = true;
break;
}
}
// We didn't find it, so we're good to add it to the array
if (!exists) {
number[count++] = candidate;
}
}
for (int j = 0; j < number.length; j++) {
System.out.println(number[j]);
}
}
}
The problem is with your inner 'for' loop. Once the program finds a unique integer, it adds the integer to the array and then increments the count. On the next loop iteration, the new integer will be added again because (num != number[i] && i == count), eventually filling up the array with the same integer. The for loop needs to exit after adding the unique integer the first time.
But if we look at the construction more deeply, we see that the inner for loop is entirely unnecessary.
See the code below.
import java.util.*;
public class RandomDemo {
public static void main( String args[] ){
// create random object
Random r = new Random();
int[] number = new int[10];
int count = 0;
int num;
while (count < number.length) {
num = r.nextInt(21);
boolean repeat = false;
int i=0;
do {
if (num == number[i]) {
repeat = true;
} else if (num != number[i] && i == count) {
number[count] = num;
count++;
repeat = true;
}
i++;
} while (!repeat && i < number.length);
}
for (int j = 0; j < number.length; j++) {
System.out.print(number[j] + " ");
}
}
}
This would be my approach.
import java.util.Random;
public class uniquerandom {
public static void main(String[] args) {
Random rnd = new Random();
int qask[]=new int[10];
int it,i,t=0,in,flag;
for(it=0;;it++)
{
i=rnd.nextInt(11);
flag=0;
for(in=0;in<qask.length;in++)
{
if(i==qask[in])
{
flag=1;
break;
}
}
if(flag!=1)
{
qask[t++]=i;
}
if(t==10)
break;
}
for(it=0;it<qask.length;it++)
System.out.println(qask[it]);
}}
public String pickStringElement(ArrayList list, int... howMany) {
int counter = howMany.length > 0 ? howMany[0] : 1;
String returnString = "";
ArrayList previousVal = new ArrayList()
for (int i = 1; i <= counter; i++) {
Random rand = new Random()
for(int j=1; j <=list.size(); j++){
int newRand = rand.nextInt(list.size())
if (!previousVal.contains(newRand)){
previousVal.add(newRand)
returnString = returnString + (i>1 ? ", " + list.get(newRand) :list.get(newRand))
break
}
}
}
return returnString;
}
Create simple method and call it where you require-
private List<Integer> q_list = new ArrayList<>(); //declare list integer type
private void checkList(int size)
{
position = getRandom(list.size()); //generating random value less than size
if(q_list.contains(position)) { // check if list contains position
checkList(size); /// if it contains call checkList method again
}
else
{
q_list.add(position); // else add the position in the list
playAnimation(tv_questions, 0, list.get(position).getQuestion()); // task you want to perform after getting value
}
}
for getting random value this method is being called-
public static int getRandom(int max){
return (int) (Math.random()*max);
}

Java - Program to find longest increasing sequence of consecutive elements (logical errors)

I am currently creating a program where the user inputs an array of integers. The program has to find the longest increasing sequence of consecutive elements. So if the user enters "3,2,1,2,4,6,7,8,1,2" the program will output "1,2,4,5,6,7,8". However, I keep running into 2 errors.
The first error is that when xs = 1000,97777,487,8274,972837. The program will output "1000,97777" instead of "487,8274,972837". Logically this is wrong since the first output is not the "LONGEST" increasing sequence of consecutive element.
The second error is that when xs = 2,7. It seems to output an empty array instead of "2,7". I'm assuming it's because there aren't enough elements perhaps?
static int[] increasing(int[] xs){
ArrayList<Integer> current_array = new ArrayList<Integer>();
ArrayList<Integer> list = new ArrayList<Integer>();
int c_counter = 0;
for (int i = 0; i<(xs.length); i++){
if (i==0){
if (xs[i+1] > xs[i]){
current_array.add(xs[i]);
c_counter++; //keeps track of how many elements have been added
}
}
else if ((xs[i] > xs[i-1])){
if (c_counter==0){
current_array.add(xs[i-1]); //makes sure the smaller number gets added too
current_array.add(xs[i]);
c_counter = c_counter + 2;
} else{
current_array.add(xs[i]);
c_counter++;
}
} else {
if (current_array.size()>list.size()){ //compares sizes to find the longest sequence
list.clear();
for (int k=0; k<(current_array.size()); k++){
if (current_array.get(k) != 0){ //removes any null values
list.add(current_array.get(k));
}
}
current_array.clear(); //clears it to restart and find any longer sequences
c_counter = 0;
}
}
}
int[] out_array = list.stream().mapToInt(i->i).toArray(); //converts from arraylist to int[] as that's the format it must output
out_array = list.stream().filter(i->i != null).mapToInt(i->i).toArray();
return out_array;
}
public static int[] increasing(int[] xs){
int start = 0;
int end = 0;
int temp = 0;
for (int i = 0; i < xs.length; i++) {
if(i==0 || xs[i]<xs[i-1]){
temp = i;
}
else if(i-temp > end-start){
start = temp;
end = i;
}
}
return Arrays.copyOfRange(xs, start, end+1);
}
It takes too long time to understand your code. Try this out:
List<Integer> test = new ArrayList<Integer>();
test.add(3);
test.add(2);
test.add(1);
test.add(2);
// test.add(4);
// test.add(6);
// test.add(7);
// test.add(8);
test.add(1);
test.add(2);
test.add(1000);
test.add(97777);
test.add(487);
test.add(8274);
test.add(972837);
List<Integer> output = new ArrayList<Integer>();
List<Integer> temp = new ArrayList<Integer>();
for(int i = 0; i < test.size(); i++) {
int current = test.get(i);
int next = Integer.MIN_VALUE;
if(i + 1 < test.size()) next = test.get(i + 1);
if(current > next) {
if(output.size() <= temp.size()) {
temp.add(current);
output = new ArrayList<Integer>(temp);
}
temp.clear();
} else {
temp.add(current);
}
}
output.forEach(i -> System.out.print(i + ", "));
If you want the longest decreasing output, change int next = Integer.MAX_VALUE; and if(current > next) to if(current < next)

Shifting an array after removing a value (Java)

I made a program that makes an array of random ints and doubles in size if the user tries to add an int. Example: 1|2|3|4 if they were to add another int it would look like 1|2|3|4|5|0|0|0. I have made a method to add an int which works but now I am trying to make methods that remove one of a certain int and another that removes all of a certain int. for example removeInt(3) would give me 1|2|0|4|5|0|0|0. I have the first part working so that it shifts the zero to the end like this 1|2|4|5|0|0|0|0 but cannot get it to work for more than one of the same value. Any suggestions?
// ****************************************************************
// IntegerList.java
//
// Define an IntegerList class with methods to create & fill
// a list of integers.
//
// ****************************************************************
public class IntegerList
{
int[] list; //values in the list
//-------------------------------------------------------
//create a list of the given size
//-------------------------------------------------------
public IntegerList(int size)
{
list = new int[size];
}
//-------------------------------------------------------
//fill array with integers between 1 and 100, inclusive
//-------------------------------------------------------
public void randomize()
{
for (int i=0; i<list.length; i++)
list[i] = (int)(Math.random() * 100) + 1;
}
//-------------------------------------------==----------
//print array elements with indices
//-------------------------------------------------------
public void print()
{
for (int i=0; i<list.length; i++)
System.out.println(i + ":\t" + list[i]);
}
public void addElement(int newVal){
boolean full = true;
System.out.println(list.length);
int position = 0;
int place;
while(position < list.length){
System.out.println("HERE");
if(list[position]==0){
System.out.println("here");
full = false;
place = position;
System.out.println(place);
}
position = position+1;
}
if(full == true){
list = increaseSize(list);
System.out.println("L"+list.length);
full = false;
}
for(int i = 0;i<list.length;i++){
if(list[i]==0){
if(i<position){
position = i;
System.out.println(list.length);
}
}
}
list[position] = newVal;
}
public void removeFirst(int newVal){
int position = 0;
boolean removed = false;
for(int i = 0; i<list.length;i++){
if(list[i] == newVal){
list[i]=0;
position = i;
removed = true;
break;
}
}
if(removed==true){
for(int i = position;i<list.length;i++){
if(i!=list.length-1){
list[i]=list[i+1];
}
}
list[list.length-1]= 0;
}
}
public void removeAll(int newVal){
int position = 0;
boolean removed = false;
for(int i = 0; i<list.length;i++){
if(list[i] == newVal){
list[i]=0;
position = i;
removed = true;
}
}
if(removed==true){
for(int i = 0;i<list.length;i++){
if(i!=list.length-1 && list[i+1]==newVal){
list[i]=0;
}
if(list[i]==newVal){
list[i]=0;
}
}
}
}
public static int[] increaseSize(int[] x){
int newLength = x.length *2;
int[] newx = new int[newLength];
for(int i = 0; i<x.length; i++){
newx[i] = x[i];
}
return newx;
}
public static int[] halfSize(int[] x){
int[] newx = new int[x.length / 2];
for(int i = 0; i<x.length; i++){
newx[i] = x[i];
}
return newx;
}
}
I believe there's an easier way to implement your removeAll method. Move 2 (rather than 1) indices through your array constantly shifting the values over the items you are removing;
int dest = 0;
int source = 0;
while (source < array.length) {
if (array[dest] != valueToRemove)
dest++;
array[dest] = array[source++];
}
while (dest < array.length) {
array[dest++] = 0;
}
I executed your code and found out that the problem is in this piece, under removeAll()...
if(removed){
for(int i = 0;i<list.length;i++){
if(i!=list.length-1 && list[i+1]==newVal){
list[i]=0;
}
if(list[i]==newVal){
list[i]=0;
}
}
}
If you comment out and try once, you will see the removeAll() is working and your desired number is replaced with 0s. Now why you don't simply check your numbers and shift(sorting), if they are greater than 0 to the left?

finding maximum number in ArrayList

this is my practice before my upcoming test, I'm trying to make the user input a number. And all elements in array1 that is below the user's number, will be put in a new ArrayList.
and then I'm trying to print only the highest number in that ArrayList. If the user input is lower than all number in array1, it will return -1.
here is my code, however, when I put 920, it still returns -1, I think there's something wrong with my code to find highest number in ArrayList. Can you guys please tell me what is wrong?
static Scanner sc = new Scanner(System.in);
static int[] array1 = {900, 885, 989, 1000, 1500, 1243, 999, 915};
public static int blabla(int[] a, int b) {
Integer d = -1;
ArrayList<Integer> al = new ArrayList<Integer>();
for (int i = 0; i < array1.length; i++) { // this is to find all numbers in array1 that is below user's number, and add it to the ArrayList
if (b > array1[i]) {
al.add(array1[i]);
} // if
} // for
outerloop: // and this function below is to find maximum number in ArrayList
for (int g = (al.size()-1); g == 0; g--) {
for (int j = 0; j <=(g-1); j++) {
if (al.get(j) > al.get(g)) {
break;
}
else if(j == (g-1)) {
if (al.get(g) > al.get(j)){
d = al.get(g);
break outerloop;
}
}
} //for^2
} // for
return d;
} // priceisright
static Scanner sc = new Scanner(System.in);
static int[] array1 = {900, 885, 989, 1000, 1500, 1243, 999, 915};
public static int blabla(int[] a, int b) {
Integer d = -1;
ArrayList<Integer> al = new ArrayList<Integer>();
At this point, a1 is an empty array, so a1.length = 0, this loop never gets executed.
for (int i = 0; i < a1.length; i++) {
// this is to find all numbers in array1 that is below user's number,
// and add it to the ArrayList
if (b > a1[i]) {
al.add(a1[i]);
} // if
} // for
a1 is still empty there, the second loop won't do anything either.
// and this function below is to find maximum number in ArrayList
outerloop:
for (int g = (al.size()-1); g == 0; g--) {
for (int j = 0; j <=(g-1); j++) {
if (al.get(j) > al.get(g)) {
break;
}
else if(j == (g-1)) {
if (al.get(g) > al.get(j)){
d = al.get(g);
break outerloop;
}
}
} //for^2
} // for
return d;
} // priceisright
What about this:
// Finds the greater value in values that is below maximum.
// Returns -1 if none is found.
public static int blabla(int[] values, int maximum) {
int best_value = -1;
for (int value : values) {
if (value < maximum && value > best_value) {
best_value = value;
}
}
return best_value;
}
You can replace int[] values by List<Integer> values if your values are in an ArrayList.
You can use this
Collections.max(arrayList);
To know more about read Javadoc for Collection.max
If you want to use an ArrayList you can check fro maximum with linear time by,
public static Integer getMaximum(List<Integer> coll) {
if (coll == null) {
return null;
}
Integer i = coll.get(0);
for (int t = 1; t < coll.size(); t++) {
Integer v = coll.get(i);
if (v != null && v > i) {
i = v;
}
}
return i;
}
Or, you could change that to a SortedSet<Integer> set = new TreeSet<Integer>(); then the maximum element is always set.last();
I would simplify your two for loops by this one:
for (int g = 0; g <=(al.size()-1); g++) { //for each value in your new array
d = (al.get(g)>d)? al.get(g):d; //is current value higher than previous? if not keep old one
}
Simple way to find the max in an array or arrayList (or any collection actually) without using built in methods such as .max
Int currentMax = 0
For (int i = 0; i < al.length; i++)
{
If al[i] > currentMax
{
CurrentMax = al[i]
}
}
Answered this from my phone so I apologize for bad indents, but you get the idea :)

How can i find the positions to the three lowest integers in an array?

I how can I find the positions of the three lowest integers in an array?
I've tried to reverse it, but when I add a third number, it all goes to hell :p
Does anybody manage to pull this one off and help me? :)
EDIT: It would be nice to do it without changing or sorting the original array a.
public static int[] lowerThree(int[] a) {
int n = a.length;
if (n < 2) throw
new java.util.NoSuchElementException("a.length(" + n + ") < 2!");
int m = 0; // position for biggest
int nm = 1; // position for second biggest
if (a[1] > a[0]) { m = 1; nm = 0; }
int biggest = a[m]; // biggest value
int secondbiggest = a[nm]; // second biggest
for (int i = 2; i < n; i++) {
if (a[i] > secondbiggest) {
if (a[i] > biggest) {
nm = m;
secondbiggest = biggest;
m = i;
biggest = a[m];
}
else {
nm = i;
secondbiggest = a[nm];
}
}
} // for
return new int[] {m,nm};
}
EDIT: I've tried something here but it still doesn't work. I get wrong output + duplicates...
public static int[] lowerthree(int[] a) {
int n= a.length;
if(n < 3)
throw new IllegalArgumentException("wrong");
int m = 0;
int nm = 1;
int nnm= 2;
int smallest = a[m]; //
int secondsmallest = a[nm]; /
int thirdsmallest= a[nnm];
for(int i= 0; i< lengde; i++) {
if(a[i]< smallest) {
if(smalles< secondsmallest) {
if(secondsmallest< thirdsmallest) {
nnm= nm;
thirdsmallest= secondsmallest;
}
nm= m;
secondsmallest= smallest;
}
m= i;
smallest= a[m];
}
else if(a[i] < secondsmallest) {
if(secondsmallest< thirdsmallest) {
nnm= nm;
thirdsmallest= secondsmallest;
}
nm= i;
secondsmallest= a[nm];
}
else if(a[i]< thirdsmallest) {
nnm= i;
thirdsmallest= a[nnm];
}
}
return new int[] {m, nm, nnm};
}
Getting the top or bottom k is usually done with a partial sort. There are versions that change the original array and those that dont.
If you only want the bottom (exactly) 3 and want to get their positions, not the values, your solution might be the best fit. This is how I would change it to support the bottom three. (I have not tried to compile and run, there may be little mistakes but the genereal idea should fit)
public static int[] lowerThree(int[] a) {
if (a.length < 3) throw
new java.util.NoSuchElementException("...");
int indexSmallest = 0;
int index2ndSmallest = 0;
int index3rdSmallest = 0;
int smallest = Integer.MAX_VALUE;
int sndSmallest = Integer.MAX_VALUE;
int trdSmallest = Integer.MAX_VALUE;
for (size_t i = 0; i < a.length; ++i) {
if (a[i] < trdSmallest) {
if (a[i] < sndSmallest) {
if (a[i] < smallest) {
trdSmallest = sndSmallest;
index3rdSmallest = index2ndSmallest;
sndSmallest = smallest;
index2ndSmallest = indexSmallest;
smallest = a[i];
indexSmallest = i;
continue;
}
trdSmallest = sndSmallest;
index3rdSmallest = index2ndSmallest;
sndSmallest = a[i];
index2ndSmallest = i;
continue;
}
trdSmallest = a[i];
index3rdSmallest = i;
}
}
return new int[] {indexSmallest, index2ndSmallest, index3rdSmallest};
}
This will have the three lowest numbers, need to add some test cases..but here is the idea
int[] arr = new int[3];
arr[0] = list.get(0);
if(list.get(1) <= arr[0]){
int temp = arr[0];
arr[0] = list.get(1);
arr[1] = temp;
}
else{
arr[1] = list.get(1);
}
if(list.get(2) < arr[1]){
if(list.get(2) < arr[0]){
arr[2] = arr[1];
arr[1] = arr[0];
arr[0] = list.get(2);
}
else{
arr[2] = arr[1];
arr[1] = list.get(2);
}
}else{
arr[2] = list.get(2);
}
for(int integer = 3 ; integer < list.size() ; integer++){
if(list.get(integer) < arr[0]){
int temp = arr[0];
arr[0] = list.get(integer);
arr[2] = arr[1];
arr[1] = temp;
}
else if(list.get(integer) < arr[1]){
int temp = arr[1];
arr[1] = list.get(integer);
arr[2] = temp;
}
else if(list.get(integer) <= arr[2]){
arr[2] = list.get(integer);
}
}
I'd store the lowest elements in a LinkedList, so it is not fixed on the lowest 3 elements. What do you think?
public static int[] lowest(int[] arr, int n) {
LinkedList<Integer> res = new LinkedList();
for(int i = 0; i < arr.length; i++) {
boolean added = false;
//iterate over all elements in the which are of interest (n first)
for(int j = 0; !added && j < n && j < res.size(); j++) {
if(arr[i] < res.get(j)) {
res.add(j, i); //the element is less than the element currently considered
//one of the lowest n, so insert it
added = true; //help me get out of the loop
}
}
//Still room in the list, so let's append it
if(!added && res.size() < n) {
res.add(i);
}
}
//copy first n indices to result array
int[] r = new int[n];
for(int i = 0; i < n && i < res.size(); i++) {
r[i] = res.get(i);
}
return r;
}
In simple words, you need to compare every new element with the maximum of the three you have at hand, and swap them if needed (and if you swap, max of the three has to be recalculated).
I would use 2 arrays of size 3 each:
arrValues = [aV1 aV2 aV3] (reals)
arrPointers = [aP1 aP2 aP3] (integers)
and a 64 bit integer type, call it maxPointer.
I will outline the algorithm logic, since I am not familiar with Java:
Set arrValues = array[0] array[1] array[2] (three first elements of your array)
Set arrPointers = [0 1 2] (or [1 2 3] if your array starts from 1)
Iterate over the remaining elements. In each loop:
Compare the Element scanned in this iteration with arrValues[maxPointer]
If Element <= arrValues[maxPointer],
remove the maxPointer element,
find the new max element and reset the maxPointer
Else
scan next element
End If
Loop
At termination, arrPointers should have the positions of the three smallest elements.
I hope this helps?
There is an easy way to find the positions of three lowest number in an Array
Example :
int[] arr={3,5,1,2,9,7};
int[] position=new int[arr.length];
for(int i=0;i<arr.length;i++)
{
position[i]=i;
}
for(int i=0;i<arr.length;i++)
{
for(int j=i+1;j<arr.length;j++)
{
if(arr[i]>arr[j]){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
int tem=position[i];
position[i]=position[j];
position[j]=tem;
}
}
}
System.out.println("Lowest numbers in ascending order");
for(int i=0;i<arr.length;i++)
{
System.out.println(arr[i]);
}
System.out.println("And their previous positions ");
for(int i=0;i<arr.length;i++)
{
System.out.println(position[i]);
}
Output
you can do it in 3 iterations.
You need two extra memory, one for location and one for value.
First iteration, you will keep the smallest value in one extra memory and its location in the second. As you are iterating, you compare every value in the slot with the value slot you keep in the memory, if the item you are visiting is smaller than what you have in your extra value slot, you replace the value as well as the location.
At the end of your first iteration, you will find the smallest element and its corresponding location.
You do the same for second and third smallest.

Categories