Java hashset vs Arrays.sort - java

I am trying to solve the below 'codility' exercise:
A zero-indexed array A consisting of N different integers is given. The array contains integers in the range [1..(N + 1)], which means that exactly one element is missing.
Your goal is to find that missing element.
Write a function:
class Solution { public int solution(int[] A); }
that, given a zero-indexed array A, returns the value of the missing element.
For example, given array A such that:
A[0] = 2
A[1] = 3
A[2] = 1
A[3] = 5
the function should return 4, as it is the missing element.
Assume that:
N is an integer within the range [0..100,000];
the elements of A are all distinct;
each element of array A is an integer within the range [1..(N + 1)].
Complexity:
expected worst-case time complexity is O(N);
expected worst-case space complexity is O(1), beyond input storage (not counting the storage required for input arguments).
Elements of input arrays can be modified.
I came up with two solutions:
1) Gives 100%/100%
class Solution {
public int solution(int[] A) {
int previous = 0;
if (A.length != 0) {
Arrays.sort(A);
for (int i : A) {
if (++previous != i) {
return previous;
}
}
}
return ++previous;
}
}
2) Gives an error WRONG ANSWER, got 65536 expected 100001
class SolutionHS {
public int solution(int[] A) {
int previous = 0;
HashSet<Integer> hs = new HashSet<>();
if (A.length != 0) {
for (int a : A) {
hs.add(a);
}
for (Integer i : hs) {
if (++previous != i) {
return previous;
}
}
}
return ++previous;
}
}
My question is:
Shouldn't both approaches (using hashset and Arrays.sort) work the same way?
If not can you tell me what the difference is?

HashSet is not sorted, so when you iterate over the elements of the Set, you don't get them in an ascending order, as your code expects. If you used a TreeSet instead of HashSet, your code would work.
The HashSet solution will give the correct answer if you change the second loop to :
for (int i = 0; i <= A.length; i++) {
if (!hs.contains(i)) {
return i;
}
}
This loop explicitly checks whether each integer in the relevant range appears in the HashSet and returns the first (and only one) which doesn't.
Anyway, both your implementations don't meet the O(n) running time and O(1) space requirements.
In order you meet the required running time and space, you should calculate the sum of the elements of the array and subtract that sum from (A.length+1)*A.length/2.

Related

Finding the sum of common elements between n number of arrays in java

I have a program that sums the common elements of two arrays. For that I used two for loops and if I have three then I could use three for loops. But how to sum the common elements of n number of arrays where n is coming during run time.
I don't know how to change the number of loops during run time or is there any other relevant concept for this ?
Here is the code I've tried for summing twoarrays:
import java.util.Scanner;
public class Sample {
public static void main(String... args)
{
Scanner sc=new Scanner(System.in);
int arr1[]={1,2,3,4,5},arr2[]={4,5,6,7,8},sum=0;
for (int i=0;i<arr1.length;i++)
{
for (int j=0;j<arr2.length;j++)
{
if (arr1[i]==arr2[j])
{
sum+=(arr1[i]);
}
}
}
}
}
There can be different implementation for that. You can use the following approach. Here is the pseudo code
use a 2D array to store the array. if the number of array is n and size is m then the array will be input[n][m]
Use a ArrayList commonItems to store the common items of. Initiate it with the elements of input[0]
Now iterate through the array for i = 1 to n-1. compare with every input[i], store only the common items of commonItems and input[i] at each step. You can do it by converting the input[i] into a list and by using retainAll method.
At the end of the iteration the commonItem list will contains the common numbers only. Now sum the value of this list.
There is actually a more general method, that also answers the question "how to change the number of loops during run time?".
The general question
We are looking for a way to implement something equivalent to this:
for (i1 = 0; i1 < k1; i1++) {
for (i2 = 0; i2 < k2; i2++) {
for (i3 = 0; i3 < k3; i3++) {
...
for (in = 0; in < kn; in++) {
f(x1[i1], x2[i2], ... xn[in]);
}
...
}
}
}
where, n is given at runtime and f is a function taking a list of n parameters, processing the current n-tuple.
A general solution
There is a general solution, based on the concept of recursion.
This is one implementation that produces the desired behavior:
void process(int idx, int n, int[][] x, int[] k, Object[] ntuple) {
if (idx == n) {
// we have a complete n-tuple,
// with an element from each of the n arrays
f(ntuple);
return;
}
// this is the idx'th "for" statement
for (int i = 0; i < k[idx]; i++) {
ntuple[idx] = x[idx][i];
// with this recursive call we make sure that
// we also generate the rest of the for's
process(idx + 1, n, x, k, ntuple);
}
}
The function assumes that the n arrays are stored in a matrix x, and the first call should look like this:
process(0, n, x, k, new Object[n]);
Practical considerations
The solution above has a high complexity (it is O(k1⋅k2⋅..⋅kn)), but sometimes it is possible to avoid going until the deepest loop.
Indeed, in the specific problem mentioned in this post (which requires summing common elements across all arrays), we can skip generating some tuples e.g. if already x2[i2] ≠ x1[i1].
In the recursive solution, those situations can easily be pruned. The specific code for this problem would probably look like this:
void process(int idx, int n, int[][] x, int[] k, int value) {
if (idx == n) {
// all elements from the current tuple are equal to "value".
// add this to the global "sum" variable
sum += value;
return;
}
for (int i = 0; i < k[idx]; i++) {
if (idx == 0) {
// this is the outer "for", set the new value
value = x[0][i];
} else {
// check if the current element from the idx'th for
// has the same value as all previous elements
if (x[idx][i] == value) {
process(idx + 1, n, x, k, value);
}
}
}
}
Assuming that the index of the element is not important: a[1] = 2 and a[5] = 2, you only need two nested loops.
First you need to put n-1 arrays in a list of sets. Then loop over nth array and check if each element exists in all of the sets in the list. If it does exist then add to total.

