I've got to find the mode of an array. I am a bit embarrassed to admit that I've been stuck on this for a day. I think I've overthought it a bit - my method just gets longer and longer. The real issue that I keep running into is that when there isn't one mode (two numbers appear with the same frequency) I need to return Double.NaN.
Here's what I've tried:
private double[] data = {1, 1, 2, 2, 2, 3, 4, 5, 5, 5, 5, 5, 6, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9};
if(data.length != 0){
double maxValue = -1;
int maxCount = 0;
for(int i = 0; i < data.length; i++) {
int count = 0;
for(int j = 0; j < data.length; j++) {
if(data[j] == data[i]) {
count++;
}
}
if(count > maxCount) {
maxValue = (int) data[i];
maxCount = count;
}
}
return maxValue;
}else{
return Double.NaN;
}
This actually returns the mode, but it can't deal with two modes. Here's my most recent attempt, but it's only half complete:
private double[] data = {1, 1, 2, 2, 2, 3, 4, 5, 5, 5, 5, 5, 6, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9};
public void mode(){
int[] frequency = new int[data.length];
double[] vals = new double[data.length];
for(int i = 0; i < data.length; i++){
frequency[i] = occursNumberOfTimes(data[i]);
}
boolean uniform = false;
for(int g = 0; g < frequency.length && !uniform; g++){
if(frequency[0] != frequency[g]){
uniform = false;
}
int[] arr = new int[frequency.length-1];
for(int j = 1; j < frequency.length; j++){
if(frequency[j] > frequency[j-1]){
int mod = 0;
for(int k = 0; k < arr.length; k++){
if(k == j){
mod += 1;
arr[k] = frequency[k + mod];
}else{
arr[k] = frequency[k + mod];
}
}
}
}
frequency = arr;
}
}
private int occursNumberOfTimes(double value){
int count = 0;
for(int i = 0; i < data.length; i++){
if(data[i] == value){
count++;
}
}
return count;
}
I sorta got lost in the second try, I just can't sort out how to deal with multiple modes. I've written out my thoughts, but I just don't know how. I can't use anything from the Arrays class, which is why I'm lost.
Does it have to be efficient? If not:
double maxValue = -1.0d;
int maxCount = 0;
for (int i = 0; i < data.length; ++i) {
double currentValue = data[i];
int currentCount = 1;
for (int j = i + 1; j < data.length; ++j) {
if (Math.abs(data[j] - currentValue) < epsilon) {
++currentCount;
}
}
if (currentCount > maxCount) {
maxCount = currentCount;
maxValue = currentValue;
} else if (currentCount == maxCount) {
maxValue = Double.NaN;
}
}
System.out.println("mode: " + maxValue);
You could track the two most common elements as was suggested in the comments, but another approach is to keep a boolean flag that indicates if the current most common element is unique. Then:
For each array element e, obtain its count as you're currently doing.
If that count is greater than the current max, set the the most common element (seen so far) to e and set the "unique" flag to true.
Otherwise, if that count is equal to the current max, set the "unique" flag to false.
At the end, just return the mode if "unique" is true, otherwise return NaN.
Here's my long, dumb solution. It works! It's a very roundabout way of getting the mode, but I'm really happy it works. I used the advice I got from some comments and looked at it differently. It was a frustrating few hours, but here it is:
public double mode2(){
if(data.length != 0){
int[] counts = new int[data.length];
double[] vals = new double[data.length];
for(int l = 0; l < data.length; l++){
counts[l] = 1;
}
for(int i = 0; i < data.length; i++){
for(int j = 0; j < data.length; j++){
if((data[i] == data[j]) && (i != j)){
vals[i] = data[i];
counts[i] += 1;
}
}
}
for(int i = 0; i < data.length; i++){
for(int j = 0; j < data.length; j++){
if((vals[i] == vals[j]) && (i != j)){
vals[i] = 0;
counts[i] = 0;
}
}
}
int counter = 0;
for(int k = 0; k < data.length; k++){
if(counts[k] != 0){
counts[counter] = counts[k];
vals[counter] = vals[k];
counter++;
}
}
int[] compactCounts = new int[counter];
double[] compactVals = new double[counter];
for(int k = 0; k < counter; k++){
if(counts[k] != 0){
compactCounts[k] = counts[k];
compactVals[k] = vals[k];
}else{
break;
}
}
for(int g = 1; g < compactVals.length; g++){
if(compactCounts[g] > compactCounts[g-1]){
compactCounts[g-1] = 0;
compactVals[g-1] = 0;
}
}
for(int g = 0; g < compactVals.length-1; g++){
if(compactCounts[g] > compactCounts[g+1]){
compactCounts[g+1] = 0;
compactVals[g+1] = 0;
}
}
int counterTwo = 0;
for(int k = 0; k < compactCounts.length; k++){
if(compactCounts[k] != 0){
compactCounts[counterTwo] = compactCounts[k];
compactVals[counterTwo] = vals[k];
counterTwo++;
}
}
int[] compactCountsTwo = new int[counterTwo];
double[] compactValsTwo = new double[counterTwo];
for(int k = 0; k < counterTwo; k++){
if(counts[k] != 0){
compactCountsTwo[k] = compactCounts[k];
compactValsTwo[k] = compactVals[k];
}else{
break;
}
}
//now populated compactTwos
//We're now setting some lesser values to 0
for(int g = 1; g < compactValsTwo.length; g++){
if(compactCountsTwo[g] > compactCountsTwo[g-1]){
compactCountsTwo[g-1] = 0;
compactValsTwo[g-1] = 0;
}
}
//now setting other lesser values to 0
for(int g = 0; g < compactValsTwo.length-1; g++){
if(compactCountsTwo[g] > compactCountsTwo[g+1]){
compactCountsTwo[g+1] = 0;
compactValsTwo[g+1] = 0;
}
}
//calling methods to shorten our arrays by dropping indexes populated by zeroes
compactValsTwo = doubleTruncator(compactValsTwo);
compactCountsTwo = intTruncator(compactCountsTwo);
//now setting some lesser values to 0
for(int g = 1; g < compactValsTwo.length; g++){
if(compactCountsTwo[g] > compactCountsTwo[g-1]){
compactCountsTwo[g-1] = 0;
compactValsTwo[g-1] = 0;
}
}
//now setting other lesser values to 0
for(int g = 0; g < compactValsTwo.length-1; g++){
if(compactCountsTwo[g] > compactCountsTwo[g+1]){
compactCountsTwo[g+1] = 0;
compactValsTwo[g+1] = 0;
}
}
//calling methods to shorten our arrays by dropping indexes populated by zeroes
compactValsTwo = doubleTruncator(compactValsTwo);
compactCountsTwo = intTruncator(compactCountsTwo);
if(compactValsTwo.length > 1){
return Double.NaN;
}else{
return compactValsTwo[0];
}
}else{
System.out.println("ISSUE");
return Double.NaN;
}
}
public double[] doubleTruncator(double[] a){
int counter = 0;
for(int k = 0; k < a.length; k++){
if(a[k] != 0){
a[counter] = a[k];
counter++;
}
}
double[] b = new double[counter];
for(int i= 0; i < counter; i++){
if(a[i] != 0){
b[i] = a[i];
}else{
break;
}
}
return b;
}
public int[] intTruncator(int[] a){
int counter = 0;
for(int k = 0; k < a.length; k++){
if(a[k] != 0){
a[counter] = a[k];
counter++;
}
}
int[] b = new int[counter];
for(int i= 0; i < counter; i++){
if(a[i] != 0){
b[i] = a[i];
}else{
break;
}
}
return b;
}
Big thanks to everybody who helped. I know it's not great (certainly not as good as the answer from #Perdi Estaquel), but I'm happy that I managed to do it.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed last month.
Improve this question
I have been working on this java code for the doomsday-fuel problem which deals with the absorbing markov chains. It has passed every test except for test four. Is there any particular type of input I may have missed while testing my code? I have only about 12 hours left. I have tested four one dimensional arrays and am curious as to if this test failure is somehow a precision error or something else.
Context:
Making fuel for the LAMBCHOP's reactor core is a tricky process because of the exotic matter involved. It starts as raw ore, then during processing, begins randomly changing between forms, eventually reaching a stable form. There may be multiple stable forms that a sample could ultimately reach, not all of which are useful as fuel.
Commander Lambda has tasked you to help the scientists increase fuel creation efficiency by predicting the end state of a given ore sample. You have carefully studied the different structures that the ore can take and which transitions it undergoes. It appears that, while random, the probability of each structure transforming is fixed. That is, each time the ore is in 1 state, it has the same probabilities of entering the next state (which might be the same state). You have recorded the observed transitions in a matrix. The others in the lab have hypothesized more exotic forms that the ore can become, but you haven't seen all of them.
Write a function solution(m) that takes an array of array of nonnegative ints representing how many times that state has gone to the next state and return an array of ints for each terminal state giving the exact probabilities of each terminal state, represented as the numerator for each state, then the denominator for all of them at the end and in simplest form. The matrix is at most 10 by 10. It is guaranteed that no matter which state the ore is in, there is a path from that state to a terminal state. That is, the processing will always eventually end in a stable state. The ore starts in state 0. The denominator will fit within a signed 32-bit integer during the calculation, as long as the fraction is simplified regularly.
public static int[] returnFractionPair(double x) {
double tolerance = 1.0E-14;//Handles the extent of precision used
double numerator=1;//Kept as one because initially the decimal may be greater than zero
double numeratorStorage=0;
double denominator=0;
double denominatorStorage=1;//prevents division by zero
double decimal = x;
double comparison = 0;
do {
double flooredDecimal = (double)(int)decimal;//Floors decimal
double aux = numerator;//Sets auxilary to be the numerator
numerator =(flooredDecimal*numerator)+numeratorStorage;
numeratorStorage = aux;
aux = denominator;
denominator = (flooredDecimal*denominator)+denominatorStorage;
denominatorStorage = aux;
decimal = 1/(decimal-flooredDecimal);
comparison = x-(numerator/denominator);
} while( returnAbs(comparison) > (x*tolerance) );//Tests if the difference between the initial decimal and this new numerator/denominator is greater than that of x multiplied by the level of tolerance it has
int[] res = new int[]{(int)numerator, (int)denominator};
return res;
}
public static double returnAbs(double value){
if(value < 0){
value *= -1;
}
return value;
}
public static int getLCD(int[][] fractions){
int num = 0;
int den = 1;
int lcd = 1;
for(int i = 0; i < fractions.length; i++){
lcd *= fractions[i][den];
}
for(int i = 2; i < lcd; i++){
boolean foundLeastCommon = true;
for(int j = 0; j < fractions.length; j++){
if( (double)( i%fractions[j][den] ) != 0){
foundLeastCommon = false;
}
}
if(foundLeastCommon == true){
lcd = i;
return lcd;
}
}
return lcd;
}
public static double[] returnRowSums(int[][] matrix){
//Assume all values in matrix are positive
double[] sumsOfEachRow = new double[matrix.length];
for(int i = 0; i < matrix.length; i++){
for(int j = 0; j < matrix.length; j++){
sumsOfEachRow[i] += matrix[i][j];
}
}
return sumsOfEachRow;
}
public static double returnMatrixCellSum(double[] row, double[] column){//Assume row size == column size.
if(row.length != column.length){
return 0;
}
double sum = 0;
for(int i = 0; i < row.length; i++){
sum += (column[i] * row[i]);
}
return sum;
}
public static int[] returnRearrangedIndices(double[] sumsOfEachRow){
int[] indicesOfRearrangedMatrix = new int[sumsOfEachRow.length];
int indicesIndex = 0;
for(int i = 0; i < sumsOfEachRow.length; i++){
if(sumsOfEachRow[i] <= 1){
indicesOfRearrangedMatrix[indicesIndex] = i;
indicesIndex++;
}//TerminalStates first
}
for(int i = 0; i < sumsOfEachRow.length; i++){
if(sumsOfEachRow[i] > 1){
indicesOfRearrangedMatrix[indicesIndex] = i;
indicesIndex++;
}
}
return indicesOfRearrangedMatrix;
}
public static double[][] subtractMatrix(double[][] matrix1, double[][] matrix2){//assumes matrices are of same dimensions
double[][] matrix3 = new double[matrix1.length][matrix1.length];
for(int i = 0; i < matrix1.length;i++){
for(int j = 0; j < matrix1[i].length; j++){
matrix3[i][j] = matrix1[i][j] - matrix2[i][j];
}
}
return matrix3;
}
public static double[][] rotateMatrix(double[][] matrix){
double[][] rotatedMatrix = new double[matrix[0].length][matrix.length];
for(int i = 0; i < rotatedMatrix.length;i++){
for(int j = 0; j < rotatedMatrix[0].length; j++){
rotatedMatrix[i][j] = matrix[j][i];
}
}
return rotatedMatrix;
}
public static double[][] getRemainingValues(double[][] matrix, int rowIgnored, int columnIgnored){
double[][] newMatrix = new double[matrix.length-1][matrix.length-1];
int iC = 0;
int iR = 0;
for(int k = 0; k < matrix.length; k++){
if(k != rowIgnored){
iR = 0;
for(int j = 0; j < matrix[k].length;j++){
if(j != columnIgnored){
newMatrix[iC][iR] = matrix[k][j];
iR++;
}
}
iC++;
}
}
return newMatrix;
}
public static double getDeterminant(double[][] matrix){
//uses top rows only
double determinant = 0;
if(matrix.length == 1 && matrix[0].length == 1){
return matrix[0][0];
}
boolean negative = false;
double[][] newMatrix = new double[matrix.length-1][matrix.length-1];
for(int i = 0; i < matrix.length; i++){
newMatrix = getRemainingValues(matrix, 0, i);
if(negative == false){
determinant += matrix[0][i]*getDeterminant(newMatrix);
negative = true;
}else{
determinant -= matrix[0][i]*getDeterminant(newMatrix);
negative = false;
}
//System.out.println(determinant);
}
return determinant;
}
public static double[][] getMinorMatrix(double[][] matrix){
double[][] newMatrix = new double[matrix.length][matrix.length];
double[][] remainderMatrix;
if(matrix.length-1 != 0){
remainderMatrix = new double[matrix.length-1][matrix.length-1];
}else{
remainderMatrix = new double[matrix.length][matrix.length];
}
for(int i = 0; i < newMatrix.length;i++){
for(int j = 0; j < newMatrix.length;j++){
remainderMatrix = getRemainingValues(matrix, i, j);
newMatrix[i][j] = getDeterminant(remainderMatrix) + 0.0;//Prevent -0.0 float values
}
}
return newMatrix;
}
public static double[][] divideMatrixByScalar(double[][] matrix, double scalar){
double[][] newMatrix = new double[matrix.length][matrix[0].length];
newMatrix = matrix;
for(int i = 0; i < matrix.length; i++){
for(int j = 0; j < matrix[i].length;j++){
newMatrix[i][j] /= scalar;
}
}
return newMatrix;
}
public static double[][] invertMatrix(double[][] matrix){
double[][] minorMatrix = new double[matrix.length][matrix.length];
if(minorMatrix.length == 2){
minorMatrix = matrix;
double temp = minorMatrix[0][0];
minorMatrix[0][0] = minorMatrix[1][1];
minorMatrix[1][1] = temp;
minorMatrix[0][1] *= -1;
minorMatrix[0][1] += 0;
minorMatrix[1][0] *= -1;
minorMatrix[1][0] += 0;
for(int i = 0; i < minorMatrix.length; i++){
for(int j = 0; j < minorMatrix[i].length; j++){
System.out.print(minorMatrix[i][j] + " ");
}
System.out.print("\n");
}
}else{
minorMatrix = getMinorMatrix(matrix);
System.out.println("Getting minorMatrix");
for(int i = 0; i < minorMatrix.length; i++){
for(int j = 0; j < minorMatrix[i].length; j++){
System.out.print(minorMatrix[i][j] + " ");
}
System.out.print("\n");
}
boolean isNegative = false;
System.out.println("Getting adjoint of minorMatrix");//Not doing things correctly
for(int i = 0; i < minorMatrix.length;i++){
for(int j = 0; j < minorMatrix[i].length;j++){
if(isNegative == true){
minorMatrix[i][j] *= -1;
minorMatrix[i][j] += 0;
isNegative = false;
}else{
isNegative = true;
}
System.out.print(minorMatrix[i][j] + " ");
}
if(minorMatrix[i].length % 2 == 0){
if(isNegative == true){
isNegative = false;
}else{
isNegative = true;
}
}
System.out.print("\n");
}
minorMatrix = rotateMatrix(minorMatrix);//rotates the minorMatrix
}
double determinant = getDeterminant(matrix);
System.out.println(determinant);
if(determinant != 0){
minorMatrix = divideMatrixByScalar(minorMatrix, determinant);
System.out.println("Result");
for(int i = 0; i < minorMatrix.length; i++){
for(int j = 0; j < minorMatrix[i].length; j++){
System.out.print(minorMatrix[i][j] + " ");
}
System.out.print("\n");
}
return minorMatrix;//Inverse is good
}else{
return matrix;
}
}
public static double[][] returnUnabsorbedToUnabsorbed(double[][] matrix, int terminalStates){//Assumes matrix layers go from absorbed to unabsorbed
double[][] unabsorbedToUnabsorbed = new double[matrix.length-terminalStates][matrix.length-terminalStates];
int uIndex = 0;
int uuIndex = 0;
for(int i = terminalStates; i < matrix.length;i++){
uuIndex = 0;
for(int j = terminalStates; j < matrix.length;j++){
unabsorbedToUnabsorbed[uIndex][uuIndex] = matrix[i][j];
uuIndex++;
}
uIndex++;
}
return unabsorbedToUnabsorbed;
}
public static double[][] returnUnabsorbedToAbsorbed(double[][] matrix, int terminalStates){//Assumes matrix layers go from absorbed to unabsorbed
double[][] unabsorbedToAbsorbed = new double[matrix.length-terminalStates][terminalStates];
int uIndex = 0;
int uuIndex = 0;
for(int i = terminalStates; i < matrix.length;i++){
uuIndex = 0;
for(int j = 0; j < terminalStates;j++){
unabsorbedToAbsorbed[uIndex][uuIndex] = matrix[i][j];
uuIndex++;
}
uIndex++;
}
return unabsorbedToAbsorbed;
}
public static double[][] getFundamental(double[][] matrix){
double[][] modifiedMatrix = new double[matrix.length][matrix[0].length];
modifiedMatrix = matrix;
double[][] identity = new double[matrix.length][matrix.length];
for(int i = 0; i < identity.length; i++){
for(int j = 0;j < identity[i].length;j++){
if(i == j){
identity[i][j] = 1;
}else{
identity[i][j] = 0;
}
}
}
modifiedMatrix = subtractMatrix(identity, modifiedMatrix);//Modified matrix is returning properly
/*System.out.println("Getting matrix to be inverted");
for(int i = 0; i < modifiedMatrix.length; i++){
for(int j = 0; j < modifiedMatrix[i].length; j++){
System.out.print(modifiedMatrix[i][j] + " ");
}
System.out.print("\n");
}*/
modifiedMatrix = invertMatrix(modifiedMatrix);//Problem here(?)
return modifiedMatrix;
}
public static double[][] multiplyMatrix(double[][] matrix1, double[][] matrix2){//Assume all rows are equal.
double[][] result = new double[matrix1.length][matrix2[0].length];
double[][] rotatedM2 = new double[matrix2[0].length][matrix2.length];
rotatedM2 = rotateMatrix(matrix2);
for(int i = 0; i < result.length;i++){
for(int j = 0; j < result[i].length; j++){
result[i][j] = returnMatrixCellSum(matrix1[i], rotatedM2[j]);
//RotateMatrix does not increase matrix sums by how it should be
}
}
return result;
}
public static int[] algorithm(int[][] matrix, int startingPoint){
if(matrix.length == 0){
return new int[]{0, 1};
}
if(matrix.length == 1){
int[] ans = new int[matrix.length+1];
for(int i = 0; i < ans.length;i++){
ans[i] = 1;
}
for(int i = 0; i < ans.length; i++){
System.out.println(ans[i]);
}
return ans;
}
double[] sumsOfEachRow = new double[matrix.length];
sumsOfEachRow = returnRowSums(matrix);
double[][] probMatrix = new double[matrix.length][matrix.length];
int terminalStates = 0;//Number of terminal states
for(int i = 0; i < probMatrix.length; i++){
for(int j = 0; j < probMatrix[i].length; j++){
if(sumsOfEachRow[i] != 0){
probMatrix[i][j] = (double)matrix[i][j];
probMatrix[i][j] /= sumsOfEachRow[i];
}else{
probMatrix[i][j] = 0;
}
}
}
boolean startingIsTerminal = false;
for(int i = 0; i < probMatrix.length;i++){
boolean foundOne = false;
for(int j = 0; j < probMatrix[i].length;j++){
if(probMatrix[i][j] == 1 && i == j){
terminalStates++;
foundOne = true;
if(i == startingPoint){
startingIsTerminal = true;
}
}
}
if(foundOne == false){
if(sumsOfEachRow[i] == 0){
terminalStates++;
}
}
}
if( (sumsOfEachRow[startingPoint] == 0) || startingIsTerminal == true){
int[] ans = new int[terminalStates+1];
for(int i = 0; i < terminalStates;i++){
if(i != startingPoint){
ans[i] = 0;
}else{
ans[i] = 1;
}
}
ans[terminalStates] = 1;
for(int i = 0; i < ans.length; i++){
System.out.println(ans[i]);
}
return ans;
}
int[] indicesOfRearrangedMatrix = new int[probMatrix.length];
indicesOfRearrangedMatrix = returnRearrangedIndices(sumsOfEachRow);
double[][] rearranged = new double[probMatrix.length][probMatrix[0].length];
for(int i = 0; i < matrix.length; i++){
for(int j = 0; j < matrix[i].length; j++){
rearranged[i][j] = probMatrix[indicesOfRearrangedMatrix[i]][indicesOfRearrangedMatrix[j]];
System.out.print(rearranged[i][j] + " ");
}
System.out.print("\n");
}//Get rearranged matrix divided
System.out.println("Matrix rearranged");
double[][] unabsorbedToUnabsorbed = new double[probMatrix.length-terminalStates][probMatrix.length-terminalStates];
unabsorbedToUnabsorbed = returnUnabsorbedToUnabsorbed(rearranged, terminalStates);//Get Unabsorbed Matrix
for(int i = 0; i < unabsorbedToUnabsorbed.length; i++){
for(int j = 0; j < unabsorbedToUnabsorbed[i].length; j++){
System.out.print(unabsorbedToUnabsorbed[i][j] + " ");
}
System.out.print("\n");
}
System.out.println("unabsorbedToUnabsorbed");
double[][] unabsorbedToAbsorbed = new double[probMatrix.length-terminalStates][terminalStates];
unabsorbedToAbsorbed = returnUnabsorbedToAbsorbed(rearranged, terminalStates);
for(int i = 0; i < unabsorbedToAbsorbed.length; i++){
for(int j = 0; j < unabsorbedToAbsorbed[i].length; j++){
System.out.print(unabsorbedToAbsorbed[i][j] + " ");
}
System.out.print("\n");
}
System.out.println("unabsorbedToAbsorbed");
double[][] fundamental = new double[unabsorbedToUnabsorbed.length][unabsorbedToUnabsorbed.length];
fundamental = getFundamental(unabsorbedToUnabsorbed);//Gets fundamental
double[][] probResult = multiplyMatrix(fundamental, unabsorbedToAbsorbed);
System.out.println("ProbResult got");
for(int i = 0; i < probResult.length; i++){
for(int j = 0; j < probResult[i].length; j++){
System.out.print(probResult[i][j] + " ");
}
System.out.print("\n");
}
int[][] fractionPairs = new int[terminalStates][2];
for(int i = 0; i < probResult[startingPoint].length; i++){
fractionPairs[i] = returnFractionPair(probResult[startingPoint][i]);
}
int lcd = getLCD(fractionPairs);
int[] ans = new int[terminalStates+1];
int num = 0;
int den = 1;
for(int i = 0; i < fractionPairs.length;++i){
int newNumerator = (lcd/fractionPairs[i][den]) * fractionPairs[i][num];
ans[i] = newNumerator;
}
ans[ans.length-1] = lcd;
for(int i = 0; i < ans.length; i++){
System.out.println(ans[i]);
}
return ans;
}
public static int[] solution(int[][] m) {
return algorithm(m, 0);
}
}
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
public static int[] sortByScores(double[] scores){
double temp;
int i,j;
int[] scoreIndex = new int[3];
for (i = 0; i <= scores.length; i++)
for (j = i+1; j < scores.length; j++) {
if (scores[i] < scores[j]) {
temp = scores[i];
scores[i] = scores[j];
scores[j] = temp;
scoreIndex[i] = j;
scoreIndex[j] = i;
}
}
return scoreIndex;
}
This method sort the "scores" array in descending order and store which index key is changed from the array in "scoreIndex" array.
This method doesn't work if I enter 1,3,2,4
Is they any better way to store the index key changes log?
Example if 1 enter:
1
2
4
3
Sorted will be:
4
3
2
1
And sortIndex should be:
Key Value
0 3
1 2
2 0
3 1
You can actually get the array containing the proper ordering of the elements at certain indices without sorting this array, for example, by doing this:
for(int i = 0; i < scores.length; i++) {
for(int j = i; j < scores.length; j++) {
if(scores[scoreIndex[j]] > scores[scoreIndex[i]]) {
int temp = scoreIndex[j];
scoreIndex[j] = scoreIndex[i];
scoreIndex[i] = temp;
}
}
}
In short, at the beginning of this method we are creating an array which contains the current order of indices in your scores[] array, this is 0, 1, ..., scores.length-1. Then, we perform an operation similar to standard sorting but not in terms of the scores[] array, but in terms of the scoreIndex[] array.
Once we have this array sorted, we can create another array and and place its elements at the appropriate position by:
double[] copy = new double[scores.length];
for(int k = 0; k < scores.length; k++) {
copy[k] = scores[k];
}
for(int n = 0; n < scores.length; n++) {
scores[n] = copy[scoreIndex[n]];
System.out.println(scores[n]);
}
So, to put it together:
public static int[] sort(double[] scores) {
int[] scoreIndex = new int[scores.length];
for(int i = 0; i < scores.length; i++) {
scoreIndex[i] = i;
}
for(int i = 0; i < scores.length; i++) {
for(int j = i; j < scores.length; j++) {
if(scores[scoreIndex[j]] > scores[scoreIndex[i]]) {
int temp = scoreIndex[j];
scoreIndex[j] = scoreIndex[i];
scoreIndex[i] = temp;
}
}
}
double[] copy = new double[scores.length];
for(int k = 0; k < scores.length; k++) {
copy[k] = scores[k];
}
for(int n = 0; n < scores.length; n++) {
scores[n] = copy[scoreIndex[n]];
System.out.println(scores[n]);
}
return scoreIndex;
}
First, you should declare scoreIndex as:
int[] scoreIndex = new int[scores.length];
And, in every outer loop, you find the max element, set it as scores[i], at the same time, set scoreIndex[indexOfMaxElement] = i. To achieve this, you also need a copy of the origial array.
Here is the complete code:
public class Main {
public static void main(String[] args) {
double[] array = new double[] {1, 2, 4, 3};
int[] result = sortByScores(array);
for (int i = 0; i < result.length; i++) {
System.out.println(result[i]);
}
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
public static int[] sortByScores(double[] scores){
int[] scoreIndex = new int[scores.length];
double[] copy = new double[scores.length];
boolean[] records = new boolean[scores.length];
// copy
for (int i = 0; i < scores.length; i++) {
copy[i] = scores[i];
}
for (int i = 0; i < scores.length; i++) {
// find the max element
for (int j = i + 1; j < scores.length; j++) {
if (scores[i] < scores[j]) {
double temp = scores[i];
scores[i] = scores[j];
scores[j] = temp;
}
}
// set the max element's index
for (int k = 0; k < copy.length; k++) {
if (copy[k] == scores[i] && !records[k]) {
scoreIndex[k] = i;
records[k] = true;
break;
}
}
}
return scoreIndex;
}
}
My one worked too but #user6690200 your one is way better.
public static int[] sortByScores(double[] scores){
double temp,temp2;
int i,j;
int[] scoreIndex = new int[3];
double[] scoreBackup = new double[scores.length];
double[] scoreBackup2 = new double[scores.length];
// Generating unique score, beacuse student can have same score
for(i=0;i<scores.length;i++)
scoreBackup[i] = scores[i]*(i+1);
for(i=0;i<scores.length;i++)
scoreBackup2[i] = scores[i]*(i+1);
for (i = 0; i < scores.length; i++) {
for (j = i+1; j < scores.length; j++) {
if (scores[i] < scores[j]) {
temp = scores[i];
temp2 = scoreBackup2[i];
scores[i] = scores[j];
scoreBackup2[i] = scoreBackup2[j];
scores[j] = temp;
scoreBackup2[j] = temp2;
}
}
}
for(i = 0; i<scores.length;i++)
for(j=0;j<scores.length;j++)
if(scoreBackup[i] == scoreBackup2[j])
scoreIndex[i] = j;
return scoreIndex;
}
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.
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