Finding the power set of a generic set - java

I had been given a question to utilize java generics and create a Set class. I have been able to perform other functions such as union, intersection, complement etc using this Set class.
But the problem i have been facing is with finding all the power sets. I am required to return a set (i.e the power set). I have been trying to solve this since yesterday but to no avail. I have tried implementing binary method to find the power sets. Everything that i have done so far is based on the requirements of the question!
public class Set<T extends Comparable> {
private ArrayList<T> theSet;
public Set(T[] theElements){
theSet = new ArrayList<>();
for(int i=0; i < theElements.length; i++){
if(!checker(theElements[i]))
theSet.add(theElements[i]);
}
}
public ArrayList<T> getTheSet() {
return theSet;
}
public Set powerSet(){
long powerSetSize = (long)Math.pow(2, theSet.size());
int counter, j;
Set[] powerSet = new Set[(int)Math.pow(2, theSet.size())];
T[] currentArray = null;
for(counter=0; counter<powerSetSize; counter++){
for(j=0; j<theSet.size(); j++){
currentArray = (T[]) new Comparable[j+1];
if((counter & (1 << j)) > 0)
currentArray[j] = theSet.get(j);
}
powerSet[counter] = new Set<>(currentArray);
}
return new Set<>((T[])powerSet);
}
public String toString(){
String str = "{";
for(int i=0; i<theSet.size(); i++){
if(i < theSet.size()-1)
str += theSet.get(i)+", ";
else
str += theSet.get(i)+"}";
}
return str;
}
}

You could try the following:
First create and Array of Integers with length of your basic set, setting every Integer to zero. Keep in mind that every Element is numbered due to its position in your basic set +1, because you need an empty Element, which is then zero. Then of course first create a Set of Sets, that you are going to return as your powerset. After that cycle through your array of Integers as follows: Create a Set out of the current Integer-Array by parsing every Integer to its corresponding element of the Set. Then add one to the first Integer of your Integer-Array. If the number is then greater than the length of your basic Set, add one to the next Integer of your Array, setting the "overflowing" Integer equal to the next Integer in the Array +1.
This should allow you to cycle through every possible combination for the powerset and add them to the Set.
public Set<Set<T>> powerSet(){
int[] num = new int[list.size()];
Arrays.fill(num,0);
Set<Set<T>> powerSet = new Set<>();
do{
powerSet.list.add(parse(num));
}while (addNum(num)); //Loops through every possibility
powerSet.list.add(parse(num));
//Because the method returns false when this was the last possible increment
return powerSet;
}
//Transforms a int[] into the corresponding Set
private Set<T> parse(int[] e){
Set<T> s = new Set<>();
for (int i = 0; i < e.length; i++) {
if(e[i]!=0){
s.list.add(list.get(e[i]-1)); //Every Element has its number
}
}
return s;
}
//Increments the counter
//Returns false if this was the last possible increment
private boolean addNum(int[] e){
e[0]++;
for (int i = 0; i < e.length; i++) {
if(e[i]>e.length-i){
e[i] = 0;
e[i+1]++;
}
}
for (int i = e.length-1; i != 0; i--) {
if(e[i]>=e[i-1]&&e[i]!=0){
e[i-1] = e[i]+1;
}
}
if(e[e.length-1]==1){
return false;
}
return true;
}
Output for [3,43,65,32] (printed out every Set of the powerset):
[]
[3]
[43]
[65]
[32]
[43, 3]
[65, 3]
[32, 3]
[65, 43]
[32, 43]
[32, 65]
[65, 43, 3]
[32, 43, 3]
[32, 65, 3]
[32, 65, 43]
[32, 65, 43, 3]
Although this may not be the most elegant way of solving the problem, it appears to work. I also don't know the requirements of the question. So maybe this answer isn't even suitable.

Related

How to change an integer array within a method

