Non-repeating numbers in 2D array - java

I have problem with my code, I want to find not repeated numbers in array but I don't know how!
1 2
3 4
1 4
For example in this case, I wan the output to be number 3 and 2:
I used this code for getting array, it's like a matrix
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 2; j++) {
cam[i][j] = in.nextInt();
}
}
And something like this one for comparing for each one:
for (int i = 1; i <= 3; i++) {
if (cam[i][2] != cam[i+1][2]) {
y = cam[i+1][2];
break;
}
}
Update: whole code is down below
int x=0,y=0;
int[][] cam = new int[10][10];
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 2; j++) {
cam[i][j] = in.nextInt();
}
}
for (int i = 1; i <= 3; i++) {
if (cam[i][1] != cam[i+1][1]) {
x = cam[i+1][1];
break;
}
for (int i = 1; i <= 3; i++) {
if (cam[i][2] != cam[i+1][2]) {
y = cam[i+1][2];
break;
}
}
System.out.println(x+" "+y);

Array indices are 0, 1, 2, ..., length-1.
for (int i = 0; i < cam.length; i++) {
for (int j = 0; j <= cam[i].length; j++) {
cam[i][j] = in.nextInt();
}
}
The search code:
for (int i = 0; i < cam.length; i++) {
for (int j = 0; j <= cam[i].length; j++) {
int valueAtIJ = cam[i][j];
boolean found = false;
... walk here through cam using valueAtIJ, set found, skip i, j.
if (!found) {
...
}
}
}
If alread Set/Map is treated in your course there are smarter solutions. But also this kind of for-i2-for-j2 loop can be optimized.

Assuming from your code that you are looking only in column 1 and 2 (do you have other data in column 0?):
for (int i = 1; i <= 3; i++) {
found = false;
for (int i1 = i + 1; i1 <= 3; i1++) {
if (cam[i][1] == cam[i1][1]) {
found = true;
break;
}
}
if (!found) {
x = cam[i][1];
}
}
for (int i = 1; i <= 3; i++) {
found = false;
for (int i1 = i + 1; i1 <= 3; i1++) {
if (cam[i][2] == cam[i1][2]) {
found = true;
break;
}
}
if (!found) {
y = cam[i][2];
}
}

You can collect a map of duplicates from this 2d array, then iterate over this map and apply filter for non-repeating elements:
int[][] arr = {
{1, 2},
{3, 4},
{1, 4}};
Map<Integer, Long> map = Arrays.stream(arr)
.flatMapToInt(Arrays::stream).boxed()
.collect(Collectors.groupingBy(
Integer::intValue, Collectors.counting()));
System.out.println(map); // {1=2, 2=1, 3=1, 4=2}
int[] arr2 = map.entrySet().stream()
.filter(e -> e.getValue() == 1)
.mapToInt(Map.Entry::getKey)
.toArray();
System.out.println(Arrays.toString(arr2)); // [2, 3]
See also: How to find duplicate elements in array in effective way?

Related

How to shift elements to left after removing array element?

I was asked to write, to remove the element (lets say k=30) from the array and shift the other elements to its left without using inbuilt methods.
I have tried the below approach.
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr = new int[] { 1, 2, 30, 4, 5, 30, 6 };
int k = 30;
int count = 0;
System.out.println("---Original Array------");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
for (int i = 0; i < arr.length; i++) {
if (arr[i] == k)
count++;
}
for (int j = 0; j < count; j++) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == k) {
for (int l = i; l < arr.length - 1; l++) {
arr[l] = arr[l + 1];
}
}
}
}
System.out.println("---Modified Array------");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
I need output like this: [1 2 4 5 6 0 0]
But the output from the above logic is: [1 2 4 5 6 6 6]
Also, I'm worried about using nested for loops here. Is there any way that we can reduce the time complexity with out using any inbuilt methods?
Here is another variant:
int[] arr = new int[] { 1, 2, 30, 4, 5, 30, 6 };
int k = 30;
int j = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] != k) {
arr[j++] = arr[i];
}
}
while (j < arr.length) {
arr[j++] = 0;
}
In order to not change your approach drastically, I would suggest adding another iteration of the array at the end, to insert 0s to count-many indices from the end of your array.
This would be as simple as adding the following snippet:
// nested for loop
// ...
// set trailing elements to 0s
for (int i = 0; i < count ; i++)
arr[arr.length-1-i] = 0;
System.out.println("\n---Modified Array------");
// ...
There are some cleaner/more-efficient ways of solving this problem.
Based exactly on your approach, I went ahead and made a modification to your nested loop to not require another iteration.
for (int j = 0; j < count; j++) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == k) {
for (int l = i; l < arr.length - 1; l++)
arr[l] = arr[l + 1];
// since we have performed the shifting, we can safely set the last element to 0
arr[arr.length-1] = 0; // <----- this was missing!!
}
}
}
The following code gives the desired result:
int [] arr = { 1, 2, 30, 4, 5, 30, 6 };
int k = 30;
int elementCount = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] == k) {
++elementCount;
}
}
int count = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] == k) {
count++;
for (int j = i; j < arr.length-1; j++) {
arr[j] = arr[j+1];
}
arr[arr.length-1] = 0;
}
if (count == elementCount) {
break;
}
}
I don't know if it helps. This is a simplified aproach, that is easier to read and understand(at least for people that learned C), that does removal as required....
public static void main(String[] args) {
int[] arr = new int[] { 1, 2, 30, 4, 5, 30, 6 };
int k = 30;
int i=0;
int j=0;
for(;j<arr.length;i++,j++){
if((arr[i]=arr[j])==k) i--;
}
while(i<j)arr[i++]=0;
System.err.println(Arrays.toString(arr));
}
output:[1, 2, 4, 5, 6, 0, 0]
First version with a small fix on your code. You issue is that the shifted elements need to be replaced by zero. Which require basically an if statement with the arr.length - count
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr = new int[] { 1, 2, 30, 4, 5, 30, 6 };
int k = 30;
int count = 0;
System.out.println("---Original Array------");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println("");
for (int i = 0; i < arr.length; i++) {
if (arr[i] == k)
count++;
}
for (int j = 0; j < count; j++) {
for (int i = 0; i < arr.length; i++) {
if(i >= arr.length - count){
arr[i] = 0;
}else {
if (arr[i] == k) {
for (int l = i; l < arr.length - 1; l++) {
arr[l] = arr[l + 1];
}
}
}
}
}
System.out.println("---Modified Array------");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println("");
}
Which gives output
---Original Array------
1 2 30 4 5 30 6
---Modified Array------
1 2 4 5 6 0 0
Now, we can simplify the code also
public static void main(String[] args) {
int[] arr = new int[] { 1, 2, 30, 4, 5, 30, 6 };
int k = 30;
int count = 0;
System.out.println("---Original Array------");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println("");
for(int i = 0; i < arr.length; i++){
if(arr[i]==k){
count++;
}else{
arr[i-count] = arr[i];
}
}
for(int i = 1; i <= count; i++){
arr[arr.length - i] = 0;
}
System.out.println("---Modified Array------");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println("");
}
which give the same output

