Adding and removing elements in an array: An exercise - java

I am looking to fill an array a with the numbers 1 through 10 and take a random number from that array and add it to an array b and remove that element from array a. I would like to know the most efficient way of doing this. EDIT: (The exercise requires that I not have repeated values in the arrays and that the permutation is random each time the method is called.) Here is my method so far:
public int[] nextPermutation() {
int capOne = 10;
int capTwo = 10;
int aSize = 0;
int bSize = 0;
int[] a = new int[capOne];
int[] b = new int[capTwo];
int upperBound = 11;
Random generator = new Random();
//fill initial array with 1 - 10
for (int i = aSize; i < 10; i++) {
a[i] = i + 1;
//companion variable for sizing array
aSize++;
}
//Create a random integer and add it to array b
//Remove same integer from array a
//Repeat and remove another random integer from the remaining integers in array a and add it to b
permuted = b;
return permuted;
}
I may be approaching this in an inefficient if not completely incorrect manner. If so, I'm sure you won't hesitate to tell me. Any help on this is greatly appreciated.

You can:
//randomly choose element
int index = (int) (Math.random() * aSize);
int dataFromA = a[index];
//"remove" it from A
aSize--;
for(int i = index; i<aSize; i++) {
a[i] = a[i+1];
}
//"add" it to b
b[bSize] = dataFromA;
bSize++;
Only interesting part is removing from A, where you have to reduce the size before the cycle (or you can i < aSize-1, then decrement size)
I guess you have to use arrays since this is an excersice, but using List for this would be better.

Here is a program producing random permutations, using swap. Well, I'm not sure which can produce a better result, but swap should be faster than add/remove to/from an array:
public int[] nextPermutation() {
int cap = 10;
int[] a = new int[cap];
Random generator = new Random();
//fill initial array with 1 - 10
for (int i = 0; i < cap; i++) {
a[i] = i + 1;
}
for (int i = 0; i < cap; i++) {
int j = generator.nextInt(cap);
int x = a[j];
a[j] = a[i];
a[i] = x;
}
// You can reduce the size of the output array:
// int output[] = new int[5];
// System.arraycopy(a, 0, output, 0, 5);
// return output;
return a;
}

Related

Random Char in 2D arrays

Hi i am new at java coding and am trying to create random numbers(which i have done) and i am trying to assign this random numbers as coordinates into the 2D array and print 'A' at the coordinates. Any help is appreciated.
package training;
import java.util.Random;
public class Training {
public static void main(String[] args) {
char[][] values = new char[10][10];
int foodX[] = new int[15];
for (int i = 1; i < foodX.length + 1; i++) {
int minFood = 0;
int maxFood = 10;
int randNum1 = minFood + (int) (Math.random() * (maxFood - minFood) + 1);
int minFoodY = 0;
int maxFoodY = 10;
int randNum2 = minFoodY + (int) (Math.random() * (maxFoodY - minFoodY) + 1);
for (int j = 1; j < foodX.length + 1; j++) {
values[randNum1][randNum2] = 'A';
}
}
// Assign three elements within it.
// Loop over top-level arrays.
for (int i = 0; i < values.length; i++) {
// Loop and display sub-arrays.
char[] sub = values[i];
for (int x = 0; x < sub.length; x++) {
System.out.print(sub[x] + " ");
}
System.out.println();
}
}
}
Arrays in Java are zero-indexed. What this means is that if you declare an array myArray as follows:
final int[] myArray = new int[10];
then you are creating a 10-element array which contains values in myArray[0], myArray[1], ..., myArray[9]. This also holds true for two-dimensional arrays, such as the values array in your code. However, you have defined randNum1 and randNum2 to return values in the range 1 to 10. When either of those values is set to 10, then values[randNum1][randNum2] will throw an ArrayIndexOutOfBoundsException, because you are trying to reference the array using indices that are out of its range.
In addition to this, you have created an array, foodX, which you do nothing with beyond determining its length. It's better in this case to declare an constant int value for this purpose. Finally, although you have imported the java.util.Random class, you are using Math.random() to generate random variables, which doesn't rely on this. You could alternatively use Random.nextDouble(), which would be useful if using a random number seed, but that's an aside.
Without following any additional considerations and to get your output simply to work as I believe is intended, I would therefore re-write your class in the following way:
package training;
public class Training {
public static void main(String[] args) {
char[][] values = new char[10][10];
int foodSize = 15
for (int i = 1; i <= foodSize; i++) {
int minFood = 0;
int maxFood = 10;
int randNum1 = minFood + (int) (Math.random() * (maxFood - minFood));
int minFoodY = 0;
int maxFoodY = 10;
int randNum2 = minFoodY + (int) (Math.random() * (maxFoodY - minFoodY));
values[randNum1][randNum2] = 'A';
// I've removed the for loop in the line above since it simply does the same thing 15 times and is inefficient
}
// Assign three elements within it.
// Loop over top-level arrays.
for (int i = 0; i < values.length; i++) {
// Loop and display sub-arrays.
char[] sub = values[i];
for (int x = 0; x < sub.length; x++) {
System.out.print(sub[x] + " ");
}
System.out.println();
}
}
}