I am having an issue with a fill-in-the-code digital textbook problem. All the code is permanent and cannot be changed, so the problem can only be solved by using the area that states //Write code here.
The problem asks to implement the removeOdd method.
import java.util.Arrays;
public class RemoveTester
{
public static int removeOdd(int[] values, int size)
{
//Write code here
}
public static void main(String[] args)
{
int[] a = { 22, 98, 95, 46, 31, 53, 82, 24, 11, 19 };
int sizeBefore = 8;
int sizeAfter = removeOdd(a, sizeBefore);
System.out.print("a: [ ");
for (int i = 0; i < sizeAfter; i++)
{
System.out.print(a[i] + " ");
}
System.out.println("]");
System.out.println("Expected: [ 22 98 46 82 24 ]");
int[] b = { 23, 97, 95, 45, 31, 53, 81, 24, 11, 19 };
sizeBefore = 7;
sizeAfter = removeOdd(b, sizeBefore);
System.out.print("b: [ ");
for (int i = 0; i < sizeAfter; i++)
{
System.out.print(b[i] + " ");
}
System.out.println("]");
System.out.println("Expected: [ ]");
}
}
The way I tried to implement removeOdd is by doing:
int evenCount = 0;
for(int i = 0; i<size; i++){
if(values[i]%2==0){
evenCount++;
}
}
int[] newValues = new int[evenCount];
int newCount =0;
for(int i = 0; i<evenCount; i++){
if(values[i]%2==0){
newValues[newCount] = values[i];
newCount++;
}
}
values = newValues;
return evenCount;
When the program is compiled and ran, main prints the beginning of the original a or b arrays instead of only the even elements in a or b. I cannot find a way to alter the original arrays within the method removeOdd into the new arrays with only their even elements. I can't think of any other way to do this either. Any help would be greatly appreciated!
The other answers give a good description of what the problem is with your overall approach...that is, why your results don't make it back to the calling method.
If your code were otherwise correct, you could use it as is and just copy the result back into the original array at the end. As it is, you had one flaw in your logic. So if you fix that flaw, and then do the copy at the end, you should get the correct result:
public static int removeOdd(int[] values, int size)
{
int evenCount = 0;
for(int i = 0; i<size; i++){
if(values[i]%2==0){
evenCount++;
}
}
int[] newValues = new int[evenCount];
int newCount =0;
for(int i = 0; i<size; i++) { // <- Need to iterate over the entire input array
if(values[i]%2==0){
newValues[newCount] = values[i];
newCount++;
}
}
for (int i = 0 ; i < evenCount ; i++) // <- now copy your result to the original array
values[i] = newValues[i];
return evenCount;
}
Rather than creating an extra array to temporarily hold the even values, you can use the same logic to copy into the original array directly:
public static int removeOdd(int[] values, int size)
{
int newCount =0;
for(int i = 0; i<size; i++) {
if(values[i]%2==0){
values[newCount] = values[i];
newCount++;
}
}
return newCount;
}
Because Java is pass by value and not pass by reference, setting the value of the values argument will not change the value of the a variable.
What you have to do is remove all the odd elements from the array and shift the remaining even elements to the left so that the actual resultant form of a looks like this:
{22, 98, 46, 82, 24, 0, 0, 0, 0, 0}
As #Geoff pointed out Java is pass by value, which means when you pass your array as an argument, what you get inside the method is a reference to the array object which is different from the original reference int[] a you have inside your main method (the caller). Therefore, when you do values = newValues; you are pointing that new reference which used to point to the same object as int[] a to the array object newValues points to, thereby not updating the original array a but actually losing any reference to it.

Largest product in a series (java)