Removing N duplicates from integer array

problem statement: I have to remove n duplicates from array.
Here is the full problem statement : https://pastebin.com/EJgKUGe3
and my solution is :
public class minion_labour_shift_2ndTry {
static int[] data = {1,2, 2, 3, 3, 3, 4, 5, 5};
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
int n = reader.nextInt();
data = answer(data, n);
for (int i = 0; i < data.length; i++) {
System.out.print(data[i] + " ");
}
}
public static int[] answer(int[] data, int n) {
if (data.length>99){
System.exit(0);
}
int[] result = new int[99];
ArrayList<Integer> temp = new ArrayList<>();
int counter = 0, count ,maxCount = 0;
for (int i = 0; i < data.length; i++) {
boolean isDistinct = false;
for (int j = 0; j < i; j++) {
if (data[i] == data[j]) {
isDistinct = true;
break;
}
}
if (!isDistinct) {
result[counter++] = data[i];
}
}
for (int i = 0; i < counter; i++) {
count = 0;
for (int j = 0; j < data.length; j++) {
if (result[i] == data[j]) {
count++;
}
}
System.out.println("....... count"+count);
if (maxCount <= count){
maxCount = count;
}
if (count <= n){
temp.add(result[i]);
}
}
if (maxCount-1 < n){
return data;
}
data = new int[temp.size()];
for (int i = 0; i <temp.size() ; i++) {
data[i] = temp.get(i);
}
return data;
}
}
Now, my question is, what I am missing and what should I do to pass all the 10 cases.
Thanks In Advance :)
NB:It will be compiled in java 7 , and Map,hashset or third-party libraries, input/output operations, spawning threads or processes and changes to the execution environment are not allowed.
I misread the requirements initially, this does what is asked:
public static int[] answer(int[] data, int n) {
Map<Integer, Integer> counts = new HashMap<>();
int elementsNeeded = 0;
for (int i = 0; i < data.length; i++) {
Integer currentCount = counts.get(data[i]);
currentCount = currentCount == null ? 1 : ++currentCount;
counts.put(data[i], currentCount);
if (currentCount <= n + 1) {
elementsNeeded += currentCount > n ? -n : 1;
}
}
int[] resultArray = new int[elementsNeeded];
int j = 0;
for (int i = 0; i < data.length; i++) {
if (counts.get(data[i]) <= n) {
resultArray[j++] = data[i];
}
}
return resultArray;
}
...and also your own code, slightly altered:
public static int[] answer2(int[] data, int n) {
if (data.length>99){
System.exit(0);
}
ArrayList<Integer> temp = new ArrayList<>();
int count;
for (int i = 0; i < data.length; i++) {
count = 0;
for (int j = 0; j < data.length; j++) {
if (data[i] == data[j]) {
count++;
}
}
if (count <= n){
temp.add(data[i]);
}
}
data = new int[temp.size()];
for (int i = 0; i <temp.size() ; i++) {
data[i] = temp.get(i);
}
return data;
}
Not going to provide a full solution but suggesting a reworking of the algorithm because it's not clear what you're doing, you never explained your actual thoughts of the algorithm. For example, what are you using isDistinct for?
1) Loop through once and compute the frequency of every number. You can just use an array of length 100 since that's all the data inputs will be. As you loop through, keep track of two things: The total number of entries that occur more than n times, as well as which those numbers are
2) Create a resulting array of the appropriate size (calculated from above) and loop through the list again and fill in the elements that didn't cross the threshold.