Java - possible permutations of an array of numbers which would result in an identical binary search tree

Given an array of ints which would generate a certain BST, how many variations of that array would result in an identical BST? I have found a few solutions in C++ and python, but nothing in Java. I think I understand the concept of how to develop the correct code.
I'm doing this for a certain Google foobar challenge. When I throw any possible arrays that I could think of I get the correct answer, but when I try to verify my code with Google I get an ArithmeticException. I cannot find where this would possibly occur in my code.
I need to return the answer in a String and the parameter can be an array with a maximum of 50 integers.
This is the code I currently have:
public static String answer(int[] seq) {
if (seq.length <= 1) {
return Integer.toString(1);
}
ArrayList<Integer> rightList = new ArrayList<>();
ArrayList<Integer> leftList = new ArrayList<>();
int root = seq[0];
for (int i : seq) {
if (i > root) {
leftList.add(i);
} else if (i < root) {
rightList.add(i);
}
}
int[] rightArray = new int[rightList.size()];
int[] leftArray = new int[leftList.size()];
int i = 0;
for (int j : rightList) {
rightArray[i++] = j;
}
int k = 0;
for (int l : leftList) {
leftArray[k++] = l;
}
int recurseLeft = Integer.parseInt(answer(leftArray));
int recurseRight = Integer.parseInt(answer(rightArray));
return Integer.toString(recurseLeft * recurseRight
* interleave(leftList.size(), rightList.size()));
}
private static int interleave(int a, int b) {
return (factorial(a + b)) / ((factorial(a) * factorial(b)));
}
private static int factorial(int n) {
return (n <= 1 ? 1 : n * factorial(n - 1));
}
Can someone help find either a bug or a possible array of integers that would cause an ArithmeticException?
Can someone help find either a bug or a possible array of integers
that would cause an ArithmeticException?
The ArithmeticException is likely thrown because you divide a number by 0. Adding the stacktrace would have helped to identify where it occurs, but you're performing a division in the interleave method.
factorial(a) * factorial(b) is an integer multiplication. If the result is too large to fit for the max value an integer can have, it will overflow.
For instance 34! mod 241 = 0. So it suffices that you have a degenerated BST where all the elements are superior than the root (which is the first element of your array here) with 35 elements to get an exception.
Hence the following array:
int[] arr = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,3‌​0,31,32,33,34,35};
will throw it.
ArithmeticException is thrown when you try to divide by zero. The only place in your code to use division is interleave function

Java method to return mode from array of integers

