Program to find pairs in array that XOR to a given value - java

I am given an array and a value x.
Input example:
2 3
1 2
Where n (length of array) = 2, the value x = 3, and the next line (1, 2) contains the values in the array. I have to find the pairs of indices i, j so that a[i] XOR a[j] = x.
What I have implemented:
import java.util.HashSet;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int x = sc.nextInt();
int[] arr = new int[n];
HashSet<Integer> hash = new HashSet<Integer>();
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
hash.add(arr[i]);
}
int count = 0;
for (int i = 0; i < n; i++) {
if (hash.contains(arr[i]^x)) {
count++;
}
}
System.out.println(count/2);
}
}
I have the divided the result by two because we only want to count a given pair once (only count [1, 2] not [1, 2] and [2, 1]).
I pass the given test above where the output is 1, and this supplementary one where the output is 2.
6 1
5 1 2 3 4 1
However I seem to fail some extra ones which I cannot see.

The problem is that you check "contains", but for duplicate values this only returns a single occurrence. By using a set you throw duplicates away. Instead you should have a HashMap with number of occurrences:
Map<Integer, Integer> hash = new HashMap<>();
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
if (!hash.containsKey(arr[i])) {
hash.put(arr[i], 0)
}
hash.put(arr[i], hash.get(arr[i]) + 1);
}
int count = 0;
for (int i = 0; i < n; i++) {
if (hash.containsKey(arr[i]^x)) {
count += hash.get(arr[i]^x);
}
}

Your logic of dividing the count by 2 as the final answer, is not correct.
Replace your logic by the following:
HashSet<Integer> hash = new HashSet<Integer>();
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
}
int count = 0;
for (int i = 0; i < n; i++) {
if (hash.contains(arr[i]^x)) {
count++;
}
hash.add(arr[i]);
}
System.out.println(count);

Your program doesn't handle duplicate numbers properly. It deals with 5 1 2 3 4 1 okay because 1 isn't part of the solution. What if it is?
Let's say number a[i] ^ a[j] is a solution as is a[i] ^ a[k]. In other words, a[j] == a[k]. The line hash.contains(arr[i]^x) will only count a[i] once.
You can solve this by having nested for loops.
for (int i = ...) {
for (int j = ...) {
if (a[i] ^ a[j] == x) {
count++;
}
}
}
This approach lets you get rid of the hash set. And if you're clever enough filling out the ... parts you can avoid double counting the pairs and won't have to divide count by 2.

Related

java array rotating by n element gives wrong output in test

I have a problem with an exercise trying to solve it. Here is the task:
Write a program that moves that rotates a list several times (the first element becomes last).
list = 1,2,3,4,5 and N = 2 -> result = 3,4,5,1,2
Note that N could be larger than the length of the list, in which case you will rotate the list several times.
list = 1,2,3,4,5 and N = 6 -> result = 2,3,4,5,1
Input
On the first line you will receive the list of numbers.
On the second line you will receive N
Output
On the only line of output, print the numbers separated by a space.
Here are the TEST:
TEST 1:
Input 5,3,2,1 2
Output 2,1,5,3
TEST 2:
Input 2,1,3,4 5
Output 1,3,4,2
Here is my code so far:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
String[] elements = input.split(",");
int[] array = new int[elements.length];
for (int i = 0; i < elements.length; i++) {
array[i] = Integer.parseInt(elements[i]);
}
int a = scanner.nextInt();
int[] rotated = new int[elements.length];
for (int x = 0; x <= array.length - 1; x++) {
rotated[(x + a) % array.length] = array[x];
}
for (int i = 0; i < rotated.length; i++) {
if (i > 0) {
System.out.print(",");
}
System.out.print(rotated[i]);
}
}
}
The first TEST is passed. But the second test is not passed and my program gives me wrong output: 4,2,1,3 instead of the right one: 1,3,4,2.
I cant figure it out where is the problem.
Thank you in advance for any help.
Your logic can be simplified to :
public static void shiftLeft(int shiftBy, int arr[]) {
for (int j = 0; j < shiftBy; j++) {
int a = arr[0]; // storing the first index
int i;
for (i = 0; i < arr.length - 1; i++) { // shifting the array left
arr[i] = arr[i + 1];
}
arr[i] = a; // placing first index at the end
}
}
Now call it :
public static void main(String[] args) {
// Fetch all data from user as you have done
int arr[] = { 1, 2, 3, 4, 5 };
shiftLeft(n % arr.length, arr);
// print out the array
}
Notice that if the number n is greater than the length of the array, you don't have to actually shift it that many times. Instead you just need to shift it n % arr.length times.