Java sorting loop not working [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
. Basically what the following code does (suppose to) is, create a set of non-repeating random numbers, fill them up to an array which gets converted to a list, and sort them out. The problem is the nested for loops, i managed a work around but not even sure how it works. Secondely, i cant seem to sort it correctly, things repeat and out of bound errors pop up from time to time.
How the code works:
Generate non-repeating random numbers
Fill an array with them
Use nested for loop to find the smallest value
Insert that to a new array
Remove it from the first array
Repeat last 2 steps till the first array is empty and second array
os filled in a sorted order
import org.apache.commons.lang.ArrayUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.*;
import java.lang.*;
import java.io.*;
public class Sorter {
public static void main(String[] args) {
int[] process = fillArray(20,1,25);
sorter(process,20);
}
public static int[] sorter(int array[],int size) {
int[] useArray = array;
Integer[] newArray = ArrayUtils.toObject(useArray);
List<Integer> arrayList = new ArrayList(Arrays.asList(newArray));
//System.out.println((arrayList));
int counter = 1;
int minval = 0;
int diffsize = size - 1;
int actualVal = 0;
int storeArray[] = new int[size];
int removeIndex =0;
Integer[] newStore = ArrayUtils.toObject(storeArray);
List<Integer> storeList = new ArrayList(Arrays.asList(newStore));
System.out.println((arrayList));
// Both loops messed up
for (int i = 0; i < size+diffsize; i++) {
for (int n = 0; n < size-1; n++) {
if (arrayList.get(minval) < arrayList.get(counter)) {
actualVal = arrayList.get(minval);
System.out.println((arrayList.get(minval)) + " Less than " + arrayList.get(counter));
counter = counter + 1;
removeIndex = minval;
} else {
actualVal = arrayList.get(counter);
System.out.println((arrayList.get(counter)) + " Less than " + arrayList.get(minval));
minval = counter;
counter = counter + 1;
removeIndex = counter;
}
}
// System.out.println(actualVal);
storeList.add(actualVal);
arrayList.remove(actualVal); // need to remove the smallest value to repeat the sorting and get the next smallest value, but this is not removing it
size = size - 1;
counter = 1;
minval = 0;
// if (i + size == i) {
// storeList.set(i, arrayList.get(0));
// }
// System.out.println(removeIndex);
// System.out.println(arrayList);
}
// System.out.println(storeList);
int[] ints = new int[storeList.size()];
int d = 0;
for (Integer u : storeList) {
ints[d++] = u;
}
return ints;
}
public static int randomNum(int lower,int upper){
Random rand = new Random();
int randomNum = lower + rand.nextInt((upper- lower) + 1);
return randomNum;
}
public static int[] fillArray(int size,int lowerBound,int upperBound){
int holdArray[] = new int[size];
int rand = 0;
for (int count =0;count < holdArray.length;count++){
holdArray[count] = 0;
}
for (int count =0;count < holdArray.length;count++){
rand = randomNum(lowerBound,upperBound);
if (ArrayUtils.contains(holdArray, rand)) {
while (ArrayUtils.contains(holdArray, rand)) {
rand = randomNum(0, 20);
}
}
holdArray[count] = rand;
}
// System.out.println(Arrays.toString(holdArray));
//return holdArray;
return holdArray;
}
}
Can you give a compelling reason to justify in converting from array to list? why not use only list or only array altogether? I use ArrayList in my answer below;
First of, the fillArray class. You do not need to fill with all zeros. Why even bother to fill it with a value that you will replace anyway?
public static ArrayList<Integer> fillArray(int size,int lowerBound,int upperBound){
ArrayList<Integer> a = new ArrayList<Integer>(size);
for (int count =0;count < size;count++){
Integer rand = new Integer(randomNum(lowerBound,upperBound));
a.add(rand);
}
return a;
}
Second, the sorting class. Your method as you said, searching for lowest value then do magic stuff and what not.
public static ArrayList<Integer> sorter(ArrayList<Integer> unsorted) {
ArrayList<Integer> sortedArray = new ArrayList<Integer>(unsorted.size());
while(!unsorted.isEmpty()) { //repeats until the unsorted list is empty
int minval = unsorted.get(0);
int removeIndex = 0;
for(int i=1;i<unsorted.size();i++)
if (unsorted.get(i)<minval) {
minval = unsorted.get(i);
removeIndex = i;
}
sortedArray.add(minval);
unsorted.remove(removeIndex);
}
return sortedArray;
}
main method to test it
public static void main(String[] args) {
ArrayList<Integer> a = fillArray(20,1,25);
System.out.println("unsorted array");
for (Integer c : a)
System.out.print(c + ";");
ArrayList<Integer> b = sorter(a);
System.out.println("\nnew unsorted array");
for (Integer c : a)
System.out.print(c + ";");
System.out.println("\nsorted array");
for (Integer c : b)
System.out.print(c + ";");
}
this outputs
unsorted array
22;2;23;22;13;12;4;1;7;14;25;18;9;12;3;8;20;3;1;20;
new unsorted array
sorted array
1;1;2;3;3;4;7;8;9;12;12;13;14;18;20;20;22;22;23;25;
Separate out the "find the smallest" and "insertion/deletion" from arrays into two methods and then use them.
This way the code will be more manageable. Below is a sample find_min method.
int find_min(int[] array, int start) {
int min = Integer.MAX_VALUE;
for(int i = start; i < array.length; ++i)
if(array[i] < min)
min = array[i] ;
return min;
}
Now in the sorting routine, use the find_min to find the minimum element and insert it to new array and then delete the minimum element from the original array. However, this method does not return the index of the minimum element. So, I suggest you to modify it to return the index and the element as a pair of int values.
Your sorting routine will look something like this :
new_array := []
while(length(original_array) > 0)
min, min_index := find_min(original_array)
new_array.append(min)
original_array.delete(min_index)
You can use something like this to return an int pair :
class IntPair {
int min;
int index;
public IntPair(int x, int y) { this.min=x; this.index=y; }
public int get_min() { return min; }
public int get_min_index() { return index; }
}
Also, since you will de doing insertion and deletion, use ArrayList instead. It has methods to remove element at a particular index and append elements to it.
Note: Your approach outlined is close to Selection Sort algorithm in which we divide the array into two parts (sorted left part and unsorted right part) and repeatedly pick the smallest element from the right of the array and swap it with the left part's rightmost element.
min := array[0]
for(i := 0; i < array.length; ++i)
for(j := i+1; j < array.length; ++j)
if(array[j] < min)
min = array[j]
break
swap(array[i], array[j])
In this case, you dont need two arrays and you dont need to delete or insert elements into an array either.

array with non repeating numbers from a range in ascending order, java

Im trying to generate an array with 1000 integers of non-repeating numbers in ascending order from 0 to 10,000
So far what I have is:
public static void InitArray(int[] arr) { // InitArray method
int i, a_num; // int declared
Random my_rand_obj = new Random(); // random numbers
for (i = 0; i <= arr.length-1; i++) // for loop
{
a_num = my_rand_obj.nextInt(10000); // acquiring random numbers from 0 - 10000
arr[i] = a_num; // numbers being put into array (previoulsy declared of size 1000)
}
}
public static void ShowArray(int[] arr) { // ShowArray method
int i; // int declared
for (i = 0; i <= arr.length-1; i++) { // for loop
System.out.print(arr[i] + " "); // show current array content
}
System.out.println(); // empty line
}
public static void Sort(int[] arr) { // SortArray method
int i, min, j; // int decalred
for (i = 0; i < arr.length-1; i++) { // for loop
min = i; // min is i
for (j = i + 1; j < arr.length; j++) { // nested for loop
if (arr[j] < arr[min]) { // if statement
min = j; // j is the new minimum
}
}
int swap = arr[min]; // swap "method"
arr[min] = arr[i];
arr[i] = swap;
}
}
Is there any way to check the numbers are not repeating? Is there a function besides the random generator that will let me generate numbers without repeating? Thanks for any help
You can declare array of size 10,000
and init the array in away that each cell in the array will holds the value of it's index:
int [] arr= new int[10000];
for (int i=0 i < arr.length; i++){
arr[i] = i
}
Now you can shuffle the array using java Collections.
and take the first 1000 items from the array and sort then using java sort.
This will do I believe..
HashSet hs = new HashSet();
for(int i=0;i< arr.length;i++)
hs.add(arr[i]);
List<Integer> integers=new ArrayList<>(hs);
Collections.sort(integers);
A very simple solution is to generate the numbers cleverly. I have a solution. Though it may not have an even distribution, it's as simple as it can get. So, here goes:
public static int[] randomSortedArray (int minLimit, int maxLimit, int size) {
int range = (maxLimit - minLimit) / size;
int[] array = new int[size];
Random rand = new Random();
for (int i = 0; i < array.length; i++ ) {
array[i] = minLimit + rand.nextInt(range) + range * i;
}
return array;
}
So, in your case, call the method as:
int randomSortedArray = randomSortedArray(0, 10_000, 1_000);
It's very simple and doesn't require any sorting algorithm. It simply runs a single loop which makes it run in linear time (i.e. it is of time complexity = O(1)).
As a result, you get a randomly generated, "pre-sorted" int[] (int array) in unbelievable time!
Post a comment if you need an explanation of the algorithm (though it's fairly simple).

Get indices of n maximums in java array

I have an array of size 1000. How can I find the indices (indexes) of the five maximum elements?
An example with setup code and my attempt are displayed below:
Random rand = new Random();
int[] myArray = new int[1000];
int[] maxIndices = new int[5];
int[] maxValues = new int[5];
for (int i = 0; i < myArray.length; i++) {
myArray[i] = rand.nextInt();
}
for (int i = 0; i < 5; i++) {
maxIndices[i] = i;
maxValues[i] = myArray[i];
}
for (int i = 0; i < maxIndices.length; i++) {
for (int j = 0; j < myArray.length; j++) {
if (myArray[j] > maxValues[i]) {
maxIndices[i] = j;
maxValues[i] = myArray[j];
}
}
}
for (int i = 0; i < maxIndices.length; i++) {
System.out.println("Index: " + maxIndices[i]);
}
I know the problem is that it is constantly assigning the highest maximum value to all the maximum elements. I am unsure how to remedy this because I have to preserve the values and the indices of myArray.
I don't think sorting is an option because I need to preserve the indices. In fact, it is the indices that I need specifically.
Sorry to answer this old question but I am missing an implementation which has all following properties:
Easy to read
Performant
Handling of multiple same values
Therefore I implemented it:
private int[] getBestKIndices(float[] array, int num) {
//create sort able array with index and value pair
IndexValuePair[] pairs = new IndexValuePair[array.length];
for (int i = 0; i < array.length; i++) {
pairs[i] = new IndexValuePair(i, array[i]);
}
//sort
Arrays.sort(pairs, new Comparator<IndexValuePair>() {
public int compare(IndexValuePair o1, IndexValuePair o2) {
return Float.compare(o2.value, o1.value);
}
});
//extract the indices
int[] result = new int[num];
for (int i = 0; i < num; i++) {
result[i] = pairs[i].index;
}
return result;
}
private class IndexValuePair {
private int index;
private float value;
public IndexValuePair(int index, float value) {
this.index = index;
this.value = value;
}
}
Sorting is an option, at the expense of extra memory. Consider the following algorithm.
1. Allocate additional array and copy into - O(n)
2. Sort additional array - O(n lg n)
3. Lop off the top k elements (in this case 5) - O(n), since k could be up to n
4. Iterate over the original array - O(n)
4.a search the top k elements for to see if they contain the current element - O(lg n)
So it step 4 is (n * lg n), just like the sort. The entire algorithm is n lg n, and is very simple to code.
Here's a quick and dirty example. There may be bugs in it, and obviously null checking and the like come into play.
import java.util.Arrays;
class ArrayTest {
public static void main(String[] args) {
int[] arr = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10};
int[] indexes = indexesOfTopElements(arr,3);
for(int i = 0; i < indexes.length; i++) {
int index = indexes[i];
System.out.println(index + " " + arr[index]);
}
}
static int[] indexesOfTopElements(int[] orig, int nummax) {
int[] copy = Arrays.copyOf(orig,orig.length);
Arrays.sort(copy);
int[] honey = Arrays.copyOfRange(copy,copy.length - nummax, copy.length);
int[] result = new int[nummax];
int resultPos = 0;
for(int i = 0; i < orig.length; i++) {
int onTrial = orig[i];
int index = Arrays.binarySearch(honey,onTrial);
if(index < 0) continue;
result[resultPos++] = i;
}
return result;
}
}
There are other things you can do to reduce the overhead of this operation. For example instead of sorting, you could opt to use a queue that just tracks the largest 5. Being ints they values would probably have to be boxed to be added to a collection (unless you rolled your own) which adds to overhead significantly.
a bit late in answering, you could also use this function that I wrote:
/**
* Return the indexes correspond to the top-k largest in an array.
*/
public static int[] maxKIndex(double[] array, int top_k) {
double[] max = new double[top_k];
int[] maxIndex = new int[top_k];
Arrays.fill(max, Double.NEGATIVE_INFINITY);
Arrays.fill(maxIndex, -1);
top: for(int i = 0; i < array.length; i++) {
for(int j = 0; j < top_k; j++) {
if(array[i] > max[j]) {
for(int x = top_k - 1; x > j; x--) {
maxIndex[x] = maxIndex[x-1]; max[x] = max[x-1];
}
maxIndex[j] = i; max[j] = array[i];
continue top;
}
}
}
return maxIndex;
}
My quick and a bit "think outside the box" idea would be to use the EvictingQueue that holds an maximum of 5 elements. You'd had to pre-fill it with the first five elements from your array (do it in a ascending order, so the first element you add is the lowest from the five).
Than you have to iterate through the array and add a new element to the queue whenever the current value is greater than the lowest value in the queue. To remember the indexes, create a wrapper object (a value/index pair).
After iterating through the whole array, you have your five maximum value/index pairs in the queue (in descending order).
It's a O(n) solution.
Arrays.sort(myArray), then take the final 5 elements.
Sort a copy if you want to preserve the original order.
If you want the indices, there isn't a quick-and-dirty solution as there would be in python or some other languages. You sort and scan, but that's ugly.
Or you could go objecty - this is java, after all.
Make an ArrayMaxFilter object. It'll have a private class ArrayElement, which consists of an index and a value and has a natural ordering by value. It'll have a method which takes a pair of ints, index and value, creates an ArrayElement of them, and drops them into a priority queue of length 5. (or however many you want to find). Submit each index/value pair from the array, then report out the values remaining in the queue.
(yes, a priority queue traditionally keeps the lowest values, but you can flip this in your implementation)
Here is my solution. Create a class that pairs an indice with a value:
public class IndiceValuePair{
private int indice;
private int value;
public IndiceValuePair(int ind, int val){
indice = ind;
value = val;
}
public int getIndice(){
return indice;
}
public int getValue(){
return value;
}
}
and then use this class in your main method:
public static void main(String[] args){
Random rand = new Random();
int[] myArray = new int[10];
IndiceValuePair[] pairs = new IndiceValuePair[5];
System.out.println("Here are the indices and their values:");
for(int i = 0; i < myArray.length; i++) {
myArray[i] = rand.nextInt(100);
System.out.println(i+ ": " + myArray[i]);
for(int j = 0; j < pairs.length; j++){
//for the first five entries
if(pairs[j] == null){
pairs[j] = new IndiceValuePair(i, myArray[i]);
break;
}
else if(pairs[j].getValue() < myArray[i]){
//inserts the new pair into its correct spot
for(int k = 4; k > j; k--){
pairs[k] = pairs [k-1];
}
pairs[j] = new IndiceValuePair(i, myArray[i]);
break;
}
}
}
System.out.println("\n5 Max indices and their values");
for(int i = 0; i < pairs.length; i++){
System.out.println(pairs[i].getIndice() + ": " + pairs[i].getValue());
}
}
and example output from a run:
Here are the indices and their values:
0: 13
1: 71
2: 45
3: 38
4: 43
5: 9
6: 4
7: 5
8: 59
9: 60
5 Max indices and their values
1: 71
9: 60
8: 59
2: 45
4: 43
The example I provided only generates ten ints with a value between 0 and 99 just so that I could see that it worked. You can easily change this to fit 1000 values of any size. Also, rather than run 3 separate for loops, I checked to see if the newest value I add is a max value right after I add to to myArray. Give it a run and see if it works for you

Java: create array with random int's (int's can only be used once)