How to write a method which takes an array of integers and returns the mode.If there is more than one mode, it should return the first one
So far I have this, it works in most cases, but I don't see why exactly it returns the first occurrence of the mode.
public static int mode(int[] a) {
int temp,temps;
for(int i=0;i<a.length-1;i++) {
temp=countRepititions(a,a[i]);
temps=countRepititions(a,a[i+1]);
if(temp>temps) {
return a[i];
} else if(temps>temp) {
return a[i+1];
}
}
return a[0];
}
Issue:
You are comparing the count of first and second element and returning the mode without checking the complete array (if the first two elements are different).
if(temp>temps) { // For 766888 temp = 1 temps = 2 and 6 is returned.
return a[i];
} else if(temps>temp) {
return a[i+1];
}
Solution:
For the current algorithm: Traverse the complete array and store maxRepCount (max Repition Count for any integer) and maxRepIdx(Index of max repeated number) at each traversal. In the end, return a[maxRepIdx];
Complexity: O(n^2)
A simpler algorithm: sort the array (O(nlogn)) and then traverse the array with maxRepCount and maxRepIdx (O(n)). In the end, return a[maxRepIdx];

check number in array

Fast way to check integer in the array. Array has not continuous integer in it, instead it has spatial numbers e.g. [1,4,11, 120,2,3].
In time efficient way, how do one check 3 in [212,31219,1,12,4]? Result is false
The answer depends on how often you need to check for a given integer.
If you have to check the same array over and over again it would be faster to sort it once and use a binary search algorithm to find your number (or not, if your number is not in the array).
In Java you don't have to reinvent the wheel. You can use the static methods in Arrays for these tasks (N size of your array):
Arrays.sort(...) will sort your array in ascending order. This sorts the array in O(N*log(N)) steps.
Arrays.binarySearch(...) afterwards will find your number in the sorted array. Finds your Element in O(log(N)) steps.
If you check for a given value only once in a while you may simply iterate over the array. Finds your Element in O(N) steps.
There are two approaches
Consider array of size N , and T searches
Linear search method
Complexity : O (T * N)
Sample code :
class Main {
public static void main(String[] args) {
int[] arr = { 212, 31219, 1, 12, 4 };
// perform searches from here
// for eg.
// boolean exists = contains(arr, 4);
}
public static boolean contains(int[] arr, int x) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == x) {
return true;
}
}
return false;
}
}
Binary search method
Complexity : O (N * log(N) + T * log(N)
Sample code :
import java.util.Arrays;
class Main {
public static void main(String[] args) {
int[] arr = { 212, 31219, 1, 12, 4 };
// sort array first => complexity O(N * log(N))
Arrays.sort(arr);
// perform searches from here
// for eg.
// boolean exists = contains(arr, 2);
}
public static boolean contains(int[] arr, int key) {
return Arrays.binarySearch(arr, key) >= 0 ? true : false;
}
}
So if your number of searches is very high use binary search method else use linear search method.

Finding closest number in an array

In an array first we have to find whether a desired number exists in that or not?
If not then how will I find nearer number to the given desired number in Java?
An idea:
int nearest = -1;
int bestDistanceFoundYet = Integer.MAX_INTEGER;
// We iterate on the array...
for (int i = 0; i < array.length; i++) {
// if we found the desired number, we return it.
if (array[i] == desiredNumber) {
return array[i];
} else {
// else, we consider the difference between the desired number and the current number in the array.
int d = Math.abs(desiredNumber - array[i]);
if (d < bestDistanceFoundYet) {
// For the moment, this value is the nearest to the desired number...
bestDistanceFoundYet = d; // Assign new best distance...
nearest = array[i];
}
}
}
return nearest;
Another common definition of "closer" is based on the square of the difference. The outline is similar to that provided by romaintaz, except that you'd compute
long d = ((long)desiredNumber - array[i]);
and then compare (d * d) to the nearest distance.
Note that I've typed d as long rather than int to avoid overflow, which can happen even with the absolute-value-based calculation. (For example, think about what happens when desiredValue is at least half of the maximum 32-bit signed value, and the array contains a value with corresponding magnitude but negative sign.)
Finally, I'd write the method to return the index of the value located, rather than the value itself. In either of these two cases:
when the array has a length of zero, and
if you add a "tolerance" parameter that bounds the maximum difference you will consider as a match,
you can use -1 as an out-of-band value similar to the spec on indexOf.
//This will work
public int nearest(int of, List<Integer> in)
{
int min = Integer.MAX_VALUE;
int closest = of;
for (int v : in)
{
final int diff = Math.abs(v - of);
if (diff < min)
{
min = diff;
closest = v;
}
}
return closest;
}
If the array is sorted, then do a modified binary search. Basically if you do not find the number, then at the end of search return the lower bound.
Pseudocode to return list of closest integers.
myList = new ArrayList();
if(array.length==0) return myList;
myList.add(array[0]);
int closestDifference = abs(array[0]-numberToFind);
for (int i = 1; i < array.length; i++) {
int currentDifference= abs(array[i]-numberToFind);
if (currentDifference < closestDifference) {
myList.clear();
myList.add(array[i]);
closestDifference = currentDifference;
} else {
if(currentDifference==closestDifference) {
if( myList.get(0) !=array[i]) && (myList.size() < 2) {
myList.add(array[i]);
}
}
}
}
return myList;
Array.indexOf() to find out wheter element exists or not. If it does not, iterate over an array and maintain a variable which holds absolute value of difference between the desired and i-th element. Return element with least absolute difference.
Overall complexity is O(2n), which can be further reduced to a single iteration over an array (that'd be O(n)). Won't make much difference though.
Only thing missing is the semantics of closer.
What do you do if you're looking for six and your array has both four and eight?
Which one is closest?
int d = Math.abs(desiredNumber - array[i]);
if (d < bestDistanceFoundYet) {
// For the moment, this value is the nearest to the desired number...
nearest = array[i];
}
In this way you find the last number closer to desired number because bestDistanceFoundYet is constant and d memorize the last value passign the if (d<...).
If you want found the closer number WITH ANY DISTANCE by the desired number (d is'nt matter), you can memorize the last possibile value.
At the if you can test
if(d<last_d_memorized){ //the actual distance is shorter than the previous
// For the moment, this value is the nearest to the desired number...
nearest = array[i];
d_last_memorized=d;//is the actual shortest found delta
}
A few things to point out:
1 - You can convert the array to a list using
Arrays.asList(yourIntegerArray);
2 - Using a list, you can just use indexOf().
3 - Consider a scenario where you have a list of some length, you want the number closest to 3, you've already found that 2 is in the array, and you know that 3 is not. Without checking the other numbers, you can safely conclude that 2 is the best, because it's impossible to be closer. I'm not sure how indexOf() works, however, so this may not actually speed you up.
4 - Expanding on 3, let's say that indexOf() takes no more time than getting the value at an index. Then if you want the number closest to 3 in an array and you already have found 1, and have many more numbers to check, then it'll be faster to just check whether 2 or 4 is in the array.
5 - Expanding on 3 and 4, I think it might be possible to apply this to floats and doubles, although it would require that you use a step size smaller than 1... calculating how small seems beyond the scope of the question, though.
// paulmurray's answer to your question is really the best :
// The least square solution is way more elegant,
// here is a test code where numbertoLookFor
// is zero, if you want to try ...
import java.util.* ;
public class main {
public static void main(String[] args)
{
int[] somenumbers = {-2,3,6,1,5,5,-1} ;
ArrayList<Integer> l = new ArrayList<Integer>(10) ;
for(int i=0 ; i<somenumbers.length ; i++)
{
l.add(somenumbers[i]) ;
}
Collections.sort(l,
new java.util.Comparator<Integer>()
{
public int compare(Integer n1, Integer n2)
{
return n1*n1 - n2*n2 ;
}
}
) ;
Integer first = l.get(0) ;
System.out.println("nearest number is " + first) ;
}
}
int[] somenumbers = getAnArrayOfSomenumbers();
int numbertoLookFor = getTheNumberToLookFor();
boolean arrayContainsNumber =
new HashSet(Arrays.asList(somenumbers))
.contains(numbertoLookfor);
It's fast, too.
Oh - you wanted to find the nearest number? In that case:
int[] somenumbers = getAnArrayOfSomenumbers();
int numbertoLookFor = getTheNumberToLookFor();
ArrayList<Integer> l = new ArrayList<Integer>(
Arrays.asList(somenumbers)
);
Collections.sort(l);
while(l.size()>1) {
if(numbertoolookfor <= l.get((l.size()/2)-1)) {
l = l.subList(0, l.size()/2);
}
else {
l = l.subList(l.size()/2, l.size);
}
}
System.out.println("nearest number is" + l.get(0));
Oh - hang on: you were after a least squares solution?
Collections.sort(l, new Comparator<Integer>(){
public int compare(Integer o1, Integer o2) {
return (o1-numbertoLookFor)*(o1-numbertoLookFor) -
(o2-numbertoLookFor)*(o2-numbertoLookFor);
}});
System.out.println("nearest number is" + l.get(0));

Categories