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.
Related
I have a factorial function on my program that works fine until i try to execute the function deleteRepeated(), the console is telling me that the error is in the return of the factorial function, maybe it's being called by a single function too many times in a short period of time? I've been stuck for hours.
import java.util.Scanner;
public class ex9 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
}
int[] newArr = new int[n - repeated(arr)];
int[] finalArr = deleteRepeated(arr, newArr);
for (int a : finalArr) {
System.out.println(a);
}
}
public static long factorial(int n) {
if (n == 0)
return 1;
return (n * factorial(n - 1));
}
public static int repeated(int arr[]) {
int n = arr.length;
int mix = (int) (factorial(n) / (2 * factorial(n - 2)));
int i = 0;
int k = 0;
int rep = 0;
int a = -100;
while (i < mix) {
for (int j = k + 1; j < n; j++) {
if (arr[k] == arr[j] && a != j) {
a = j;
rep += 1;
}
i++;
}
k++;
}
return rep;
}
public static int[] deleteRepeated(int arr[], int newArr[]) {
int n = arr.length;
int rep = repeated(arr);
int i = 0;
int k = 0;
int a = -100;
while (i < newArr.length) {
for (int j = k + 1; j < n; j++) {
if (arr[k] == arr[j] && a != arr[k]) {
a = arr[j];
newArr[k] = arr[k];
}
i++;
}
k++;
}
rep = repeated(newArr);
if (rep > 0) {
int[] newArr2 = new int[newArr.length - rep];
deleteRepeated(newArr, newArr2);
}
return newArr;
}
}
Only thing i could do to avoid the error was stopping the function from executing :/, maybe it has to do with how i'm re-calling it at the end of each execution...? is what i did allowed?
So, deleteRepeated is all messed up. The issue is deleteRepeated does not actually remove duplicate elements, so the check for the base case of recursion always fails. I'm not sure why you're using recursion here anyway; if the while loop worked properly, it could remove all duplicates without need for recursion.
It appears that you copy-pasted the implementation of repeated into deleteRepeated, and you replaced the logic for handling repeated elements with logic that handles non-repeated elements.
Here is how I would implement the method:
public static int deleteRepeated(int arr[], int newArr[]) {
int n = 0;
for(int i = 0; i < arr.length; i++) {
boolean unique = true;
for(int j = 0; j < n; j++)
unique = unique && newArr[j] != arr[i];
if(unique)
newArr[n++] = arr[i];
if(n >= newArr.length) break;
}
return n;
}
I am new to programming and want to establish good habits, could I have done this in another and faster way?
int[] getNegatives(int[][] m) {
int countNegatives = 0; // used to create length of array
for (int i = 0; i < m.length; i++) {
for (int j = 0; j < m[i].length; j++) {
if (m[i][j] < 0) {
countNegatives += 1;
}
}
}
int[] arr = new int[countNegatives];
int increase = 0; // used to increment index of array
for (int i = 0; i < m.length; i++) {
for (int j = 0; j < m[i].length; j++) {
if (m[i][j] < 0) {
arr[increase] = m[i][j];
increase += 1;
}
}
}
return arr;
}
You could use an ArrayList instead of an array. That way you don't need to know the exact number before creating the array, and you can skip the counting.
You would need to use Integer though since you cant put primitives in Java Collections.
List<Integer> getNegatives(int[][] m) {
List<Integer> negatives = new ArrayList<>();
for (int[] ints : m) {
for (int anInt : ints) {
if (anInt < 0) {
negatives.add(anInt);
}
}
}
return negatives;
}
If you really don't want to use Collections you can still improve your code by using the enhanced for loop
int[] getNegatives(int[][] m) {
int countNegatives = 0;
for (int[] ints : m) {
for (int anInt : ints) {
if (anInt < 0) {
countNegatives += 1;
}
}
}
int[] arr = new int[countNegatives];
int increase = 0;
for (int[] ints : m) {
for (int anInt : ints) {
if (anInt < 0) {
arr[increase++] = anInt;
}
}
}
return arr;
}
i try to make method that can be find the profit for some input and calculation.
but i think there a problem in a length of Array or somewhat i don't know.
also i wanna try it by using recursive but how to implement ?
please i need your helps ^_^
thanks
public class MatlabLAB2 {
public static void main(String[] args) {
int capital = 100;
int nDay = 7;
int[] buyP = {5, 20, 7, 10, 4, 80, 1};
int[] sellP = {25, 50, 100, 3, 10, 2, 95};
findProfit(capital, nDay, buyP, sellP);
}
public static void findProfit(int capital, int NDay, int[] BuyingP, int[] SellingP) {
int[] Array = new int[NDay];
int Profit = 0;
for (int i = 0; i <= BuyingP.length; i++) {
for (int j = i; j <= SellingP.length; j++) {
for (int k = 0; k <= NDay-1; k++) {
Array[k] = (capital / BuyingP[i]) * SellingP[j];
}
Profit = findMaxOfArray(Array);
}
}
System.out.println(Profit);
}
public static int findMaxOfArray(int[] a) {
int max = 0;
for (int i = 0; i <= a.length-1; i++) {
if (a[i] >= max) {
max = a[i];
}
}
return max;
}
}
the result:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 7
at matlab.lab.pkg2.MatlabLAB2.findProfit(MatlabLAB2.java:24)
at matlab.lab.pkg2.MatlabLAB2.main(MatlabLAB2.java:11)
Java Result: 1
You are iterating the loop till
(int i = 0; i <= BuyingP.length; i++)
it should be iterated till
(int i = 0; i < BuyingP.length; i++)
same with j loop
You have two options to fix this.
1.
public static void findProfit(int capital, int NDay, int[] BuyingP, int[] SellingP) {
int[] Array = new int[NDay];
int Profit = 0;
for (int i = 0; i <= BuyingP.length-1; i++) {
for (int j = i; j <= SellingP.length-1; j++) {
for (int k = 0; k <= NDay-1; k++) {
Array[k] = (capital / BuyingP[i]) * SellingP[j];
}
Profit = findMaxOfArray(Array);
}
}
System.out.println(Profit);
}
2.
public static void findProfit(int capital, int NDay, int[] BuyingP, int[] SellingP) {
int[] Array = new int[NDay];
int Profit = 0;
for (int i = 0; i < BuyingP.length; i++) {
for (int j = i; j < SellingP.length; j++) {
for (int k = 0; k <= NDay-1; k++) {
Array[k] = (capital / BuyingP[i]) * SellingP[j];
}
Profit = findMaxOfArray(Array);
}
}
System.out.println(Profit);
}
Because in your code your array goes from 0 to 6 and you are trying to take array[7] which is out of your array's bound.
I am trying to create a method that calculates (N choose R) using dynamic programming but I get an array out of bounds exception:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 7
at BinomialCoefficients.method5(BinomialCoefficients.java:127)
at BinomialCoefficients.main(BinomialCoefficients.java:50)
I am using a 2 dimensional array. Here is my code,
protected static long method5(long lN, long lR)
{
long lArray[][] = new long[(int) (lN+1)][(int) (lR+1)];
for(int i = 0; i <= lN; i++)
{
lArray[i][0] = 1;
}
for(int i = 0; i <= lN; i++)
{
lArray[i][i] = 1;
}
for(int i = 0; i <= lN; i++)
{
for(int j = i; j <= i; j++)
{
lArray[i][j] = lArray[i-1][j-1] + lArray[i-1][j];
}
}
/*for(int i = 0; i <= lN; i++)
{
for(int j = 0; j <= i; j++)
{
System.out.print(String.format("%5d", lArray[i][j]));
}
System.out.println();
}*/
return lArray[(int) lN][(int) lR];
}
Can somebody tell me what is wrong with it?
This code looks suspicious
for(int i = 0; i <= lN; i++)
{
lArray[i][i] = 1;
}
considering lArray was initialized using two potentially different values:
long lArray[][] = new long[(int) (lN+1)][(int) (lR+1)];
I think you should have an inner loop here, such as:
for(int i = 0; i <= lN; i++) {
for (int j=0; j<=lR; j++) {
lArray[i][j] = 1;
}
}
I see the indexing error has already been corrected. But will point out that you're allocating a square array when you only need one row. You're also not taking advantage of symmetry. Consider something like this:
public class Binomial {
public static long n_choose_r(int n, int r) {
r = Math.min(r, n - r);
long [] a = new long[r + 1];
a[0] = 1;
for (int i = 1; i <= n; ++i) {
if (i <= r) {
a[i] = 1;
}
for (int j = Math.min(r, i - 1); j > 0; --j) {
a[j] += a[j - 1];
}
}
return a[r];
}
public static void main(String [] args) {
System.out.println(n_choose_r(6, 4));
}
}
I have a method which counts how many sums of 3 elements,which are equal to 0, does the array contains. I need help finding the way to stop counting the same triplets in the loop. For instance, 1 + 3 - 4 = 0, but also 3 - 4 +1 = 0.Here is the method:
private static int counter(int A[])
{
int sum;
int e = A.length;
int count = 0;
for (int i=0; i<e; i++)
{
for (int j=i+1; j<e; j++)
{
sum=A[i]+A[j];
if(binarySearch(A,sum))
{
count++;
}
}
}
return count;
edit: I have to use the Binary Search (the array is sorted).
Here is the binarySearch code:
private static boolean binarySearch(int A[],int y)
{
y=-y;
int max = A.length-1;
int min = 0;
int mid;
while (max>=min)
{
mid = (max+min)/2;
if (y==A[mid])
{
return true;
}
if (y<A[mid])
{
max=mid-1;
}
else
{
min=mid+1;
}
}
return false;
You can avoid counting different triplets by making one assumption that we need to look for the triplets (x,y,z) with x < y < z and A[x] + A[y] + A[z] == 0.
So what you need to do is to modify the binarySearch function to return the number of index that greater than y and has A[z] == -(A[x] + A[y])
private static int binarySearch(int A[],int y, int index)
{
y=-y;
int max = A.length-1;
int min = index + 1;
int mid;
int start = A.length;
int end = 0;
while (max>=min)
{
mid = (max+min)/2;
if (y==A[mid])
{
start = Math.min(start, mid);
max = mid - 1;
} else
if (y<A[mid])
{
max=mid-1;
}
else
{
min=mid+1;
}
}
int max = A.length - 1;
int min = index + 1;
while (max>=min)
{
mid = (max+min)/2;
if (y==A[mid])
{
end = Math.max(end, mid);
min= mid + 1;
} else if (y<A[mid])
{
max=mid-1;
}
else
{
min=mid+1;
}
}
if(start <= end)
return end - start + 1;
return 0;
}
So the new function binarySearch will return the total number of index that greater than index and has value equals to y.
So the rest of the job is to count the answer
private static int counter(int A[])
{
int sum;
int e = A.length;
int count = 0;
for (int i=0; i<e; i++)
{
for (int j=i+1; j<e; j++)
{
sum=A[i]+A[j];
count += binarySearch(A,sum, j);
}
}
return count;
}
Notice how I used two binary search to find the starting and the ending index of all values greater than y!
private static int counter(int A[]) {
int e = A.length;
int count = 0;
for (int i = 0; i < e; i++) {
for (int j = 1; (j < e - 1) && (i != j); j++) {
for (int k = 2; (k < e - 2) && (j != k); k++) {
if (A[i] + A[j] + A[k] == 0) {
count++;
}
}
}
}
return count;
}
private static int counter(int ints[]) {
int count = 0;
for (int i = 0; i < ints.length; i++) {
for (int j = 0; j < ints.length; j++) {
if (i == j) {
// cannot sum with itself.
continue;
}
for (int k = 0; k < ints.length; k++) {
if (k == j) {
// cannot sum with itself.
continue;
}
if ((ints[i] + ints[j] + ints[k]) == 0) {
count++;
}
}
}
}
return count;
}
To solve problem with binary search
Your code was almost correct. all you needed to do was just to replace
if (sum == binarySearch(A,sum)) {
with this
if (binarySearch(A,sum)) {
I am assuming that your binarySearch(A, sum) method will return true if it will found sum in A array else false
private static int counter(int A[]) {
int sum;
int e = A.length;
int count = 0;
for (int i=0; i<e; i++) {
for (int j=i+1; j<e; j++) {
sum=A[i]+A[j];
if (binarySearch(A,sum)) {
count++;
}
}
}
return count;
}
Here is my solution assuming the array is sorted and there are no repeated elements, I used the binary search function you provided. Could the input array contain repeated elements? Could you provide some test cases?
In order to not counting the same triplets in the loop, we should have a way of inspecting repeated elements, the main idea that I used here is to have a list of int[] arrays saving the sorted integers of {A[i],A[j],-sum}.Then in each iteration I compare new A[i] and A[j] to the records in the list, thus eliminating repeated ones.
private static int counter(int A[]){
int sum;
int e = A.length;
int count = 0;
List<int[]> elements = new ArrayList<>();
boolean mark = false;
for (int i=0; i<e; i++)
{
for (int j=i+1; j<e; j++)
{
sum=A[i]+A[j];
if (-sum == binarySearch(A,sum)){
int[] sort = {A[i],A[j],-sum};
if(-sum == A[i] || -sum == A[j]){
continue;
}else{
Arrays.sort(sort);
//System.out.println("sort" + sort[0] + " " + sort[1]+ " " + sort[2]);
for (int[] element : elements) {
if((element[0] == sort[0] && element[1] == sort[1]) && element[2] == sort[2])
mark = true;
}
if(mark){
mark = false;
continue;
}else{
count++;
elements.add(sort);
//System.out.println("Else sort" + sort[0] + " " + sort[1]);
}
}
}
}
}
return count;
}
you can use a assisted Array,stored the flag that indicate if the element is used;
Here is the code:
private static int counter(int A[])
{
int sum;
int e = A.length;
int count = 0;
// assisted flag array
List<Boolean> flagList = new ArrayList<Boolean>(e);
for (int k = 0; k < e; k++) {
flagList.add(k, false);// initialization
}
for (int i=0; i<e; i++)
{
for (int j=i+1; j<e; j++)
{
sum=A[i]+A[j];
// if element used, no count
if(binarySearch(A,sum)&& !flagList.get(i)&& !flagList.get(j))
{
count++;
flagList.set(i, true);
flagList.set(j, true);
}
}
}
return count;