I'm trying to find the 3 adjacent numbers that produce the maximum product given a 9 digit number. For example for the number 198348756 my solution should return [8,7,5] since the product of this is 280 and is the maximum product possible.My code finds the max product but cannot return the array of digits that create the max product. Instead it returns the last array it checks in the for loop. I cannot understand why the array of digits that create the max product isn't stored in the variable result?
public class Solution {
ArrayList<Integer> digits = new ArrayList<>();
/// digits to int array
void tocharArray(String num) {
char[] charArray = num.toCharArray();
for (Character c : charArray) {
digits.add(Character.getNumericValue(c));
}
//System.out.println(digits);
//System.out.println(digits.size());
}
//gets product of array ex [1,2,3] ->6
int arrayproduct(ArrayList<Integer> array) {
int product = 1;
for(int i=0;i < array.size(); i++) {
product = product * array.get(i);
}
return product;
}
ArrayList<Integer> func() {
ArrayList<Integer> three = new ArrayList<>();
ArrayList<Integer> result = new ArrayList<>();
// array of the first 3 digits of the number
for(int index = 0; index < 3;index++) {
three.add(digits.get(index));
}
//initially the max product is the first 3 digits
int maxproduct = arrayproduct(three);
System.out.println(three); //from test [1,9,8]
System.out.println(maxproduct);// from test 72
ArrayList<Integer> copy = three;
for(int j = 3 ; j < digits.size();j++) {
copy.remove(0);
copy.add(digits.get(j));
int next = arrayproduct(copy);
System.out.println(copy);
if(next > maxproduct) {
maxproduct = next;
result = copy;
}
}
System.out.println(maxproduct); // returns 280 which is correct
System.out.println(result); // returns [7,5,6]
return result;
}
public static void main(String[] args) {
String test1 = "198348756";
Solution sol = new Solution();
sol.tocharArray(test1); \\[1,9,8,3,4,8,7,5,6]
sol.arrayproduct(sol.digits); \\returns [7,5,6] which is incorrect
sol.func();
}
}
The problem is on this line:
ArrayList<Integer> copy = three;
Your code assumes that copy is, well, a copy, but in reality it is an alias to the same three list.
You can fix it by actually copying the list:
ArrayList<Integer> copy = new ArrayList<>(three);
Same goes for result = copy - it needs to be result = new ArrayList<>(copy)
Note: You can further simplify this code by changing arrayproduct to take the initial index and length. This way you would be able to avoid creating new lists as you go. Once the proper location is found, you would be able to make a copy of three-element subrange by calling subList.
A easier approach
ArrayList<Integer> getMaxConsecutive(ArrayList<Integer> arr)
{
ArrayList<Integer> result = new ArrayList<Integer>();
int start=-1;
int max=INT_MIN;
for(int i=0;i<(arr.size()-3);i++)
{
int sum = arr.get(i)+arr.get(i+1)+arr.get(i+2);
if(sum>max){
max=sum;
start = i;
}
}
result.add(arr.get(start));
result.add(arr.get(start+1));
result.add(arr.get(start+2));
return result;
}
From the source code:
for (int j = 3; j < digits.size(); j++) {
copy.remove(0);
copy.add(digits.get(j));
int next = arrayproduct(copy);
System.out.println("-->" + next);
System.out.println("-->" + copy);
if (next > maxproduct) {
maxproduct = next;
result = copy;
System.out.println("result-->" + result);
}
}
The variable copy and result are object references like a pointer of C.
So, you need to copy(clone) all contents of copy's contents to the result object explicitly whenever the maxproduct value changes. There are several ways to accomplish about this method.
Using a clone method is one simple way to do;
result = copy;
to
result = (ArrayList<Integer>)copy.clone();
So, the func method is as follows:
#SuppressWarnings("unchecked")
ArrayList<Integer> func() {
ArrayList<Integer> three = new ArrayList<>();
ArrayList<Integer> result = new ArrayList<>();
// array of the first 3 digits of the number
for (int index = 0; index < 3; index++) {
three.add(digits.get(index));
}
// initially the max product is the first 3 digits
int maxproduct = arrayproduct(three);
System.out.println(three); // from test [1,9,8]
System.out.println(maxproduct);// from test 72
ArrayList<Integer> copy = three;
for (int j = 3; j < digits.size(); j++) {
copy.remove(0);
copy.add(digits.get(j));
int next = arrayproduct(copy);
System.out.println(copy);
if (next > maxproduct) {
maxproduct = next;
result = (ArrayList<Integer>)copy.clone();
}
}
System.out.println(maxproduct); // returns 280 which is correct
System.out.println(result); // returns [7,5,6]
return result;
}
Then the output message might be what you expected.
[1, 9, 8]
72
[9, 8, 3]
[8, 3, 4]
[3, 4, 8]
[4, 8, 7]
[8, 7, 5]
[7, 5, 6]
280
[8, 7, 5]
Have a good coding...

