Getting the Elements that has duplicates in an int array Java - java

This post - "Java + Count duplicates from int array without using any Collection or another intermediate Array", was also a sample exercise in my book at school, but what I want to do is get the elements that has duplicates without sorting it.
What I did is I removed the duplicates of arrays first, to get only the unique elements and then I compare it to the original array and count how many times the element has been found. But the problem is it doesn't print the correct elements which has duplicates.
int[] num = {7, 2, 6, 1, 4, 7, 4, 5, 4, 7, 7, 3, 1};
the correct output should be: 7, 1, 4
but instead it outputs: 7, 6, 1
This is my codes:
//method for removing duplicates
public static int[] removeDuplicates(int[] n) {
int limit = n.length;
for(int i = 0; i < limit; i++) {
for(int j = i + 1; j < limit; j++) {
if(n[i] == n[j]) {
for(int k = j; k < limit - 1; k++) {
n[k] = n[k + 1];
}
limit--;
j--;
}
}
}
int[] uniqueValues = new int[limit];
for(int i = 0; i < uniqueValues.length; i++) {
uniqueValues[i] = n[i];
}
return uniqueValues;
}
//method for getting elements that has duplicates
public static int[] getDuplicatedElements(int[] n) {
int[] nCopy = n.clone();
int[] u = removeDuplicates(nCopy);
int count = 0;
int limit = u.length;
for(int i = 0; i < u.length; i++) {
for(int j = 0; j < n.length; j++) {
if(u[i] == n[j]) {
count++;
}
}
if(count == 1) {
for(int k = i; k < limit - 1; k++) {
u[k] = u[k + 1];
}
limit--;
}
count = 0;
}
int[] duplicated = new int[limit];
for(int i = 0; i < duplicated.length; i++) {
duplicated[i] = u[i];
}
return duplicated;
}
//main
public static void main(String[] args) {
int[] num = {7, 2, 6, 1, 4, 7, 4, 5, 4, 7, 7, 3, 1};
//printing original values
System.out.print(Arrays.toString(num));
System.out.println();
int[] a = getDuplicatedElements(num);
System.out.print("Elements with Duplicates: " + Arrays.toString(a));
}
What's the error in my codes here? Please help thanks...

You have two issues:
public static int[] getDuplicatedElements(int[] n) {
int[] nCopy = n.clone();
int[] u = removeDuplicates(nCopy);
System.out.println ("unique " + Arrays.toString (u));
int count = 0;
int limit = u.length;
for(int i = 0; i < limit; i++) { // you must use limit instead of u.length
// in order for the loop to terminate
for(int j = 0; j < n.length; j++) {
if(u[i] == n[j]) {
count++;
}
}
if(count == 1) {
for(int k = i; k < limit - 1; k++) {
u[k] = u[k + 1];
}
limit--;
i--; // you must decrement i after you find a unique element in u
// otherwise you'll be skipping elements in the u array
}
count = 0;
}
int[] duplicated = new int[limit];
for(int i = 0; i < duplicated.length; i++) {
duplicated[i] = u[i];
}
return duplicated;
}
With those fixes, you'll get the expected output:
Elements with Duplicates: [7, 1, 4]

It's fairly simple when using a stream
int[] num = {7, 2, 6, 1, 4, 7, 4, 5, 4, 7, 7, 3, 1};
List<Integer> list = Arrays.stream(num).boxed().collect(Collectors.toList());
list.stream().filter(i -> Collections.frequency(list, i) > 1)
.collect(Collectors.toSet()).forEach(System.out::println);

Related

ArrayList Bubblesort with strings