Getting the most "popular" number from array

I need for homework to get the most "popular" number in an array (the number in the highest frequency), and if there are several numbers with the same number of shows, get some number randomly.
After more then three hours of trying, and either searching the web, this is what I got:
public int getPopularNumber(){
int count = 1, tempCount;
int popular = array[0];
int temp = 0;
for ( int i = 0; i < (array.length - 1); i++ ){
if ( _buses[i] != null )
temp = array[i];
tempCount = 0;
for ( int j = 1; j < _buses.length; j++ ){
if ( array[j] != null && temp == array[j] )
tempCount++;
}
if ( tempCount > count ){
popular = temp;
count = tempCount;
}
}
return popular;
}
This code work, but don't take into account an important case- if there is more than one number with the same count of shows. Then it just get the first one.
for example: int[]a = {1, 2, 3, 4, 4, ,5 ,4 ,5 ,5}; The code will grab 4 since it shown first, and it's not random as it should be.
Another thing- since it's homework I can't use ArrayList/maps and stuff that we still didn't learn.
Any help would be appreciated.
Since they didn't give you any time complexity boundary, you can "brute force" the problem by scanning the the array N^2 times. (disclaimer, this is the most intuitive way of doing it, not the fastest or the most efficient in terms of memory and cpu).
Here is some psuedo-code:
Create another array with the same size as the original array, this will be the "occurrence array"
Zero its elements
For each index i in the original array, iterate the original array, and increment the element in the occurrence array at i each time the scan finds duplicates of the value stored in i in the original array.
Find the maximum in the occurrence array
Return the value stored in that index in the original array
This way you mimic the use of maps with just another array.
If you are not allowed to use collection then you can try below code :
public int getPopularNumber(){
int inputArr[] = {1, 2, 3, 4, 4, 5 ,4 ,5 ,5}; // given input array
int[] tempArr = new int[inputArr.length];
int[] maxValArr = new int[inputArr.length];
// tempArr will have number as index and count as no of occurrence
for( int i = 0 ; i < inputArr.length ; i++){
tempArr[inputArr[i]]++;
}
int maValue = 0;
// find out max count of occurrence (in this case 3 for value 4 and 5)
for( int j = 0 ; j < tempArr.length ; j++){
maValue = Math.max(maValue, tempArr[j]);
}
int l =0;
// maxValArr contains all value having maximum occurrence (in this case 4 and 5)
for( int k = 0 ; k < tempArr.length ; k++){
if(tempArr[k] == maValue){
maxValArr[l] = k;
l++;
}
}
return maxValArr[(int)(Math.random() * getArraySize(maxValArr))];
}
private int getArraySize(int[] arr) {
int size = 0;
for( int i =0; i < arr.length ; i++){
if(arr[i] == 0){
break;
}
size++;
}
return size;
}
that's hard as hell :D
After some trying, I guess I have it (If there will be 2 numbers with same frequency, it will return first found):
int mostPopNumber =0;
int tmpLastCount =0;
for (int i = 0; i < array.length-1; i++) {
int tmpActual = array[i];
int tmpCount=0;
for (int j = 0; j < array.length; j++) {
if(tmpActual == array[j]){
tmpCount++;
}
}
// >= for the last one
if(tmpCount > tmpLastCount){
tmpLastCount = tmpCount;
mostPopNumber = tmpActual;
}
}
return mostPopNumber;
--
Hah your code give me idea- you cant just remember last most popular number, btw I've found it solved there Find the most popular element in int[] array
:)
EDIT- after many, and many years :D, that works well :)
I've used 2D int and Integer array - you can also use just int array, but you will have to make more length array and copy actual values, Integer has default value null, so that's faster
Enjoy
public static void main(String[] args) {
//income array
int[] array= {1,1,1,1,50,10,20,20,2,2,2,2,20,20};
//associated unique numbers with frequency
int[][] uniQFreqArr = getUniqValues(array);
//print uniq numbers with it's frequency
for (int i = 0; i < uniQFreqArr.length; i++) {
System.out.println("Number: " + uniQFreqArr[i][0] + " found : " + uniQFreqArr[i][1]);
}
//get just most frequency founded numbers
int[][] maxFreqArray = getMaxFreqArray(uniQFreqArr);
//print just most frequency founded numbers
System.out.println("Most freq. values");
for (int i = 0; i < maxFreqArray.length; i++) {
System.out.println("Number: " + maxFreqArray[i][0] + " found : " + maxFreqArray[i][1]);
}
//get some of found values and print
int[] result = getRandomResult(maxFreqArray);
System.out.println("Found most frequency number: " + result[0] + " with count: " + result[1]);
}
//get associated array with unique numbers and it's frequency
static int[][] getUniqValues(int[] inArray){
//first time sort array
Arrays.sort(inArray);
//default value is null, not zero as in int (used bellow)
Integer[][] uniqArr = new Integer[inArray.length][2];
//counter and temp variable
int currUniqNumbers=1;
int actualNum = inArray[currUniqNumbers-1];
uniqArr[currUniqNumbers-1][0]=currUniqNumbers;
uniqArr[currUniqNumbers-1][1]=1;
for (int i = 1; i < inArray.length; i++) {
if(actualNum != inArray[i]){
uniqArr[currUniqNumbers][0]=inArray[i];
uniqArr[currUniqNumbers][1]=1;
actualNum = inArray[i];
currUniqNumbers++;
}else{
uniqArr[currUniqNumbers-1][1]++;
}
}
//get correctly lengthed array
int[][] ret = new int[currUniqNumbers][2];
for (int i = 0; i < uniqArr.length; i++) {
if(uniqArr[i][0] != null){
ret[i][0] = uniqArr[i][0];
ret[i][1] = uniqArr[i][1];
}else{
break;
}
}
return ret;
}
//found and return most frequency numbers
static int[][] getMaxFreqArray(int[][] inArray){
int maxFreq =0;
int foundedMaxValues = 0;
//filter- used sorted array, so you can decision about actual and next value from array
for (int i = 0; i < inArray.length; i++) {
if(inArray[i][1] > maxFreq){
maxFreq = inArray[i][1];
foundedMaxValues=1;
}else if(inArray[i][1] == maxFreq){
foundedMaxValues++;
}
}
//and again copy to correctly lengthed array
int[][] mostFreqArr = new int[foundedMaxValues][2];
int inArr= 0;
for (int i = 0; i < inArray.length; i++) {
if(inArray[i][1] == maxFreq){
mostFreqArr[inArr][0] = inArray[i][0];
mostFreqArr[inArr][1] = inArray[i][1];
inArr++;
}
}
return mostFreqArr;
}
//generate number from interval and get result value and it's frequency
static int[] getRandomResult(int[][] inArray){
int[]ret=new int[2];
int random = new Random().nextInt(inArray.length);
ret[0] = inArray[random][0];
ret[1] = inArray[random][1];
return ret;
}