How to make while loop work properly to correct given 2D array

I'm trying to write a method that will take a two-dimensional array as an input, and return a new 2D array in which all the zeroes are removed from the array.
Also, if there is an element in the first array that has a value equal to the length of the second array, then it should be removed and all elements in the second array will be subtracted by 1.
The above process should be repeated for the second array also.
This is what I've written for the code implementation so far, but the code gets stuck in a loop and I don't think it's doing what it's supposed to do.
Note: When ArrayUtils is called, the Apache Lang library is being used, and this is the 2D array I inputted:
[[0, 0, 2, 2, 3, 4], [0, 0, 2, 2, 3, 4]]
Code:
public static int[][] removeTrivialCases(int[][] startingSums) {
int[][] correctedSums = startingSums;
int counter = 0;
int numRows = correctedSums[0].length;
int numCols = correctedSums[1].length;
boolean zeroesExist = true;
boolean valueEqualsDimension = true;
boolean trivialCasesRemain = true;
while(trivialCasesRemain) {
for (int i = 0; i < correctedSums.length; i++) {
for (int j = 0; j < correctedSums[i].length; j++) {
if (correctedSums[i][j] == 0) {
trivialCasesRemain = true;
correctedSums[i] = ArrayUtils.removeElement(correctedSums[i], j);
}
for (int h = 0; h < correctedSums[i].length; h++) {
if (correctedSums[i][h] == 0) {
zeroesExist = true;
}
}
}
}
for (int i = 0; i < correctedSums[0].length; i++) {
if (correctedSums[0][i] == numCols) {
trivialCasesRemain = true;
correctedSums[0] = ArrayUtils.removeElement(correctedSums[0], i);
for (int j = 0; j < correctedSums[0].length; j++) {
correctedSums[0][j]--;
}
valueEqualsDimension = false;
for (int h = 0; h < correctedSums[0].length; h++) {
if (correctedSums[0][h] == numCols) {
valueEqualsDimension = true;
}
}
}
}
for (int i = 0; i < correctedSums[1].length; i++) {
if (correctedSums[1][i] == numRows) {
trivialCasesRemain = true;
correctedSums[1] = ArrayUtils.removeElement(correctedSums[1], i);
for (int j = 0; j < correctedSums[1].length; j++) {
correctedSums[1][j]--;
}
}
valueEqualsDimension = false;
for (int h = 0; h < correctedSums[1].length; i++) {
if (correctedSums[1][h] == numRows) {
valueEqualsDimension = true;
}
}
}
if (!zeroesExist || !valueEqualsDimension) {
trivialCasesRemain = false;
}
}
return correctedSums;
}
Regarding,
but the code gets stuck in a loop and I don't think it's doing what it's supposed to do.
Here:
for (int h = 0; h < correctedSums[1].length; i++) {
This loop will never end since h never changes within the loop. It should be:
for (int h = 0; h < correctedSums[1].length; h++) {
If you ran the code in a debugger, or used println's, you'd know what loop the code is stuck in, and this would allow you to inspect it immediately and correct it.

copy element of array

I can't figure out why isn't the code copying the unique elements to another array. Here is my code. I though that the == is to copy the element, but I got an error, so I used the = instead.
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] B = new int[15];
B[2] = 2;
B[3] = 3;
B[4] = 4;
B[5] = 5;
B[6] = 6;
B[7] = 7;
B[8] = 8;
B[9] = 9;
B[10] = 10;
int[] check = new int[B.length];
for (int i = 0; i < B.length; i++) {
for (int x = 0; x < check.length; x++) {
if (B[i] != check[x]) {
check[x] = B[i];
}
}
}
for (int i = 0; i < check.length; i++) {
System.out.println(check[i]);
}
}
You're looping over everything twice, when it should just be once.
Currently it looks like this:
for (int i = 0; i < B.length; i++) {
for (int x = 0; x < B.length; x++) {
if (B[i] != check[x]) {
check[x] = B[i];
}
}
}
This means that when i = 0 , then x=0, 1, 2, 3, 4, etc.. . Then when i = 1, x=0,1,2,3.... , etc.
So the last run will be i=14, where B[i] = 0.
So for every check[x], it won't be equal to 0.
What you want to do is handle it in a line. So instead of 2 variables i and x you can just use i and the outer loop, like this. This means that you're only comparing B[1] to check[1] and B[2] to check[2], and so on.
Like this:
for (int i = 0; i < B.length; i++) {
if (B[i] != check[i]) {
check[i] = B[i];
}
}
== is for test of equalation,= is for assignment,
by the way ,use System.arraycopy(xxx) to copy arrays.
public int[] findUnique(int[] data) {
int[] unique = new int[data.length];
int x = 0;
for (int i = 0; i < data.length; i++) {
boolean uni = true;
for (int j = i + 1; j < data.length; j++) {
if (data[i] == data[j]) {
uni = false;
break;
}
}
if (uni) {
unique[x++] = data[i];
}
}
return unique;
}
System.arrayCopy() is much faster