The sorting is not working, it doesn't sort the names by the alphabet, I wrote a bubble sort algorithm with int and it worked fine. Can you help me? Is something wrong with the compareTo() method?
public ArrayList<FootballPlayer> sortByNames(ArrayList<FootballPlayer> pList)
{
FootballPlayer z;
for(int i=0; i<pList.size(); i++)
{
for(int j=0; j<pList.size()-i-1;j++)
{
if((pList.get(i).getName()).compareTo(pList.get(j+1).getName())>0)
{
z = pList.get(j);
pList.set(j, pList.get(j+1));
pList.set(j+1,z);
}
}
}
for(int i=0; i<pList.size(); i++)
{
System.out.print(pList.get(i).getName()+";");
System.out.println("");
}
return pList;
}
Your implementation is not BubbleSort! Check Bubble sort or event a bit more advanced Cocktail shaker sort.
public static void bubbleSort(List<String> pList) {
boolean done = false;
for (int i = pList.size(); !done; i--) {
done = true;
for (int j = 0; j + 1 < i; j++) {
if (pList.get(j).compareTo(pList.get(j + 1)) <= 0)
continue;
done = false;
String tmp = pList.get(j);
pList.set(j, pList.get(j + 1));
pList.set(j + 1, tmp);
}
}
}
Output:
List<String> pList = new ArrayList<>();
for (int i = 0; i < 10; i++)
pList.add(String.valueOf(i));
Collections.shuffle(pList);
System.out.println(pList); // [0, 6, 7, 9, 5, 8, 4, 1, 3, 2]
bubbleSort(pList);
System.out.println(pList); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Merge K sorted arrays of size n using merge algorithm from mergeSort