Merging two arrays in Java

Write a method
public static ArrayList merge(ArrayList a, ArrayList b)
that merges two array lists, alternating elements from both array lists. If one array list is shorter than the other, then alternate as long as you can and then append the remaining elements from the longer array list. For example, if a is
1 4 9 16
and b is
9 7 4 9 11
then merge returns the array list
1 9 4 7 9 4 16 9 11
What I tried doing was writing a for loop with if statements such that a number is added to the merge array list from array list a when i is an even number (i%2==0) and from array list b when i is an odd number. I am however not sure how to deal with the fact that one array list can be longer than the other. Could anyone please help me out?here is my code so far
package test;
import java.util.Scanner;
public class Arraybig {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int m = scan.nextInt();
int n = scan.nextInt();
int[] A = new int[m];
for (int k = 0; k < m; k++) {
A[k] = scan.nextInt();
}
int[] B = new int[n];
for (int k = 0; k < n; k++) {
B[k] = scan.nextInt();
}
int[] C = new int[m + n];
int max = Math.max(m, n);
int a = 0, b = 0;
for (int i = 0; i < m+n; i++) {
if (i % 2 == 0 && a < A.length) {
C[i] = A[a];
a++;
} else if (i % 2 != 0 && b < B.length) {
C[i] = B[b];
b++;
} else if (a < A.length) {
C[i] = A[a];
a++;
} else {
C[i] = B[b];
b++;
}
}
for (int j = 0; j < C.length; j++) {
System.out.println(C[j] + " ");
}
}
}
A more cleaner approach can be something like this..
list<Integer> a1=//1st list
list<Integer> a2=//2nd list
list<Integer> a3=new Arraylist<Integer>();
int length=(a1.size()<=a2.size())?a1.size():a2.size();
for(int i=0;i<length;i++){
a3.add(a1.get(i));
a3.add(a2.get(i));
}
for(int i=length;i<a1.size();i++){
a3.add(a1.get(i));
}
for(int i=length;i<a2.size();i++){
a3.add(a2.get(i));
}
Hint: How long is the array you want to fill? And how many iterations does your main for loop run? Why is it not the same number?

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

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