Series of nested loops without recursion

In Java, I have the following general code for integer d equal to 2, 3, 4, ..., dmax - up to a maximum number dmax : d < dmax (so this code is repeated for every value of d in that range):
// d is the number of wrapper loops
int[] ls = new int[d];
...
// let ls array be filled with some arbitrary positive numbers here
...
// first wrapper loop
for (int i1 = 0; i1 < ls[0]; i1++) {
...
// last wrapper loop
for (int id = 0; id < ls[d - 1]; id++) {
// internal loop
for (int j = id + 1; j < ls[d - 1]; j++) {
myCode();
}
}
...
}
In case of d = 3 it looks like:
int ls = new int[3];
ls[0] = 5; ls[1] = 7; ls[2] = 5;
for (int i1 = 0; i1 < ls[0]; i1++) {
for (int i2 = 0; i2 < ls[1]; i2++) {
for (int i3 = 0; i3 < ls[2]; i3++) {
for (int j = i3 + 1; j < ls[2]; j++) {
myCode();
}
}
}
}
I want to gather all that repeated code into a single generalized one. For that purpose I can use the while loop and recursion like below:
int d = 2, dmax = 10;
while (d < dmax) {
// in algorithm ls is pre-filled, here its length is shown for clearance
int[] ls = new int[d];
for (int i = 0; i < ls[0]; i++) {
doRecursiveLoop(1, d, -1, ls);
}
d++;
}
doRecursiveLoop(int c, int d, int index, int[] ls) {
if (c < d) {
for (int i = 0; i < ls[c]; i++) {
// only on the last call we give the correct index, otherwise -1
if (c == d - 1) index = i;
doRecursiveLoop(c + 1, d, index, ls);
}
} else {
for (int j = index + 1; j < ls[d - 1]; j++) {
myCode();
}
}
}
Can anybody shed some light as to how I would approach this problem of dynamically occurred nested loops without recursion?
You effectively have tail recursion here. Any tail-recursive function can trivially be converted to an iterative function using a loop.
For example:
void foo() {
// ... Stuff ...
if (someCondition) {
foo();
} else {
bar();
}
}
becomes:
void foo() {
while (someCondition) {
// ... Stuff ...
}
bar();
}

Categories

Resources