Background:
I have an N-length array of positive random numbers that are certain to contain duplicates.
e.g. 10,4,5,7,10,9,10,9,8,10,5
Edit: N is likely to be 32, or some other power of two about that size.
The Problem:
I am trying to find the fastest way to replace the duplicates with the missing numbers from 0-(N-1). Using the above example, I want a result that looks like this:
10,4,5,7,0,9,1,2,8,3,6
The goal being to have one of each number from 0 to N-1, without just replacing all the numbers with 0-(N-1) (the random order is important).
Edit: It's also important that this replacement is deterministic, i.e. the same input will have the same output (not random).
My solution:
Currently implemented in Java, uses 2 boolean arrays to keep track of used/unused numbers (unique numbers/missing numbers in the range [0,N) ), and has an approximate worst-case runtime of N+N*sqrt(N).
The code follows:
public byte[] uniqueify(byte[] input)
{
boolean[] usedNumbers = new boolean[N];
boolean[] unusedIndices = new boolean[N];
byte[] result = new byte[N];
for(int i = 0; i < N; i++) // first pass through
{
int newIdx = (input[i] + 128) % N; // first make positive
if(!usedNumbers[newIdx]) // if this number has not been used
{
usedNumbers[newIdx] = true; // mark as used
result[i] = newIdx; // save it in the result
}
else // if the number is used
{
unusedIndices[i] = true; // add it to the list of duplicates
}
}
// handle all the duplicates
for(int idx = 0; idx < N; idx++) // iterate through all numbers
{
if(unusedIndices[idx]) // if unused
for(int i = 0; i < N; i++) // go through all numbers again
{
if(!usedNumbers[i]) // if this number is still unused
{
usedNumbers[i] = true; // mark as used
result[i] = idx;
break;
}
}
}
return result;
}
This seems like the fastest I can hope for, but I thought I'd ask the internet, because there are people much more clever than I who may have a better solution.
N.B. Suggestions/solutions do not have to be in Java.
Thank you.
Edit: I forgot to mention that I am converting this to C++. I posted my java implementation because it's more complete.
Use a balanced binary search tree to keep track of used/unused numbers instead of a boolean array. Then you're running time will be n log n.
The most straightforward solution would be this:
Go through the list and build the "unused" BST
Go through the list a second time, keeping track of numbers seen so far in a "used" BST
If a duplicate is found, replace it with a random element of the "unused" BST.
Here is how I would write it.
public static int[] uniqueify(int... input) {
Set<Integer> unused = new HashSet<>();
for (int j = 0; j < input.length; j++) unused.add(j);
for (int i : input) unused.remove(i);
Iterator<Integer> iter = unused.iterator();
Set<Integer> unique = new LinkedHashSet<>();
for (int i : input)
if (!unique.add(i))
unique.add(iter.next());
int[] result = new int[input.length];
int k = 0;
for (int i : unique) result[k++] = i;
return result;
}
public static void main(String... args) {
System.out.println(Arrays.toString(uniqueify(10, 4, 5, 7, 10, 9, 10, 9, 8, 10, 5)));
}
prints
[10, 4, 5, 7, 0, 9, 1, 2, 8, 3, 6]
The fastest way to do this is probably the most straightforward one. I would take a pass through the list of data keeping a count of each distinct value and marking where duplicates appeared. Then it is just a matter of forming a list of unused values and applying them in turn at the places where duplicates were found.
Tempting as it may be to use a C++ List, if speed is of the essence a simple C array is the most efficient.
This program show the principle.
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
int data[] = { 10, 4, 5, 7, 10, 9, 10, 9, 8, 10, 5 };
int N = sizeof(data) / sizeof(data[0]);
int tally[N];
memset(tally, 0, sizeof(tally));
int dup_indices[N];
int ndups = 0;
// Build a count of each value and a list of indices of duplicate data
for (int i = 0; i < N; i++) {
if (tally[data[i]]++) {
dup_indices[ndups++] = i;
}
}
// Replace each duplicate with the next value having a zero count
int t = 0;
for (int i = 0; i < ndups; i++) {
while (tally[t]) t++;
data[dup_indices[i]] = t++;
}
for (int i = 0; i < N; i++) {
cout << data[i] << " ";
}
return 0;
}
output
10 4 5 7 0 9 1 2 8 3 6
My approach would be
1. copy the array to a Set in Java.
Set will automatically remove duplicates in the fastest complexity possible(because Sun Micro has implemented it, generally their approach is the fastest like.. use of TimSort for sorting etc...)
Calculate size() of the set.
the size will give you no of duplicates present.
now copy array 0-n-1 to the same set... the missing values will get inserted.
I think it is even possible with running time n. The idea is to keep track of items used in the original list and additional items used during processing in a separate array. A possible java implementation looks like this:
int[] list = { 10, 4, 5, 7, 10, 9, 10, 9, 8, 10, 5 };
boolean[] used = new boolean[list.length];
for (int i : list) {
used[i] = true;
}
boolean[] done = new boolean[list.length];
int nextUnused = 0;
Arrays.fill(done, false);
for (int idx = 0; idx < list.length; idx++) {
if (done[list[idx]]) {
list[idx] = nextUnused;
}
done[list[idx]] = true;
while (nextUnused < list.length && (done[nextUnused] || used[nextUnused])) {
nextUnused++;
}
}
System.out.println(Arrays.toString(list));
List<Integer> needsReplaced = newLinkedList<Integer>();
boolean[] seen = new boolean[input.length];
for (int i = 0; i < input.length; ++i) {
if (seen[input[i]]) {
needsReplaced.add(i);
} else {
seen[input[i]] = true;
}
}
int replaceWith = 0;
for (int i : needsReplaced) {
while (seen[replaceWith]) {
++replaceWith;
}
input[i] = replaceWith++;
}
This should behave in about 2n. The list operations are constant time, and even though that second loop looks nested, the outer loop runs significantly less than n iterations, and the inner loop will only run a total of n times.
C# but should be easy to convert to java. O(n).
int[] list = { 0, 0, 6, 0, 5, 0, 4, 0, 1, 2, 3 };
int N = list.length;
boolean[] InList = new boolean[N];
boolean[] Used = new boolean[N];
int[] Unused = new int[N];
for (int i = 0; i < N; i++) InList[list[i]] = true;
for (int i = 0, j = 0; i < N; i++)
if (InList[i] == false)
Unused[j++] = i;
int UnusedIndex = 0;
for (int i = 0; i < N; i++)
{
if (Used[list[i]] == true)
list[i] = Unused[UnusedIndex++];
Used[list[i]] = true;
}
Edit: tried to convert it to java from c#. I don't have java here so it may not compile but should be easy to fix. The arrays may need to be initialized to false if java doesn't do that automatically.
Related
I'm trying to get the N smallest numbers (given by the user) in an array without using methods like sort()... in the last step, I keep getting only the smallest values and 0 for the rest.. where's the problem?
//1- Scanner to take inputs
Scanner input = new Scanner(System.in);
//2- Take the array size as input and store it in "sizeOfArr" var
System.out.print("Enter the array size: ");
int sizeOfArr = input.nextInt();
//3- Assign the input as an array size
int array[] = new int[sizeOfArr];
//4- Looping on the array and update its values by inputs taken from the user
for(int i = 0; i < array.length; i++) {
System.out.print("Enter "+ (i+1) + "-st element: ");
array[i] = input.nextInt();
}
//5- Print out the array after convert it to String
System.out.println(Arrays.toString(array));
//6- Find the smallest element in the array and print it
int minVal = array[0];
for(int i = 0; i < array.length; i++) {
if (array[i] < minVal) {
minVal = array[i];
}
}
// System.out.println(minVal);
//7- Find the (n) smallest of number defined by the user
System.out.print("Enter the number of smallest numbers do you want: ");
int n = input.nextInt();
//8- new array to store n smallest numbers
int smallestNums[] = new int[n];
//9- trying to loop on the original array n times
int counter;
for(int i = 0; i < n ; i++) {
//10- trying to loop on the original array to store the smallest values in smallestNum[] array.
for(int j = 0; j < array.length; j++) {
smallestNums[i] = minVal;
}
if(smallestNums[i] == smallestNums[i]) {
break;
}
}
System.out.println(Arrays.toString(smallestNums));
Here is one way. Just do a partial sort with the outer loop limit equal to the number of items required. This is variant of the selection sort. This example, varies n in the outer list for demo purposes.
int[] array = { 10, 1, 5, 8, 7, 6, 3 };
for (int n = 1; n <= array.length; n++) {
int[] smallest = getNSmallest(n, array);
System.out.printf("smallest %2d = %s%n", n,
Arrays.toString(smallest));
}
prints
smallest 1 = [1]
smallest 2 = [1, 3]
smallest 3 = [1, 3, 5]
smallest 4 = [1, 3, 5, 6]
smallest 5 = [1, 3, 5, 6, 7]
smallest 6 = [1, 3, 5, 6, 7, 8]
smallest 7 = [1, 3, 5, 6, 7, 8, 10]
Here is the method. The first thing to do is copy the array so the
original is preserved. Then just do the sort and return array of smallest elements.
public static int[] getNSmallest(int n, int[] arr) {
int[] ar = Arrays.copyOf(arr, arr.length);
int[] smallest = new int[n];
for (int i = 0; i < n; i++) {
for (int k = i + 1; k < ar.length; k++) {
if (ar[i] > ar[k]) {
int t = ar[i];
ar[i] = ar[k];
ar[k] = t;
}
}
smallest[i] = ar[i];
}
return smallest;
}
For this task, you don't have to sort the whole array. Only a group of N elements has to be sorted. I.e. only a partial sorting is required.
Below, I've provided two implementations for this problem. The first utilizes only plane arrays and loops, the second makes use of the PriorytyQueue.
The first solution maintains a variable pos which denotes the position in the result array which isn't assigned yet. Note that the default value for an element of the int[] is 0. It's important to be able to distinguish between the default value and a zero-element from the given array. Hence we can't rely on the values and have to track the number of elements that are assigned.
Every element of the source array gets compared with all the elements of the result array that are already assigned. The new element will be added to the result array in two cases:
nested loop has reached an unoccupied position pos in the result array;
an element in the result array that is greater than the next element from the given array has been found.
In the first case, a new element gets assigned the position denoted by pos. In the second case, a new element has to be inserted
nested loop iterates over the given array at the current position i and all elements must be shifted to the right. That's what the method shiftElements() does.
The First solution - Arrays & Loops
public static int[] getSmallest(int[] arr, int limit) {
int[] result = new int[Math.min(limit, arr.length)];
int pos = 0;
for (int next: arr) {
for (int i = 0; i < Math.min(pos + 1, result.length); i++) {
if (i == pos) result[i] = next;
else if (result[i] > next) {
shiftElements(result, next, i, Math.min(pos + 1, result.length));
break;
}
}
pos++;
}
return result;
}
private static void shiftElements(int[] arr, int val, int start, int end) {
int move = arr[start];
arr[start] = val;
for (int i = start + 1; i < end; i++) {
int temp = arr[i];
arr[i] = move;
move = temp;
}
}
Maybe you'll be more comfortable with the first version, but if you are somehow familiar with the Collections framework, then it's a good time to get acquainted with PriorytyQueue. In the nutshell, this collection is backed by an array and maintains its element in the same order as they were added, but when an element is being deleted collection retrieves the smallest one according to the natural order or based on the Comparator, which can be provided while instantiating the PriorytyQueue. It uses a sorting algorithm that is called a heapsort which allows removing a single element in O(log N) time.
The Second solution - PriorytyQueue
public static int[] getSmallestWithPriorityQueue(int[] arr, int limit) {
Queue<Integer> queue = new PriorityQueue<>();
populateQueue(queue, arr);
int[] result = new int[Math.min(limit, arr.length)];
for (int i = 0; i < result.length; i++) {
result[i] = queue.remove();
}
return result;
}
private static void populateQueue(Queue<Integer> queue, int[] arr) {
for (int next: arr) {
queue.add(next);
}
}
main & utility-method to generate an array
public static void main(String[] args) {
int[] source = generateArr(100, 10);
System.out.println("source : " + Arrays.toString(source));
int[] result1 = getSmallest(source, 3);
System.out.println("result(Arrays & Loops) : " + Arrays.toString(result1));
int[] result2 = getSmallestWithPriorityQueue(source, 3);
System.out.println("result(PriorityQueue) : " + Arrays.toString(result2));
}
public static int[] generateArr(int maxVal, int limit) {
Random random = new Random();
return IntStream.generate(() -> random.nextInt(maxVal + 1))
.limit(limit)
.toArray();
}
output
source : [61, 67, 78, 53, 74, 51, 50, 83, 59, 21]
result(Arrays & Loops) : [21, 50, 51]
result(PriorityQueue) : [21, 50, 51]
Randomized select allows to find k-th ranked element in linear time on average.
It alters the input order, so practically, it makes sense to just sort and return k-th element of the sorted array. Especially if there are several such calls on the given input array.
The idea is to have a two dimensional array NxN where all the elements (numbers from 0 to N*N) are in random positions. To generate the random numbers I used:
// Creates a set so we avoid repetition of generated numbers
Set<Integer> generatedNumbers = new LinkedHashSet<Integer>();
while (generatedNumbers.size() < numberOfElements){
Integer next = rng.nextInt(numberOfElements) ;
generatedNumbers.add(next);
}
Now I need to copy the elements to a two dimensional array. Basically, something like this:
for (Integer number: generatedNumbers){
// Here I'd like to have:
// 1st iteration: board[0][0] = number
// 2nd iteration: board[0][1] = number
// ...
// last iteration: board[3][3] = number
}
where:
board = new int[boardSize][boardSize];
with boardSize = 4 for this particular case.
Btw, if there's a better way to achieve the same but using a different method, I'd be happy to read it.
If I understood correctly you want to randomly distribute numbers from a collection into a 2d array. Here is a working code based on what you gave us that will do just that:
public static Integer[][] getRandomNumbersArray(int base)
{
Random rng = new Random();
int numberOfElements = base * base;
// Let's use a list so we access by index
List<Integer> generatedNumbers = new ArrayList<>();
for (int i = 0; i < numberOfElements; i++)
{
// Generate our random number
Integer next = rng.nextInt(numberOfElements) ;
// Check if the number is already added
if (!generatedNumbers.contains(next)) {
generatedNumbers.add(next);
}
// Number was a duplicate, redo loop cycle
else i--;
}
// Create our board array here
Integer[][] array = new Integer[base][base];
// Index used to access the list
int i1 = 0;
for (int i2 = 0; i2 < base; i2++)
{
// Populate board row
for (int i3 = 0; i3 < base; i3++, i1++) {
array[i2][i3] = generatedNumbers.get(i1);
}
}
return array;
}
public static void main(String[] args)
{
Integer[][] array = getRandomNumbersArray(4);
System.out.println("Here is how our board looks like:");
for (int i = 0; i < array.length; i++) {
System.out.println(Arrays.toString(array[i]));
}
}
Output
Here is how our board looks like:
[8, 7, 11, 3]
[15, 5, 1, 0]
[2, 9, 10, 12]
[13, 4, 6, 14]
Instead of iterating the set on the outside of the loop, consider doing it in reverse. Something along the lines of
Iterator iter = generatedNumbers.iterator()
for (...) {
for (...) {
if (iter.hasNext()) arr[i][j] = iter.next()
else ...
}
}
I'm trying to solve the problem below from CodeFights. I left my answer in Java after the question. The code works for all the problems, except the last one. Time limit exception is reported. What could I do to make it run below 3000ms (CodeFights requirement)?
Note: Write a solution with O(n) time complexity and O(1) additional space complexity, since this is what you would be asked to do during a real interview.
Given an array a that contains only numbers in the range from 1 to a.length, find the first duplicate number for which the second occurrence has the minimal index. In other words, if there are more than 1 duplicated numbers, return the number for which the second occurrence has a smaller index than the second occurrence of the other number does. If there are no such elements, return -1.
Example
For a = [2, 3, 3, 1, 5, 2], the output should be
firstDuplicate(a) = 3.
There are 2 duplicates: numbers 2 and 3. The second occurrence of 3 has a smaller index than than second occurrence of 2 does, so the answer is 3.
For a = [2, 4, 3, 5, 1], the output should be
firstDuplicate(a) = -1.
Input/Output
[time limit] 3000ms (java)
[input] array.integer a
Guaranteed constraints:
1 ≤ a.length ≤ 105,
1 ≤ a[i] ≤ a.length.
[output] integer
The element in a that occurs in the array more than once and has the minimal index for its second occurrence. If there are no such elements, return -1.
int storedLeastValue = -1;
int indexDistances = Integer.MAX_VALUE;
int indexPosition = Integer.MAX_VALUE;
for (int i = 0; i < a.length; i++)
{
int tempValue = a[i];
for (int j = i+1; j < a.length; j++) {
if(tempValue == a[j])
{
if(Math.abs(i-j) < indexDistances &&
j < indexPosition)
{
storedLeastValue = tempValue;
indexDistances = Math.abs(i-j);
indexPosition = j;
break;
}
}
}
}
return storedLeastValue;
Your solution has two nested for loops which implies O(n^2) while the question explicitly asks for O(n). Since you also have a space restriction you can't use an additional Set (which can provide a simple solution as well).
This question is good for people that have strong algorithms/graph theory background. The solution is sophisticated and includes finding an entry point for a cycle in a directed graph. If you're not familiar with these terms I'd recommend that you'll leave it and move to other questions.
Check this one, it's also O(n) , but without additional array.
int firstDuplicate(int[] a) {
if (a.length <= 1) return -1;
for (int i = 0; i < a.length; i++) {
int pos = Math.abs(a[i]) - 1;
if (a[pos] < 0) return pos + 1;
else a[pos] = -a[pos];
}
return -1;
}
The accepted answer does not work with the task.
It would work if the input array would indeed contain no bigger value than its length.
But it does, eg.: [5,5].
So, we have to define which number is the biggest.
int firstDuplicate(int[] a) {
int size = 0;
for(int i = 0; i < a.length; i++) {
if(a[i] > size) {
size = a[i];
}
}
int[] t = new int[size+1];
for(int i = 0; i < a.length; i++) {
if(t[a[i]] == 0) {
t[a[i]]++;
} else {
return a[i];
}
}
return -1;
}
What about this:
public static void main(String args[]) {
int [] a = new int[] {2, 3, 3, 1, 5, 2};
// Each element of cntarray will hold the number of occurrences of each potential number in the input (cntarray[n] = occurrences of n)
// Default initialization to zero's
int [] cntarray = new int[a.length + 1]; // need +1 in order to prevent index out of bounds errors, cntarray[0] is just an empty element
int min = -1;
for (int i=0;i < a.length ;i++) {
if (cntarray[a[i]] == 0) {
cntarray[a[i]]++;
} else {
min = a[i];
// no need to go further
break;
}
}
System.out.println(min);
}
You can store array values in hashSet. Check if value is already present in hashSet if not present then add it in hashSet else that will be your answer. Below is code which passes all test cases:-
int firstDuplicate(int[] a) {
HashSet<Integer> hashSet = new HashSet<>();
for(int i=0; i<a.length;i++){
if (! hashSet.contains(a[i])) {
hashSet.add(a[i]);
} else {
return a[i];
}
}
return -1;
}
My simple solution with a HashMap
int solution(int[] a) {
HashMap<Integer, Integer> countMap = new HashMap<Integer, Integer>();
int min = -1;
for (int i=0; i < a.length; i++) {
if (!(countMap.containsKey(a[i]))) {
countMap.put(a[i],1);
}
else {
return a[i];
}
}
return min;
}
Solution is very simple:
Create a hashset
keep iterating over the array
if element is already not in the set, add it.
else element will be in the set, then it mean this is minimal index of first/second the duplicate
int solution(int[] a) {
HashSet<Integer> set = new HashSet<>();
for(int i=0; i<a.length; i++){
if(set.contains(a[i])){
// as soon as minimal index duplicate found where first one was already in the set, return it
return a[i];
}
set.add(a[i]);
}
return -1;
}
A good answer for this exercise can be found here - https://forum.thecoders.org/t/an-interesting-coding-problem-in-codefights/163 - Everything is done in-place, and it has O(1) solution.
Problem H (Longest Natural Successors):
Two consecutive integers are natural successors if the second is the successor of the first in the sequence of natural numbers (1 and 2 are natural successors). Write a program that reads a number N followed by N integers, and then prints the length of the longest sequence of consecutive natural successors.
Example:
Input 7 2 3 5 6 7 9 10 Output 3 this is my code so far and i have no idea why it does not work
import java.util.Scanner;
public class Conse {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int x = scan.nextInt();
int[] array = new int[x];
for (int i = 0; i < array.length; i++) {
array[i] = scan.nextInt();
}
System.out.println(array(array));
}
public static int array(int[] array) {
int count = 0, temp = 0;
for (int i = 0; i < array.length; i++) {
count = 0;
for (int j = i, k = i + 1; j < array.length - 1; j++, k++) {
if (Math.abs(array[j] - array[k]) == 1) {
count++;
} else {
if (temp <= count) {
temp = count;
}
break;
}
}
}
return temp + 1;
}
}
Why two loops? What about
public static int array(final int[] array) {
int lastNo = -100;
int maxConsecutiveNumbers = 0;
int currentConsecutiveNumbers = 0;
for (int i = 0; i < array.length; i++) {
if (array[i] == lastNo + 1) {
currentConsecutiveNumbers++;
maxConsecutiveNumbers = Math.max(maxConsecutiveNumbers,
currentConsecutiveNumbers);
} else {
currentConsecutiveNumbers = 1;
}
lastNo = array[i];
}
return Math.max(maxConsecutiveNumbers, currentConsecutiveNumbers);
}
This seems to work:
public static int longestConsecutive(int[] array) {
int longest = 0;
// For each possible start
for (int i = 0; i < array.length; i++) {
// Count consecutive.
for (int j = i + 1; j < array.length; j++) {
// This one consecutive to last?
if (Math.abs(array[j] - array[j - 1]) == 1) {
// Is it longer?
if (j - i > longest) {
// Yup! Remember it.
longest = j - i;
}
} else {
// Start again.
break;
}
}
}
return longest + 1;
}
public void test() {
int[] a = new int[]{7, 2, 3, 5, 6, 7, 9, 10};
System.out.println("Longest: " + Arrays.toString(a) + "=" + longestConsecutive(a));
}
prints
Longest: [7, 2, 3, 5, 6, 7, 9, 10]=3
Since your question has "Problem H" associated with it, I'm assuming you are just learning. Simpler is always better, so it usually pays to break it down into "what has to be done" before starting on a particular road by writing code that approaches the problem with "how can this be done."
In this case, you may be over-complicating things with arrays. A number is a natural successor if it is one greater than the previous number. If this is true, increment the count of the current sequence. If not, we're starting a new sequence. If the current sequence length is greater than the maximum sequence length we've seen, set the max sequence length to the current sequence length. No arrays needed - you only need to compare two numbers (current and last numbers read).
For example:
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int N = scan.nextInt();
int maxSequenceLen = 0; // longest sequence ever
int curSequenceLen = 0; // when starting new sequence, reset to 1 (count the reset #)
int last = 0;
for(int i = 0; i < N; i++) {
int cur = scan.nextInt();
if ((last+1) == cur){
++curSequenceLen;
}
else{
curSequenceLen = 1;
}
if (curSequenceLen > maxSequenceLen){
maxSequenceLen = curSequenceLen;
}
last = cur;
}
System.out.println(maxSequenceLen);
Caveat: I'm answering this on a computer that does not have my Java development environment on it, so the code is untested.
I'm not sure I understand this question correctly. The answer's written here assumes that the the natural successors occur contiguously. But if this is not the same then the solution here might not give the correct answer.
Suppose instead of [7 2 3 5 6 7 9 10] the input was [7 2 6 3 7 5 6 9 10] then the answer becomes 2 while the natural successor [5 6 7] is present in the array.
If the input is not sorted we'll have to use a different approach. Like using HashSet
Load the entire array into a HashSet which removes duplicates.
Pick the first value from the HashSet and assigned it to start and end and remove it from the set.
Now decrements start and check if it is present in the HashSet and continue till a particular value for start is not present int the HashSetwhile removing the value being searched from the set.
Do the same for end except that you will have to increase the value of end for each iteration.
We now have to continuous range from start to end present in the set and whose range is current_Max = end - start + 1
In each iteration we keep track of this current_Max to arrive at the longest natural successor for the entire array.
And since HashSet supports Add, Remove, Update in O(1) time. This algorithm will run in O(n) time, where n is the length of the input array.
The code for this approach in C# can be found here
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am trying to send array to method and checking the array integer values whether they are prime or not and then storing all prime numbers in new array and sending it back.
import java.util.Arrays;
public class FunPrime {
public static int[] calculate(int[] arr) {
int arr2[] = {};
int count = 0;
for (int i = 0, m = 0; i < arr.length; i++) {
for (int j = 1; j <= arr[i]; j++) {
if (arr[i] % j == 0) {
count++;
}
if (count > 2)
break;
}
if (count <= 2) {
arr2[m] = arr[i];
}
}
return arr2;
}
public static void main(String args[]) {
int no[] = { 1, 4, 5, 6, 7, 8, 11, 22, 43 };
System.out.println(Arrays.toString(calculate(no)));
}
}
In Java if we write
int array = new int [10] ;
Then its a dynamic initialization and not static. Therefore you need to allocate memory statically by
int array = { 1, 4, 5, 6, 7, 8, 11, 22, 43 };
also in future if you want to initialize an array to zero then you can use
int arr[] = new int[10];
for(int i=0;i<arr.length;i++)
arr[i] = 0;
There are, at least, three things wrong...
First...
int arr2[] = {};
Is creating an empty array with no positions available to store any content, this means the moment you try and access any element within it, you will get an ArrayIndexOutOfBoundsException
You should initialise the array to the desired length, for example...
int arr2[] = new int[arr.length];
Two...
The value of count is never re-initialised after it is used, this means that it keeps getting incremented on each loop, meaning it will only ever be capable of reporting the first successful match, instead, you should initialise the count back to 0 on each loop, for example...
for (int i = 0, m = 0; i < arr.length; i++) {
count = 0;
for (int j = 1; j <= arr[i]; j++) {
Third...
m is never incremented, meaning that you are always storing the sucessful match to the first element position in the arr2, don't forget to increment the value, for example...
arr2[m] = arr[i];
m++;
Bonus
The problem with this is, this will return 0 for the elements that don't match, for example...
[1, 5, 7, 11, 43, 0, 0, 0, 0]
This might not be desired
You can "trim" the result using System.arraycopy, but you will need to make one minor change first. The m value indicates the number of matches, this is useful, but because it's declared in the for-loop, we can't access it outside the for-loop, so instead, you need to declare it outside of the for-loop, for example...
int m = 0;
for (int i = 0; i < arr.length; i++) {
This then allows us to declare a third array which will hold the final results we want, for example...
int[] arr3 = new int[m];
System.arraycopy(arr2, 0, arr3, 0, m);
return arr3;
Which will now output...
[1, 5, 7, 11, 43]
Instead of...
[1, 5, 7, 11, 43, 0, 0, 0, 0]
You really want to use new to allocate that memory before you start using references. I also think you can do away with the x = x and x = 1; then you can stop your loop with a break. That should be quicker. Something like
for (int y = 2; y < x; y++) if (x % y == 0) { result = true; break; }
How to find number of prime numbers between two integers
You initialize your second array with zero elements
int arr2[] = {};
Arrays do not grow, so arr2[0] = someValue will give you an ArrayIndexOutOfBounds since there is no first element.
When you create a new array, you should specify it's size.
int arr2[] = {};
This creates an array of size 0. You probably get an ArrayIndexOutOfBoundsException
This is your solution..this will print
[1, 5, 7, 11, 43]
import java.util.ArrayList;
public class FunPrime {
public static ArrayList<Integer> calculate(int[] arr) {
ArrayList<Integer> l = new ArrayList<Integer>();
for (int i = 0; i < arr.length; i++) {
if(isPrime(arr[i]))
{
l.add(arr[i]);
}
}
return l;
}
static boolean isPrime(int n) {
for(int i=2;i<n;i++) {
if(n%i==0)
return false;
}
return true;
}
public static void main(String args[]) {
int no[] = { 1, 4, 5, 6, 7, 8, 11, 22, 43 };
System.out.println(calculate(no));
}
}