How to find if any values in array add up to n

I have an array of random values, and a target value.
#!/bin/bash
objective='50'
declare -a values=(1 2 2 6 8 14.5 15 28.7 .. 42)
I need to find a way to extract any combination of numbers in the array 'values' that add up to 50
The array has duplicates, and floating point integers.
A solution set might look like:
50 = 42 + 8
50 = 42 + 6 + 2
Initially I started in bash with some nested for loops, however I'm quickly realizing that this will grow exponentially with my array length.
I took a couple of java classes in college, but I'm still inexperienced in programming. I'm starting to think this may require recursion.
Can anyone with more programming experience point me in the right direction?
Besides nested for loops, how else could you approach this problem?
Here is an algorithm that has time complexity O(M*N) whereas M is Target and N is total size of set. Use analogy with knapsack problem as follows :-
Knapsack capacity = Target
Items are elements in the set with weight & value same as itself
Calculate maximum profit using dynamic programming
maxprofit = Target then there is/are subset which sum up to target.
Retrace the solution.
Java Solution for the same :-
public class SubSetSum {
static int[][] costs;
public static void calSets(int target,int[] arr) {
costs = new int[arr.length][target+1];
for(int j=0;j<=target;j++) {
if(arr[0]<=j) {
costs[0][j] = arr[0];
}
}
for(int i=1;i<arr.length;i++) {
for(int j=0;j<=target;j++) {
costs[i][j] = costs[i-1][j];
if(arr[i]<=j) {
costs[i][j] = Math.max(costs[i][j],costs[i-1][j-arr[i]]+arr[i]);
}
}
}
System.out.println(costs[arr.length-1][target]);
if(costs[arr.length-1][target]==target) {
System.out.println("Sets :");
printSets(arr,arr.length-1,target,"");
}
else System.out.println("No such Set found");
}
public static void printSets(int[] arr,int n,int w,String result) {
if(w==0) {
System.out.println(result);
return;
}
if(n==0) {
System.out.println(result+","+arr[0]);
return;
}
if(costs[n-1][w]==costs[n][w]) {
printSets(arr,n-1,w,new String(result));
}
if(arr[n]<=w&&(costs[n-1][w-arr[n]]+arr[n])==costs[n][w]) {
printSets(arr,n-1,w-arr[n],result+","+arr[n]);
}
}
public static void main(String[] args) {
int[] arr = {1,2,3,8,9,7};
calSets(10,arr);
}
}
I would do it like this:
1.some init
const int N=array size;
int val[N]; // input data
bool flag[N]; // is val used ?
for (int i=0;i<N;i++) flag[i]=false;
sort val[] descending
2.create function bool find_sum(int s);
if it found solution returns true else false
set flag to true for all used values
{
for (int i=0;i<N;i++) // find first usable big number (could be faster with binary search or with tailing last used i index into recursion)
if ((val[i]<=s)&&(!flag[i]))
{
flag[i]=true; // flag it as used
if (val[i]==s) return true; // try to find reminder
if (find_sum(s-val[i])) return true; // if found return true
flag[i]=false; // else unflag val[i] and continue winth next number
}
return false; // if sum not found then return false
}
3.after find_sum(s) your sum consists of all val[i] where flag[i]!=false
[edit1] functional source tested even for your case [6,5,5] and sum=10 it is OK
//---------------------------------------------------------------------------
int find_sum(int *val,int *use,int N,int sum,bool init=true)
{
int i;
if (init)
{
for (i=0;i<N;i++) use[i]=0; // nothibg used yet
for (int e=1;e;) // bubble sort
for (e=0,i=1;i<N;i++)
if (val[i-1]<val[i])
{ e=val[i-1]; val[i-1]=val[i]; val[i]=e; e=1; }
}
for (i=0;i<N;i++) // find first usable big number (could be faster with binary search or with tailing last used i index into recursion)
if ((val[i]<=sum)&&(!use[i]))
{
use[i]=1; // val[i] is used
if (val[i]==sum) return 1; // try to find reminder
if (find_sum(val,use,N,sum-val[i],false)) return 1; // if found return true
use[i]=0; // else val[i] is unused and continue winth next number
}
return 0; // if sum not found then return false
}
//---------------------------------------------------------------------------
void main()
{
int in[]={6,5,5}; // input data
const int N=sizeof(in)/sizeof(int);
int ret,out[N];
if (find_sum(in,out,N,10))
for (int i=0;i<N;i++)
if (out[i])
{
cout << in[i] << " ";
}
}
//---------------------------------------------------------------------------
PS. in your question in the input array are also floating point values
so you have to change int val[],sum to float/double
and add some accuracy for sum comparison to work with floats
if (val[i]==sum) return 1;
change to
if (fabs(val[i]-sum)<1e-10) return 1;
or use any other accuracy instead of 1e-10
You can use recursion yes, you can break the array into sub-parts (I use List).
Start from 0th index of the Parent list and a blank list
Iterate over to subList your Parent from i+1 to the end and thereby increasing your working list from 0 to i
Check for the sum (calculated) equals your objective
Code:
static Integer[] array = { 1, 2, 2, 6, 8, 14, 15, 28, 30, 32, 12, 48, 6, 42 };
static int objective = 50;
public static void main(String args[]) {
add(new ArrayList<Integer>(Arrays.asList(array)),
new ArrayList<Integer>());
}
public static void add(List<Integer> digits, List<Integer> workingList) {
for (int i = 0; i < digits.size(); i++) {
// New sublist to store values from 0 to i
List<Integer> list = new ArrayList<Integer>(workingList);
list.add(digits.get(i));
// Here you call this recursively with your Parent list from i+1
// index and working list from 0 to i
add(digits.subList(i + 1, digits.size()), list);
}
int sum = 0;
for (int element : workingList) {
sum += element;
}
if (sum == objective) {
System.out.println(objective + " = "
+ Arrays.toString(workingList.toArray()));
}
}
Output:
50 = [1, 2, 2, 15, 30]
50 = [1, 2, 6, 8, 15, 12, 6]
50 = [1, 2, 6, 14, 15, 12]
50 = [1, 2, 14, 15, 12, 6]
50 = [1, 2, 15, 32]
50 = [1, 2, 6, 8, 15, 12, 6]
...

