So far, I only get the part where I can count one particular value in an array array. However, I would like to know how to get occurrence of 'every' number in an array and display them.
Here is the code I've got -
public class CIS3618thAssignment
{
public static void main(String[] args) {
int[] randomNumbers = new int[100];
for(int index = 0; index < randomNumbers.length; index++)
{
randomNumbers[index] = (int) (Math.random()*100);
}
for(int index = 0; index < randomNumbers.length; index++)
{
System.out.println(randomNumbers[index]);
}
System.out.println("Occurrence of 2 is " + GetOccurrence(2, randomNumbers, 0, randomNumbers.length));
}
public static int GetOccurrence(int k, int[] numbers, int startIndex, int endIndex)
{
if(endIndex<startIndex)
return 0;
if(numbers[startIndex]>k)
return 0;
if(numbers[endIndex]<k)
return 0;
if(numbers[startIndex]==k && numbers[endIndex]==k)
return endIndex-startIndex +1;
int midInd = (startIndex+endIndex)/2;
if(numbers[midInd]==k)
return 1+GetOccurrence(k, numbers, startIndex, midInd-1) + GetOccurrence(k, numbers, midInd+1,endIndex);
else if(numbers[midInd]>k)
return GetOccurrence(k, numbers, startIndex, midInd-1);
else
return GetOccurrence(k, numbers, midInd+1, endIndex);
}
}
So, in the source code, I am only capable of getting the occurrence of the value = 2 out of the array.
By reading your codes, it seems that you are trying to find the element by binary search? But you know that binary search works on sorted array. I didn't see the sorting part in your codes.
For your requirement, why not just build a Map<Integer,Integer> the key is the number, the value is the occurrence? It makes your implementation a lot easier.
You could use HashMap, where key is given number and value is number of occurrences.
You iterate over array and if the key(number) already exists, increment value(occurrences). Else, add new key and set its value to 1.
Check this DEMO.
I guess is what you want...
I didn't use Map or recursion as in your code, important for-loop to count is this one:
int[] results = new int[100];
// fill map with results
for(int index = 0; index < randomNumbers.length; index++)
{
// if number on randomnumbers is 2, this line sum +1 in position 2 of the array
results[randomNumbers[index]] = results[randomNumbers[index]] + 1;
}
Put this line in the loop:
System.out.println("Occurrence of 2 is " + GetOccurrence(2, randomNumbers, 0, randomNumbers.length));
And change it as follows:
for(int index = 0; index < randomNumbers.length; index++) {
System.out.println("Occurrence of " + randomNumbers[index] + " is " + GetOccurrence(randomNumbers[index], randomNumbers, 0, randomNumbers.length));
}
Related
I found this code online and it works well to permute through the given array and return all possible combinations of the numbers given. Does anyone know how to change this code to incorporate a 2D array instead?
public static ArrayList<ArrayList<Integer>> permute(int[] numbers) {
ArrayList<ArrayList<Integer>> permutations = new ArrayList<ArrayList<Integer>>();
permutations.add(new ArrayList<Integer>());
for ( int i = 0; i < numbers.length; i++ ) {
ArrayList<ArrayList<Integer>> current = new ArrayList<ArrayList<Integer>>();
for ( ArrayList<Integer> p : permutations ) {
for ( int j = 0, n = p.size() + 1; j < n; j++ ) {
ArrayList<Integer> temp = new ArrayList<Integer>(p);
temp.add(j, numbers[i]);
current.add(temp);
}
}
permutations = new ArrayList<ArrayList<Integer>>(current);
}
return permutations;
}
This is what I have attempted:
public static int[][] permute(int[] numbers){
int[][] permutations = new int[24][4];
permutations[0] = new int[4];
for ( int i = 0; i < numbers.length; i++ ) {
int[][] current = new int[24][4];
for ( int[] permutation : permutations ) {
for ( int j = 0; j < permutation.length; j++ ) {
permutation[j] = numbers[i];
int[] temp = new int[4];
current[i] = temp;
}
}
permutations = current;
}
return permutations;
}
However this returns all zeroes. I chose 24 and 4 because that is the size of the 2D array that I need.
Thanks
It’s not really that easy. The original code exploits the more dynamic behaviour of ArrayList, so a bit of hand coding will be necessary. There are many correct thoughts in your code. I tried to write an explanation of the issues I saw, but it became too long, so I decided to modify your code instead.
The original temp.add(j, numbers[i]); is the hardest part to do with arrays since it invloves pushing the elements to the right of position j one position to the right. In my version I create a temp array just once in the middle loop and shuffle one element at a time in the innermost loop.
public static int[][] permute(int[] numbers) {
// Follow the original here and create an array of just 1 array of length 0
int[][] permutations = new int[1][0];
for (int i = 0; i < numbers.length; i++) {
// insert numbers[i] into each possible position in each array already in permutations.
// create array with enough room: when before we had permutations.length arrays, we will now need:
int[][] current = new int[(permutations[0].length + 1) * permutations.length][];
int count = 0; // number of new permutations in current
for (int[] permutation : permutations) {
// insert numbers[i] into each of the permutation.length + 1 possible positions of permutation.
// to avoid too much shuffling, create a temp array
// and use it for all new permutations made from permutation.
int[] temp = Arrays.copyOf(permutation, permutation.length + 1);
for (int j = permutation.length; j > 0; j--) {
temp[j] = numbers[i];
// remember to make a copy of the temp array
current[count] = temp.clone();
count++;
// move element to make room for numbers[i] at next position to the left
temp[j] = temp[j - 1];
}
temp[0] = numbers[i];
current[count] = temp.clone();
count++;
}
assert count == current.length : "" + count + " != " + current.length;
permutations = current;
}
return permutations;
}
My trick with the temp array means I don’t get the permutations in the same order as in the origianl code. If this is a requirement, you may copy permutation into temp starting at index 1 and shuffle the opposite way in the loop. System.arraycopy() may do the initial copying.
The problem here is that you really need to implement properly the array version of the ArrayList.add(int,value) command. Which is to say you do an System.arraycopy() and push all the values after j, down one and then insert the value at j. You currently set the value. But, that overwrites the value of permutation[j], which should actually have been moved to permutations[j+1] already.
So where you do:
permutation[j] = numbers[i];
It should be:
System.arraycopy(permutation,j, permutations, j+1, permutations.length -j);
permutation[j] = numbers[i];
As the ArrayList.add(int,value) does that. You basically wrongly implemented it as .set().
Though personally I would scrap the code and go with something to dynamically make those values on the fly. A few more values and you're talking something prohibitive with regard to memory. It isn't hard to find the nth index of a permutation. Even without allocating any memory at all. (though you need a copy of the array if you're going to fiddle with such things without incurring oddities).
public static int[] permute(int[] values, long index) {
int[] returnvalues = Arrays.copyOf(values,values.length);
if (permutation(returnvalues, index)) return returnvalues;
else return null;
}
public static boolean permutation(int[] values, long index) {
return permutation(values, values.length, index);
}
private static boolean permutation(int[] values, int n, long index) {
if ((index == 0) || (n == 0)) return (index == 0);
int v = n-(int)(index % n);
int temp = values[n];
values[n] = values[v];
values[v] = temp;
return permutation(values,n-1,index/n);
}
This question follows my brevious one on how to Return value of smallest index of repeated number in array.
In this function given to me by #Andreas:
private static void printFirstIndexOfRepeated(int[] values) {
Integer firstIndex = null;
Map<Integer, Integer> mapValueToIndex = new HashMap<>();
for (int i = 0; i < values.length; i++) {
Integer prevIndex = mapValueToIndex.put(values[i], i); // put() returns old value, or null
if (prevIndex != null && (firstIndex == null || prevIndex < firstIndex))
firstIndex = prevIndex;
}
if (firstIndex != null)
System.out.println("First index of repeated: " + firstIndex);
else
System.out.println("No repeat found");
}
Function test:
int [] array = {10,5, 4, 3, 5, 6};
printFirstIndexOfRepeated(array);
Output
First index of repeated: 1 // it looks for 5 and return the value of smallest index of repeated 5 in array.
Due to my lack of programming knowledge with Map, I'm new and I know only Array. I need some help to transform this function and add another parameter like (int number) to decide witch number I'm looking for and not automatically
The desired one: printFirstIndexOfRepeated(int[] values, int number)
So because you basically just want the index of the first occurrence of a given number inside an array, you don't need the Map at all. Instead you can just use a simple for loop:
private static int printFirstIndexOfRepeated(int[] values,int number) {
for(int i = 0; i < values.length; i++){
if(values[i] == number){
//System.out.println("The first index of " + number + " is " + i);
return i;
}
}
//System.out.println(number + " is not a member of the array.");
return -1;
}
This function returns the first index of a given number or -1 if the number was not found. You can uncomment the print lines to also get an output if you like (or just delete them).
Let's say I have an array in the length of n, and the only values that can appear in it are 0-9. I want to create a recursive function that returns the number of different values in the array.
For example, for the following array: int[] arr = {0,1,1,2,1,0,1} --> the function will return 3 because the only values appearing in this array are 0, 1 and 2.
The function receives an int array and returns int
something like this:
int numOfValues(int[] arr)
If you are using Java 8, you can do this with a simple one-liner:
private static int numOfValues(int[] arr) {
return (int) Arrays.stream(arr).distinct().count();
}
Arrays.stream(array) returns an IntStream consisting of the elements of the array. Then, distinct() returns an IntStream containing only the distinct elements of this stream. Finally, count() returns the number of elements in this stream.
Note that count() returns a long so we need to cast it to an int in your case.
If you really want a recursive solution, you may consider the following algorithm:
If the input array is of length 1 then the element is distinct so the answer is 1.
Otherwise, let's drop the first element and calculate the number of distinct elements on this new array (by a recursive call). Then, if the first element is contained in this new array, we do not count it again, otherwise we do and we add 1.
This should give you enough insight to implement this in code.
Try like this:
public int myFunc(int[] array) {
Set<Integer> set = new HashSet<Integer>(array.length);
for (int i : array) {
set.add(i);
}
return set.size();
}
i.e, add the elements of array inside Set and then you can return the size of Set.
public int f(int[] array) {
int[] counts = new int[10];
int distinct = 0;
for(int i = 0; i< array.length; i++) counts[array[i]]++;
for(int i = 0; i< counts.length; i++) if(counts[array[i]]!=0) distinct++;
return distinct;
}
You can even change the code to get the occurrences of each value.
You can try following code snippet,
Integer[] arr = {0,1,1,2,1,0,1};
Set<Integer> s = new HashSet<Integer>(Arrays.asList(arr));
Output: [0, 1, 2]
As you asked for a recursive implementation, this is one bad way to do that. I say bad because recursion is not the best way to solve this problem. There are other easier way. You usually use recursion when you want to evaluate the next item based on the previously generated items from that function. Like Fibonacci series.
Ofcourse you will have to clone the array before you use this function otherwise your original array would be changed (call it using countDistinct(arr.clone(), 0);)
public static int countDistinct(int[] arr, final int index) {
boolean contains = false;
if (arr == null || index == arr.length) {
return 0;
} else if (arr.length == 1) {
return 1;
} else if (arr[index] != -1) {
contains = true;
for (int i = index + 1; i < arr.length; i++) {
if (arr[index] == arr[i]) {
arr[i] = -1;
}
}
}
return countDistinct(arr, index + 1) + (contains ? 1 : 0);
}
int numOfValues(int[] arr) {
boolean[] c = new boolean[10];
int count = 0;
for(int i =0; i < arr.length; i++) {
if(!c[arr[i]]) {
c[arr[i]] = true;
count++;
}
}
return count;
}
I tried to generate a sorted list of random data with no duplicates in descending order for my array. It also returns number of duplicates, but it keeps printing out nothing but zero .... Can anyone help me please :(
// 2. Ask the user for size of arbitrary numbers.
System.out.print("Please enter a size for arbitray numbers: ");
int size = indata.nextInt();
int [] SortedNumbers = new int [size];
// 3. Process arbitrary numbers and remove all duplicates
int numDuplicates = generate_data(SortedNumbers);
// 4. Print the numbers and number of duplicates
printArray(SortedNumbers, numDuplicates);
and here is the random method
public static int generate_data (int [ ] list){
int duplicates = 0;
Random random = new Random();
System.out.println(n[random.nextInt(n.length)]);
return duplicates;
}
here is the print_array method
public static void printArray(int [] list, int duplicates) {
// Additional code required
System.out.println("\nSize of array: " + list.length + " .Numbers of duplicates: " + duplicates); for (int i = 0; i<list.length; i++){
System.out.printf("%7d", list[i]);
if ((i + 1) % 10 == 0){
System.out.println();
}
}
}
random.nextInt(n.length)
gives you a random index of your array.
But printing the value corresponding to this index, will always give you 0. As you never store any other value in the array.
You should rather do something like this :
int[] list = new int[10];
int duplicates = 0;
Random random = new Random();
for (int i = 0; i < list.length; i++) {
int nextVal = random.nextInt(list.length);
System.out.println("list["+i+"] = "+ nextVal);
// test duplicates
for (int index = 0; index < i; index++) {
if (list[index] == nextVal) {
duplicates++;
break;
}
}
list[i] = nextVal;
}
return duplicates;
Your generate_data method always returns 0, since the local field duplicates is initialized with a 0 value and never changed.
The n field referenced by your generate_data method (which you haven't posted) is likely to be an int[], but its elements might not have been initialized (hence the print out will print default value 0, if within array index).
Hence your numDuplicates local field is always 0 too.
Notes
Your Random initialization is not performing. You should initialize a static Random object in your class and re-use it, instead of re-initializing every time in your generate_data method.
You probably want to have a look at coding conventions for Java in terms of field naming
You might want to post the code in your printArray method as well
Given an array of integers ranging from 1 to 60, i'm attempting to find how many times the numbers 1-44 appear in the array. Here is my method
public static void mostPopular(int[] list, int count)
{
int[] numbers;
numbers = new int[44];
for (int i = 0; i<count;i++)
{
if (list[i]<45 )
{
numbers[i-1]=numbers[i-1]+1; //error here
}
}
for (int k=0; k<44;k++)
{
System.out.println("Number " + k + " occurs " + numbers[k-1]+ "times");
}
}
I'm trying to iterate through the array, list, that contains over 5000 numbers that are between 1-60, then test if that number is less than 45 making it a number of interest to me, then if the integer is 7 for example it would increment numbers[6] By 1. list is the array of numbers and count is how many total numbers there are in the array. I keep getting an ArrayIndexOutOfBoundsException. How do I go about fixing this?
Replace this line numbers[i-1]=numbers[i-1]+1;
with numbers[list[i] - 1] = numbers[list[i] - 1] + 1;
Now it will update the count of correct element.
You need to increment numbers[list[i]] because that's your value which is smaller than 45. i goes up to 5000 and your array numbers is too small.
You should really start using a debugger. All the modern IDE have support for it (Eclipse, IntelliJ, Netbeans, etc.). With the debugger you would have realized the mistake very quickly.
If your initial value is less than 45, it will add 1 to numbers[i-1]. However, since you start with i=0, it will try to add 1 to the value located at numbers[-1], which doesn't exist by law of arrays. Change i to start at 1 and you should be okay.
Very close, but a few indexing errors, remember 0-1 = -1, which isn't an available index. Also, this isn't c, so you can call list.length to get the size of the list.
Try this (you can ignore the stuff outside of the mostPopular method):
class Tester{
public static void main(String args[]){
int[] list = new int[1000];
Random random = new Random();
for(int i=0; i<list.length; i++){
list[i] = random.nextInt(60) + 1;
}
mostPopular(list);
}
public static void mostPopular(int[] list)
{
int[] numbers = new int[44];
for (int i = 0; i< list.length ;i++)
{
int currentInt = list[i];
if(currentInt<45 )
{
numbers[currentInt - 1] = (numbers[currentInt -1] + 1);
}
}
for (int k=0; k<numbers.length; k++)
{
System.out.println("Number " + (k+1) + " occurs " + numbers[k]+ "times");
}
}
}
When i is 0, i-1 is -1 -- an invalid index. I think that you want the value from list to be index into numbers. Additionally, valid indices run from 0 through 43 for an array of length 44. Try an array of length 45, so you have valid indices 0 through 44.
numbers = new int[45];
and
if (list[i] < 45)
{
// Use the value of `list` as an index into `numbers`.
numbers[list[i]] = numbers[list[i]] + 1;
}
numbers[i-1]=numbers[i-1]+1; //error here
change to
numbers[list[i]-1] += 1;
as list[i]-1 because your number[0] store the frequency of 1 and so on.
we increase the corresponding array element with index equal to the list value minus 1
public static void mostPopular(int[] list, int count)
{
int[] numbers = new int[44];
for (int i = 0; i<count;i++)
{
//in case your list value has value less than 1
if ( (list[i]<45) && (list[i]>0) )
{
//resolve error
numbers[list[i]-1] += 1;
}
}
//k should start from 1 but not 0 because we don't have index of -1
//k < 44 change to k <= 44 because now our index is 0 to 43 with [k-1]
for (int k=1; k <= 44;k++)
{
System.out.println("Number " + k + " occurs " + numbers[k-1]+ "times");
}
}