ArrayList - searching for the most common integer

I have 999 numbers in my arrayList, some of the numbers are repeated. And i want to find the most frequent number in the list, what is the most efficient way of doing that?
Sort the list and than count which occurs the most by reading the sorted List.
Needs 0(n log n) Time
1 3 6 1 82 42 11 42 1 42 3 42
sorted
1 1 1 3 3 6 11 42 42 42 42 82
Read the list from left to right and remember which value was seen the most so far and how often
I assume, as you wrote in comment, that you read numbers from 0 to 100
from a text file, so you can use
int[] count = new int[101];
...
count[numberJustRead]++;
...
and after read all numbers
int max = 0;
int maxIndex = 0; //this is what you looking for
for(int i = 0, k = count.length; i < k; i++){
if(count[i] > max){
max = count[i];
maxIndex = i;
}
}
or you maybe like guava's Mulitset
Here are two simple implementations with different complexity (of course if you have only a few numbers performance gain is symbolic) :
import java.util.*;
public class Test
{
static AbstractMap.SimpleEntry<Integer, Integer> getMostFrequentN2(ArrayList<Integer> values)
{
ArrayList<AbstractMap.SimpleEntry<Integer, Integer>> frequencies = new ArrayList<>();
int maxIndex = 0;
main:
for (int i = 0; i < values.size(); ++i)
{
int value = values.get(i);
for (int j = 0; j < frequencies.size(); ++j)
{
if (frequencies.get(j).getKey() == value)
{
frequencies.get(j).setValue(frequencies.get(j).getValue() + 1);
if (frequencies.get(maxIndex).getValue() < frequencies.get(j).getValue())
{
maxIndex = j;
}
continue main;
}
}
frequencies.add(new AbstractMap.SimpleEntry<Integer, Integer>(value, 1));
}
return frequencies.get(maxIndex);
}
static AbstractMap.SimpleEntry<Integer, Integer> getMostFrequentNLogN(ArrayList<Integer> values)
{
ArrayList<Integer> tmp = new ArrayList(values);
Collections.sort(tmp);
AbstractMap.SimpleEntry<Integer, Integer> max = new AbstractMap.SimpleEntry<>(0, 0);
int current = tmp.get(0);
int count = 0;
for (int i = 0; i < tmp.size(); ++i)
{
if (tmp.get(i) == current)
{
count++;
}
else
{
if (count > max.getValue())
{
max = new AbstractMap.SimpleEntry<Integer, Integer>(current, count);
}
current = tmp.get(i);
count = 1;
}
}
if (count > max.getValue())
{
max = new AbstractMap.SimpleEntry<Integer, Integer>(current, count);
}
return max;
}
public static void main(String[] args)
{
ArrayList<Integer> numbers = new ArrayList(99);
for (int i = 0; i < 99; ++i)
{
numbers.add((int)(Math.random() * 10));
}
System.out.println(numbers);
System.out.println(getMostFrequentN2(numbers));
System.out.println(getMostFrequentNLogN(numbers));
}
}
Yes, slowly.
You could do this with a List of Lists; an inner list contains the numbers you have seen, and the index of the outer list is the number of occurrences. So after processing "1,2,1,3,1,2,3,4" you would have
[ [4], [2, 3], [1] ]
Once you are done processing the input list, you can get the last inner list contained by the highest index of the outer list, which in this case is [1]. All elements in that list are tied for the maximum number of occurrences.

Categories