Removing duplicates from array without using Util classes

Please read the question before marking it as duplicate
I have written following code to remove duplicates from array without using Util classes but now I am stuck
public class RemoveDups{
public static void main(String[] args) {
int[] a = { 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 3, 1, 4, 52, 1, 45, };
int temp;
for (int i : a) {
for (int j = 0; j < a.length - 1; j++) {
if (a[j] > a[j + 1]) {
temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
a = removeDups(a);
for (int i : a) {
System.out.println(i);
}
}
private static int[] removeDups(int[] a) {
int[] result = new int[a.length];
int j = 0;
for (int i : a) {
if (!isExist(result, i)) {
result[j++] = i;
}
}
return result;
}
private static boolean isExist(int[] result, int i) {
for (int j : result) {
if (j == i) {
return true;
}
}
return false;
}
}
and now the output is
1
2
3
4
5
6
45
52
0
0
0
0
0
0
0
0
0
0
Here my problem is
My code is not working in case of 0s
I am not able to understand how sorting an array can reduce time of execution
Is there any way to remove elements from array without using Util classes I know one way to remove convert array into list and then remove but for that also we need Util classes is there any way to implement by myself.
Since the numbers you deal with are limited to a small range you can remove duplicates by a simple "counting sort": mark the numbers you have found in a set-like data structure and then go over the data structure. An array of boolean works just fine, for less memory usage you could create a basic bitset or hash table. If n is the number of elements in the array and m is the size of the range, this algorithm will have O(n+m) complexity.
private static int[] removeDups(int[] a, int maxA) {
boolean[] present = new boolean[maxA+1];
int countUnique = 0;
for (int i : a) {
if (!present[i]) {
countUnique++;
present[i] = true;
}
}
int[] result = new int[countUnique];
int j = 0;
for (int i=0; i<present.length; i++) {
if (present[i]) result[j++] = i;
}
return result;
}
I am not able to understand how sorting an array can reduce time of execution
In a sorted array you can detect duplicates in a single scan, taking O(n) time. Since sorting is faster than checking each pair - O(n log n) compared to O(n²) time complexity - it would be faster to sort the array instead of using the naive algorithm.
As you are making the result array of the same length as array a
so even if you put only unique items in it, rest of the blank items will have the duplicate values in them which is 0 for int array.
Sorting will not help you much, as you code is searching the whole array again and again for the duplicates. You need to change your logic for it.
You can put some negative value like -1 for all the array items first in result array and then you can easily create a new result array say finalResult array from it by removing all the negative values from it, It will also help you to remove all the zeroes.
In java , arrays are of fixed length. Once created, their size can't be changed.
So you created an array of size18.
Then after you applied your logic , some elements got deleted. But array size won't change. So even though there are only 8 elements after the duplicate removal, the rest 10 elements will be auto-filled with 0 to keep the size at 18.
Solution ?
Store the new list in another array whose size is 8 ( or whatever, calculate how big the new array should be)
Keep a new variable to point to the end of the last valid element, in this case the index of 52. Mind you the array will still have the 0 values, you just won't use them.
I am not able to understand how sorting an array can reduce time of execution
What ? You sort an array if you need it to be sorted. Nothing else. Some algorithm may require the array to be sorted or may work better if the array is sorted. Depends on where you are using the array. In your case, the sorting will not help.
As for your final question , you can definitely implement your own duplicate removal by searching if an element exists more than once and then deleting all the duplicates.
My code is not working in case of 0
There were no zeroes to begin with in your array. But because its an int[], after the duplicates are removed the remaining of the indexes are filled with 0. That's why you can see a lot of zeroes in your array. To get rid of those 0s, you need to create another array with a lesser size(size should be equal to the no. of unique numbers you've in your array, excluding 0).
If you can sort your array(I see that its already sorted), then you could either bring all the zeroes to the front or push them to the last. Based on that, you can iterate the array and get the index from where the actual values start in the array. And, then you could use Arrays.copyOfRange(array, from, to) to create a copy of the array only with the required elements.
try this
package naveed.workingfiles;
public class RemoveDups {
public static void main(String[] args) {
int[] a = { 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 3, 1, 4, 52, 1, 45, };
removeDups(a);
}
private static void removeDups(int[] a) {
int[] result = new int[a.length];
int j = 0;
int count = 0;
for (int i : a) {
if (!isExist(result, i)) {
result[j++] = i;
count++;
}
}
System.out.println(count + "_____________");
for (int i=0;i<count;i++) {
System.out.println(result[i]);
}
// return result;
}
private static boolean isExist(int[] result, int i) {
for (int j : result) {
if (j == i) {
return true;
}
}
return false;
}
}
public class RemoveDups {
public static void main(String[] args) {
int[] a = { 1, 2, 0, 3, 1,0, 3, 6, 2};
removeDups(a);
}
private static void removeDups(int[] a) {
int[] result = new int[a.length];
int j = 0;
int count = 0;
boolean zeroExist = false;
for (int i : a) {
if(i==0 && !zeroExist){
result[j++] = i;
zeroExist = true;
count++;
}
if (!isExist(result, i)) {
result[j++] = i;
count++;
}
}
System.out.println(count + "_____________");
for (int i=0;i<count;i++) {
System.out.println(result[i]);
}
// return result;
}
private static boolean isExist(int[] result, int i) {
for (int j : result) {
if (j == i) {
return true;
}
}
return false;
}
}
// It works even Array contains 'Zero'
class Lab2 {
public static void main(String[] args) {
int[] a = { 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 3, 1, 4, 52, 1, 45 };
removeDups(a);
}
private static void removeDups(int[] a) {
int[] result = new int[a.length];
int j = 0;
int count = 0;
for (int i : a) {
if (!isExist(result, i)) {
result[j++] = i;
count++;
}
}
System.out.println(count + "_____________");
for (int i = 0; i < count; i++) {
System.out.println(result[i]);
}
}
private static boolean isExist(int[] result, int i) {
for (int j : result) {
if (j == i) {
return true;
}
}
return false;
}
}

How to find duplicates in a java array?

I'm trying to count how many duplicate items are in an array.
Example:
[0, 2, 0] would return 2, [0, 0, 0] would return 3, [0, 1, 2] = 0
So far I have it working for when all three items are equal, but I'm not sure why it's returning one less than what it should for 2 items being the same.
int equal = 0;
for(int i = 0; i < recent.length; i++) {
for(int j = i; j < recent.length; j++) {
if(i != j && recent[i].equals(recent[j])) {
equal++;
}
}
}
Your algorithm is flawed in the following way: for every element in the array you look at all the elements after that element and if they happen to be equal, you increase the counter. However when you have 3 same elements, you count the last one twice - when you run internal loop for first and for second element. Moreover you never count the first element.
So it works by accident for [0, 0, 0] but doesn't work for other inputs.
I think that having nested loops is quite inefficient. You should be able to do it in o(n) rather than o(n^2).
If you time yours against the following...
public void run() {
int[] array = createRandomArray(2000000, 1000000);
System.out.println(countNumDups1(array));
}
private int[] createRandomArray(int numElements, int maxNumExclusive) {
int[] array = new int[numElements];
Random random = new Random();
for (int i = 0; i < array.length; i++) {
array[i] = random.nextInt(maxNumExclusive);
}
return array;
}
private int countNumDups1(int[] array) {
Map<Integer, Integer> numToCountMap = new HashMap<>();
for (int i = 0; i < array.length; i++) {
Integer key = array[i];
if (numToCountMap.containsKey(key)) {
numToCountMap.put(key, numToCountMap.get(key) + 1);
}
else {
numToCountMap.put(key, 1);
}
}
int numDups = 0;
for (int i = 0; i < array.length; i++) {
Integer key = array[i];
if (numToCountMap.get(key) > 1) {
numDups++;
}
}
return numDups;
}
I think you'll find the above is much faster even considering the horrible inefficiency of autoboxing and object creation.
The code you gave counts equivalences, so it adds one every time an element equals another element.
It sounds like what you want is the number of duplicate items, which is the same as (length - number of items that don't have a duplicate). I will call the latter "uniqueItems".
I would recommend the following:
// set of every item seen
Set<Integer> allItems = new HashSet<Integer>();
// set of items that don't have a duplicate
Set<Integer> uniqueItems = new HashSet<Integer>();
for(int i = 0; i < recent.length; i++) {
Integer val = i;
if(allItems.contains(val)) {
// if we've seen the value before, it is not a "uniqueItem"
uniqueItems.remove(val);
} else {
// assume the value is a "uniqueItem" until we see it again
uniqueItems.add(val);
}
allItems.add(val);
}
return recent.length - uniqueItems.size();
The below code works perfectly to find the duplicates
int array[] = {1,2,3,4,5,2,3,4,5,3,4,5,4,5,5};
HashMap<Integer,Integer> duplicates = new HashMap<Integer,Integer>();
for(int i=0; i<array.length; i++)
{
if(duplicates.containsKey(array[i]))
{
int numberOfOccurances = duplicates.get(array[i]);
duplicates.put(array[i], (numberOfOccurances + 1));
}else{
duplicates.put(array[i], 1);
}
}
Iterator<Integer> keys = duplicates.keySet().iterator();
System.out.print("Duplicates : " );
while(keys.hasNext())
{
int k = keys.next();
if(duplicates.get(k) > 1)
{
System.out.print(" "+k);
}
}
You are counting the number of pairs of indices that have equal values. What you claim to want is the total size of all sets of equal elements that have more than one element in them.
I would use a Map or similar to count the total number of appearances of a given value. At the end, iterate over the key values adding the number of appearances for each key that has more than one appearance.
int intArray[] = {5, 1, 2, 3, 4, 5, 3, 2};
String val = "";
int c = 1;
Map<Integer, Integer> nwmap = new HashMap<Integer, Integer>();
for (int i = 0; i < intArray.length; i++) {
Integer key = intArray[i];
if(nwmap.get(key) != null && nwmap.containsKey(key)){
val += " Duplicate: " +String.valueOf(key)+"\n";
}else{
nwmap.put(key, c);
c++;
}
}
LOG.debug("duplicate value:::"+val);
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
public class ArrayDuplicateCount {
/**
* #author:raviteja katari
*/
public static void main(String[] args) {
int intArray[] = {5, 1,4,4,4,5,1,2,1,2,5,5};
//for counting duplicate items
int c = 0;
//creating map collection to hold integers as keys and Cont as value
Map<Integer, Integer> nwmap = new LinkedHashMap<Integer, Integer>();
for (int i = 0; i <intArray.length; i++) {
//Assigning array element to key
Integer key = intArray[i];
//this code checks for elemnt if present updates count value else
//put the new Array elemnt into map and increment count
if(nwmap.containsKey(key)){
//updating key value by 1
nwmap.put(key, nwmap.get(key) + 1);
}else{
//Adding new array element to map and increasing count by 1
nwmap.put(key, c+1);
}
}
//printing map
System.out.println(nwmap);
}
}
output:
{5=4, 1=3, 4=3, 2=2}
public void TotalduplicateNumbers {
int a[] = {2,8,2,4,4,6,7,6,8,4,5};
Map<Integer,Integer> m = new HashMap<Integer,Integer>();
for(int i=0;i<a.length;i++){
if(!m.containsKey(a[i]))
{
m.put(a[i], 1);
}
else
{
m.put(a[i], (m.get(a[i])+1));
}
}
for(Integer i:m.keySet()){
System.out.println("Number "+i+" "+"Occours "+m.get(i)+" time,");
}
}
We have an array containing 11 numbers, The logic is to create a map using these no. in which KEYS of map would be the actual number that must be entered by user and no. of occournce of that actual no. would be the value of that KEY. Here, containsKey() method checks whether the map contain that key already and return boolean value true or false as applied.If it does not contain then add that key into the map and its corresponding value should be 1 otherwise key would have already be contained in map so get the value of that key using get() and increment it by 1. Finally printing the map.
OUTPUT:--
Number 2 Occours 2 time,
Number 4 Occours 3 time,
Number 5 Occours 1 time,
Number 6 Occours 2 time,
Number 7 Occours 1 time,
Number 8 Occours 2 time,

Categories