I have an array called arr, with place for 15 elements.
I need to place the numbers 1 through 15 in a random order into that array.
Here is what I have tried:
int[] arr = new int[15];
int i,j,k,n;
for (i = 0; i<15; i++) {
for (j=0; j<15; j++) {
n = (int)(Math.random() * 14 + 1);
if (rij[j] != n) {
rij[i] = n;
break;
}
}
}
Thanks! :)
Use an ArrayList and fill it up with numbers 1 to 15.
Shuffle the list.
Convert it to an array.
This seems like homework (or an interview question?). If that's the case and you are required to use arrays rather than the built in methods with the Java Collection Objects, (or even if not, really), the answer is the Fisher-Yates Shuffle algorithm
The modern in-place shuffle is:
To shuffle an array a of n elements (indexes 0..n-1):
for i from n − 1 downto 1 do
j ← random integer with 0 ≤ j ≤ i
exchange a[j] and a[i]
(I'd have to check, but I suspect this is what Java uses under the hood for its shuffle() methods).
Edit because it's fun to implement algorithms:
In java, this would be:
public static void main(String[] args) {
int[] a = new int[15];
for (int i = 1; i <= 15; i++)
{
a[i-1] = i;
}
Random rg = new Random();
int tmp;
for (int i = 14; i > 0; i--)
{
int r = rg.nextInt(i+1);
tmp = a[r];
a[r] = a[i];
a[i] = tmp;
}
for (int i = 0; i < 15; i++)
System.out.print(a[i] + " ");
System.out.println();
}
And ... this can be further optimized using the inside-out version of the algo since you're wanting to insert a known series of numbers in random order. The following is the best way to achieve what you stated as wanting to do as there are no extra copies being made such as when creating an ArrayList and having it copy back out to an array.
a = new int[15];
Random rg = new Random();
for (int i = 0; i < 15; i++)
{
int r = rg.nextInt(i+1);
a[i] = a[r];
a[r] = i+1;
}
Do it like this
// Create an ordered list
List<Integer> list = new ArrayList<Integer>();
for (int i = 1; i < 16; i++) {
list.add(i);
}
// Shuffle it
Collections.shuffle(list);
// Get an Integer[] array
Integer[] array1 = list.toArray(new Integer[list.size()]);
// Get an int[] array
int[] array2 = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
array2[i] = list.get(i);
}
This will leave the elements randomly shuffled in a Integer[], if that's fine with you:
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < 15; i++)
list.add(i + 1);
Collections.shuffle(list);
Integer[] arr = list.toArray(new Integer[0]);
I will do something like this:
First create a temporary arraylist filled with numbers from start to end, then using random select a number, copy it into array and remove it from the temp arraylist, repeat until the arraylist is empty...
ArrayList<Integer> arr = new ArrayList<Integer>();
int[] arr2 = new int[15];
int i,j,k,n;
for (i=0;i<15;i++) arr.add(i+1);
i=0;
while(arr.size()>0){
n = (int)(Math.random() * (14 + 1 - i));
arr2[i]=arr.get(n);
arr.remove(n);
i++;
}

Categories

Resources