Problem: Given K sorted arrays of size N each, merge them and print the sorted output.
Sample Input-1:
K = 3, N = 4
arr[][] = { {1, 3, 5, 7},
{2, 4, 6, 8},
{0, 9, 10, 11}} ;
Sample Output-1:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
I know there is a way to do this problem using a priority queue/min heap, but I want to do it using the merge procedure from mergeSort. The idea seems straightforward enough...at each iteration, merge the remaining arrays in groups of two, such that the number of arrays gets halved at each iteration.
However, whenever halving leads to an odd number, this becomes problematic.
My idea is that whenever halving leads to an odd number, we take care of the extra array by merging it with the array formed from the last merge.
The code I have so far is below. This only works on one out of 30 test cases, however:
static int[] mergeArrays(int[][] arr) {
int k = arr.length;
int n = arr[0].length;
if(k < 2){
return arr[0];
}
boolean odd_k;
if(k%2){
odd_k = false;
}
else{
odd_k = true;
}
while(k > 1){
int o;
if(odd_k){
o = (k/2) + 1;
}
else{
o = k/2;
}
int[][] out = new int[o][];
for(int i=0; i < k; i = i + 2){
int[] a;
int[] b;
if(odd_k && i == (k-1)){
b = arr[i];
b = out[i-1];
}
else{
a = arr[i];
b = arr[i+1];
}
out[i] = mergeTwo(a, b);
}
k = k/2;
if(k % 2 == 0){
odd_k = false;
}
else{
odd_k = true;
}
arr = out;
}
return arr[0];
}
static int[] mergeTwo(int[] a, int[] b){
int[] c = new int[a.length + b.length];
int i, j, k;
i = j = k = 0;
while(i < a.length && j < b.length){
if(a[i] < b[j]){
c[k] = a[i];
i++;
k++;
}
else{
c[k] = b[j];
j++; k++;
}
}
if(i < a.length){
while(i < a.length){
c[k] = a[i];
i++; k++;
}
}
if(j < b.length){
while(j < b.length){
c[k] = b[j];
j++; k++;
}
}
return c;
}
We can shorten your mergeTwo implementation,
static int[] mergeTwo(int[] a, int[] b) {
int[] c = new int[a.length + b.length];
int i = 0, j = 0, k = 0; // declare and initialize on one line
while (i < a.length && j < b.length) {
if (a[i] <= b[j]) {
c[k++] = a[i++]; // increment and assign
} else {
c[k++] = b[j++]; // increment and assign
}
}
// No need for extra if(s)
while (i < a.length) {
c[k++] = a[i++];
}
while (j < b.length) {
c[k++] = b[j++];
}
return c;
}
And we can then fix your mergeArrays and shorten it by starting with the first row from the int[][] and then using mergeTwo to concatenate the arrays iteratively. Like,
static int[] mergeArrays(int[][] arr) {
int[] t = arr[0];
for (int i = 1; i < arr.length; i++) {
t = mergeTwo(t, arr[i]);
}
return t;
}
I then tested it with
public static void main(String[] args) {
int arr[][] = { { 1, 3, 5, 7 }, { 2, 4, 6, 8 }, { 0, 9, 10, 11 } };
System.out.println(Arrays.toString(mergeArrays(arr)));
}
And I get (as expected)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
As you say you have merged two arrays at a time. As it is inefficient you can merge all subarrays same time. What you have to do is to find the minimum from every subarray and remember the position of that element.
To do that we can use another array (say curPos) to remember the current position
private int[] merge(int[][] arr)
{
int K = arr.length;
int N = arr[0].length;
/** array to keep track of non considered positions in subarrays **/
int[] curPos = new int[K];
/** final merged array **/
int[] mergedArray = new int[K * N];
int p = 0;
while (p < K * N)
{
int min = Integer.MAX_VALUE;
int minPos = -1;
/** search for least element **/
for (int i = 0; i < K; i++)
{
if (curPos[i] < N)
{
if (arr[i][curPos[i]] < min)
{
min = arr[i][curPos[i]];
minPos = i;
}
}
}
curPos[minPos]++;
mergedArray[p++] = min;
}
return mergedArray;
Probably the easiest way to handle this is to use a queue of arrays. Initially, add all the arrays to the queue. Then, remove the first two arrays from the queue, merge them, and add the resulting array to the queue. Continue doing that until there is only one array in the queue. Something like:
for each array in list of arrays
queue.push(array)
while queue.length > 1
a1 = queue.pop()
a2 = queue.pop()
a3 = merge(a1, a2)
queue.push(a3)
result = queue.pop()
That simplifies things quite a bit, and the problem of "halving" goes away.

Trouble with splitting an array into chunks

I have an array:
private static int[] array = {5, 2, 1, 6, 3, 7, 8, 4};
I'm trying to split it into a two-dimensional array with x amount of chunks, where all of the chunks have an equal length (in my case, 2), then assign each value of the original array to a corresponding index within the array. It would then increment the index of the chunk number and reset the index iterating through the individual arrays hit the length of one.
Problem is, the code I wrote to perform all that isn't outputting anything:
public class Debug
{
private static int[] array = {5, 2, 1, 6, 3, 7, 8, 4};
private static void chunkArray(int chunkSize)
{
int chunkNumIndex = 0;
int chunkIndex = 0;
int numOfChunks = (int)Math.ceil((double)array.length / chunkSize);
int[][] twoDimensionalArray = new int[numOfChunks][chunkSize];
for (int i = 0; i < array.length; i++)
{
twoDimensionalArray[chunkNumIndex][chunkIndex] = array[i];
chunkIndex++;
while(chunkNumIndex < numOfChunks)
{
if (chunkIndex == chunkSize)
{
chunkNumIndex++;
chunkIndex = 0;
}
}
}
for(int i = 0; i < chunkNumIndex; i++)
{
for(int j = 0; j < chunkIndex; j++)
{
System.out.printf("%5d ", twoDimensionalArray[i][j]);
}
System.out.println();
}
}
public static void main(String args[])
{
chunkArray(2);
}
}
Could anyone be of assistance in debugging my program?
The problem is that you have an unnecessary while(chunkNumIndex < numOfChunks) which makes no sense. The if statement is sufficient to iterate your variables correctly:
for (int i = 0; i < array.length; i++) {
twoDimensionalArray[chunkNumIndex][chunkIndex] = array[i];
chunkIndex++;
if (chunkIndex == chunkSize) {
chunkNumIndex++;
chunkIndex = 0;
}
}
Also, remember that the values of chunkNumIndex and chunkIndex are dynamic, so for the last for loops, use twoDimensionalArray.length and twoDimensionalArray[0].length instead:
for(int i = 0; i < twoDimensionalArray.length; i++) {
for(int j = 0; j < twoDimensionalArray[0].length; j++) {
System.out.printf("%5d ", twoDimensionalArray[i][j]);
}
}
You're making this unnecessarily hard, there is no need to keep counters for chunkIndex and chunkNumIndex, we can just div and mod i.
int numOfChunks = (array.length / chunkSize) + (array.length % chunkSize == 0 ? 0 : 1);
int[][] twoDimensionalArray = new int[numOfChunks][chunkSize];
for (int i = 0; i < array.length; i++) {
twoDimensionalArray[i / chunkSize][i % chunkSize] = array[i];
}
Something like this should already do the job.

Java Multidimensional array and integer occurrences

I have this integer array called numList which has
[4, 4, 3, 3, 3, 2, 1, 1, 1, 1, -1, -12, -12, -12, -12]
I would like to create a multidimensional array which can store
Which left side represents the number and the right side determines the number of occurrences.
The attempt i tried... i got nowhere.
// Declaring the new multi-dimensional array.
int [] [] newArray = new int [6] [2];
// Counter 3.
int counter3 = 0;
// Get first occurrence.
while (numList[counter3] < numList.length){
for (int counter3:numList){
newArray[] ([counter3]++);
}
Assuming your numbers are in order as they are in your example numList, then you could do this:
int[] numList = { 4, 4, 3, 3, 3, 2, 1, 1, 1, 1, -1, -12, -12, -12, -12 };
int[][] newArray = new int[6][2];
int index = 0;
for (int i = 0; i < numList.length;) {
int count = 0;
for (int x = 0; x < numList.length; x++)
if (numList[x] == numList[i]) count++;
newArray[index][0] = numList[i];
newArray[index][1] = count;
index++;
i += count;
}
for (int x = 0; x < newArray.length; x++) {
for (int i = 0; i < newArray[0].length; i++)
System.out.print(newArray[x][i] + " ");
System.out.println();
}
This way, you don't have to deal with imports as in the other answers (and this is shorter), but this only works if you have ordered numbers. There are some good sorting algorithms out there, though.
Edit: I changed it so that it can take numbers in any order of any size.
int[] numList = { 6, 6, 5, 5, 4, 4, 3, 2, 1, 1, 1, 7, 6, 5, 7, 8, 65, 65, 7 };
int[][] newArray = new int[1][2];
int index = 0;
for (int i = 0; i < numList.length;) {
try {
int count = 0;
boolean isUnique = true;
for (int x = 0; x < i; x++)
if (numList[x] == numList[i]) {
isUnique = false;
break;
}
if (isUnique) {
for (int x = 0; x < numList.length; x++)
if (numList[x] == numList[i]) count++;
newArray[index][0] = numList[i];
newArray[index][1] = count;
index++;
}
i++;
} catch (ArrayIndexOutOfBoundsException e) {
int tmpArray[][] = newArray;
newArray = new int[tmpArray.length + 1][tmpArray[0].length];
for (int row = 0; row < tmpArray.length; row++)
for (int col = 0; col < 2; col++)
newArray[row][col] = tmpArray[row][col];
}
}
for (int x = 0; x < newArray.length; x++) {
for (int i = 0; i < newArray[0].length; i++)
System.out.print(newArray[x][i] + " ");
System.out.println();
}
So, at this point, it would probably be shorter to use the maps from the other answer. The only benefit of my second answer not worrying about imports.
private Map<Integer, Integer> segregateArray(List<Integer> list) {
Map<Integer, Integer> result = new HashMap<>();
for (Integer i : list) {
if (result.containsKey(i)) {
result.put(i, result.get(i) + 1);
} else {
result.put(i, 1);
}
}
return result;
}
This should work. If you still need to return array use this:
private int[][] segregateArray(int[]list) {
Map<Integer, Integer> resultHelper = new HashMap<>();
for (int i : list) {
if (resultHelper.containsKey(i)) {
resultHelper.put(i, resultHelper.get(i) + 1);
} else {
resultHelper.put(i, 1);
}
}
int[][] result = new int[resultHelper.size()][2];
int arrayIterator=0;
for(Integer key : resultHelper.keySet())
{
result[arrayIterator][0]=key;
result[arrayIterator][1]=resultHelper.get(key);
arrayIterator++;
}
return result;
}
In the real life project you probably should avoid implementing a functionality like this yourself using a low level array mechanism (you added an extensive test suite, didn't you? :) and opt for one of available libraries.
In Java 8 this can be done nicely using closures similarly to what has been described here: Count int occurrences with Java8.
In Java 7 and earlier I would use one of the collection libraries such as Guava, which contains a Multiset collection delivering exactly what you're after.

difficulty with arrays

I am a bit stuck so if anyone has a spare moment it would be a great help for me. I am using eclipse and the program is compiling and running. but there is a runtime error.
in the array {2, 1, 1, 2, 3, 3, 2, 2, 2, 1} I want to print {2, 2, 2} which is the numbers with the highest repeating times in the array. What I am getting is:
0
1
0
0
3
0
2
2
0
Thank you guys and here is my code.
public class SameIndexInArray
{
public static void main(String[] args)
{
int[] array = {2, 1, 1, 2, 3, 3, 2, 2, 2, 1};
int[] subarray = new int[array.length]; //store the values should be {2, 2, 2}
int max = 1;
int total = 1;
for(int i=0; i<array.length-1; i++)
{
if(array[i] != array[i + 1])
{
max = 1;
}
else if(array[i] == array[i + 1])
{
max++;
total = max;
subarray[i] = array[i]; // here is the issue
}
System.out.println(subarray[i]);
}
//System.out.println(total);
}
}
You only store facultatively into subarray, so you should define a separate counter (let's say j) for subarray index counting, and say subarray[j++] = array[i]. And, you shouldn't output subarray for each index of array, so move that println into the second if clause.
see if this works
int[] array = {2, 1, 1, 2, 3, 3, 2, 2, 2, 1};
int frequency = 0;
int num = 0;
for(int i=0; i<array.length-1; i++)
{
int lfreq = 1;
int lnum = array[i];
while(array[i] == array[i+1]){
lfreq++;
i++;
}
if(lfreq >= frequency){
frequency = lfreq;
num = lnum;
}
}
int[] subarray = new int[frequency];
for(int i=0; i < frequency; i++)
subarray[i] = num;
System.out.println(Arrays.toString(subarray));
You need to use another index but "i"
you can't relate to 2 arrays with the same index
Your problem is that all values in subarray are initialized with 0 and you only edit the values when there is an actual sequence, starting with the second element.
The whole subarray is unneccessary. Just save the start index and the length of the subquery ;)
What I mean is something like this:
int[] array = {2, 1, 1, 2, 3, 3, 2, 2, 2, 1};
int startIndex = 0;
int length = 0;
int longestIndex = 0;
int longestLength = 0;
for(int i=0; i<array.length-1; i++)
{
if(array[i] != array[i + 1])
{
if (length > longestLength) {
longestLength = length;
longestIndex = startIndex;
}
startIndex = i;
length = 1;
}
else if(array[i] == array[i + 1])
{
length++;
}
}
if (length > longestLength) {
longestLength = length;
longestIndex = startIndex;
}
Now you that you know where your longest sequence starts and how long it is you can build your new array:
int[] sequence = new int[longestLength];
for (int i = 0; i < longestLength; i++) {
sequence[i] = array[i + startIndex];
}
Thats because you are inserting at an index position "i" into subarray.
For example,
The second time the loop runs.
array[1] == array[2] is true and
subarray[i] = array[i];
runs. So at this moment the contents of subarray is {0,1,0,0,0,0,0,0,0}. Note that arrays are initialized to 0 by default.
This is how you could do it.
int[] array = {2, 1, 1, 2, 3, 3, 2, 2, 2, 1};
//store the values should be {2, 2, 2}
int max = 1;
int total = 1;
int value = 0;
for(int i=0; i<array.length-1; i++)
{
if(array[i] != array[i + 1])
{
max = 1;
}
else if(array[i] == array[i + 1])
{
max++;
total = max;
value = array[i];
}
}
int[] subarray = new int[total];
for(int i=0; i<total; i++)
subarray[i] = value;
public static void main(String[] args) {
int[] ar = { 2, 1, 1, 2, 3, 3, 2, 2, 2, 1 };
int max=0,
maxStart=0,
count=1;
for(int i=1; i<ar.length; i++) {
if (ar[i-1] == ar[i]) {
count++;
if(count > max) {
max = count;
maxStart = i-count+1;
}
}else {
count=1;
}
}
System.out.println("Sub array begins from " + maxStart);
for(int i = maxStart; i < maxStart + max; i++) {
System.out.print(ar[i] + " ");
}
}

Categories

Resources