Need to get the Least Frequent element of a 2D array - java

int curr = 0;
int cnt;
String element = values[0][0];
int numberRepeats = 0;//cnt-counter,what's the element ,how many times it's repeated
for (int i = 0; i < values.length; i++) {
for (int j = 0; j < values[i].length; j++) {//those two for's are for the current element
cnt = 0;//counter is nullified
for (int j2 = i; j2 < values.length; j2++) {
for (int k = 0; k < values[j2].length; k++) {//and those two are the compared element
if (values[i][j] == values[j2][k]) {//if the current element is the same as the compared element,increase counter
cnt++;
}
}
if (cnt >numberRepeats) {//after the compared element is done comparing and the number of repeats of the current element is more then the lastly checked element
element = values[i][j];//we get the element ,and how many times it's repeated
numberRepeats = cnt;
}
}
}
}
System.out.println();
System.out.println("The most popular item is: "+element+". Number sold:"+numberRepeats);`
This is what I currently get:
houseShampoo meatPork dairyCream wheatBread wheatCrackers
houseShampoo houseShampoo houseDetergent meatPork dairyYogurt
meatLamb dairyMilk dairyCream meatPork houseShampoo
wheatCookies meatLamb dairyYogurt wheatCereal wheatBread
meatLamb dairyMilk wheatCookies wheatCrackers wheatPasta
The most popular item is: houseShampoo. Number sold:4
This is what I want to get:
The least popular item is: wheatPasta. Number sold:1
But I don't know how to change the condition in the if statement to give out the least frequent element instead of most popular

Since you want to find the minimum number of repeats, start of your initial value with the maximum value:
int numberRepeats = Integer.MAX_VALUE;
and when an item is found with a smaller number of repeats, replace it:
if (cnt < numberRepeats) {
element = values[i][j];
numberRepeats = cnt;
}
This should do the trick.

Hi I choosed different approach using Map I hope it helps :)
int dimension = 3;
int sold = 0;
String product = "";
Map<String,Integer> productsSoldAndCount = new HashMap<>();
String[][] elements = new String[3][3];
elements[0] = new String[]{"houseShampoo","meatpork","dairyCream"};
elements[1] = new String[]{"houseShampoo","bread","cookies"};
elements[2] = new String[]{"meatpork","meatpork","meatpork"};
for(var tmpArray : elements){
for(var tmpString : tmpArray){
if(!productsSoldAndCount.containsKey(tmpString)){
productsSoldAndCount.put(tmpString,1);
}else{
productsSoldAndCount.put(tmpString,productsSoldAndCount.get(tmpString) + 1);
}
}
}
for(var resultPair : productsSoldAndCount.entrySet()){
if(resultPair.getValue() > sold){
sold = resultPair.getValue();
product = resultPair.getKey();
}
}
System.out.println("The most popular item is: " + product + " Sold: " + sold);

Related

How do I remove the item with the highest value in an unsorted array?

So right now I am trying to code a function that will remove the highest value in an unsorted array.
Currently the code looks like this:
#Override
public void remove() throws QueueUnderflowException {
if (isEmpty()) {
throw new QueueUnderflowException();
} else {
int priority = 0;
for (int i = 1; i < tailIndex; i++) {
while (i > 0 && ((PriorityItem<T>) storage[i - 1]).getPriority() < priority)
storage[i] = storage[i + 1];
i = i - 1;
}
/*int max = array.get(0);
for (int i = 1; i < array.length; i++) {
if (array.get(i) > max) {
max = array.get(i);
}*/
}
tailIndex = tailIndex - 1;
}
Here I have my attempt at this:
int priority = 0;
for (int i = 1; i < tailIndex; i++) {
while (i > 0 && ((PriorityItem<T>) storage[i - 1]).getPriority() < priority)
storage[i] = storage[i + 1];
i = i - 1;
The program runs no bother but still deletes the first item in the array instead of the highest number. This code was given my my college lecturer for a different solution but unfortunately it doesn't work here.
Would this solution work with enough altercations? Or is there another solution I should try?
Thanks.
The code snippet in the question can be updated to below code, while keeping the same data structure i.e. queue and this updated code has 3 steps - finding the index of largest element, shifting the elements to overwrite the largest element and finally set the tailIndex to one less i.e. decrease the size of the queue.
#Override
public void remove() throws QueueUnderflowException {
if (isEmpty()) {
throw new QueueUnderflowException();
} else {
int priority = 0;
int largeIndex = 0;
for (int i = 0; i < tailIndex; i++) {
if (((PriorityItem<T>) storage[i]).getPriority() > priority) {
priority = ((PriorityItem<T>) storage[i]).getPriority();
largeIndex = i ;
}
}
for(int i = largeIndex; i < (tailIndex - 1) ; i++)
storage[i] = storage[i + 1];
}
tailIndex = tailIndex - 1;
}
Hope it helps.
Step 1
Find the highest index.
int[] array;
int highIndex = 0;
for (int i = 1; i < highIndex.size(); i++)
if (array[highIndex] < array[highIndex])
highIndex = i;
Step 2
Create new array with new int[array.size() - 1]
Step 3
Move all values of array into new array (except the highest one).
My hint: When its possible, then use a List. It reduces your complexity.
You can find the largest Number and it's index then copy each number to its preceding number. After that, you have two options:
Either add Length - 1 each time you iterate the array.
Or copy the previous array and don't include removed number in it.
Working Code:
import java.util.Arrays;
public class stackLargest
{
public static void main(String[] args)
{
int[] unsortedArray = {1,54,21,63,85,0,14,78,65,21,47,96,54,52};
int largestNumber = unsortedArray[0];
int removeIndex = 0;
// getting the largest number and its index
for(int i =0; i<unsortedArray.length;i++)
{
if(unsortedArray[i] > largestNumber)
{
largestNumber = unsortedArray[i];
removeIndex = i;
}
}
//removing the largest number
for(int i = removeIndex; i < unsortedArray.length -1; i++)
unsortedArray[i] = unsortedArray[i + 1];
// now you have two options either you can iterate one less than the array's size
// as we have deleted one element
// or you can copy the array to a new array and dont have to add " length - 1" when iterating through the array
// I am doing both at once, what you lke you can do
int[] removedArray = new int[unsortedArray.length-1];
for(int i =0; i<unsortedArray.length-1;i++)
{
System.out.printf(unsortedArray[i] + " ");
removedArray[i] = unsortedArray[i];
}
}
}
Note: Use List whenever possible, it will not only reduce complexity, but, comes with a very rich methods that will help you a big deal.

Array output repeating one more then it should

This code basically takes a string array goes through it one at a time and displays a tally of each elements occurrence.
problem is that element number 3 ("One") is repeated at the end and im not sure why, so the out put i would get is:
Current Output:
One 2
Two 1
Three 1
One 2
Code:
public static void main(String[] args) {
String [] myStrings = {"One", "Two", "Three", "One"};
StringCount(myStrings);
}
public static void StringCount(String [] Array)
{
int size = Array.length;
for (int i = 0; i < size; i++)
{
int count = 0;
String element = Array[i];
for (int j = 0; j < size; j++)
{
if (Array[j].equals(element)){
count ++;
}
}
System.out.println(Array[i] + " " + count);
}
}
Expected Output:
One 2
Two 1
Three 1
First, you get four printed lines because you call the output method inside a loop that runs exactly four times:
for (int i = 0; i < size; i++) // size is 4
{
...
System.out.println(Array[i] + " " + count);
}
As you want to count the occurrences of all distinct strings, you want to map those strings to their count. The problem is that you can't know the exact number of distinct strings beforehand. So you have to build up such a map and loop again over its elements (in a second step):
Map<String, Integer> counts = new HashMap<>();
/* setup map */
for (int i = 0; i < size; i++) {
String element = Array[i];
/* special case for having an element the first time: */
if (!counts.containsKey(element)) {
counts.put(element, Integer.valueOf(0));
}
/* increase the count for the element and store it back in map */
int oldCount = counts.get(element).intValue();
counts.put(element, Integer.valueOf(oldCount+1));
}
/* print out values */
for(String element : counts.keySet()) {
System.out.println(element + " " + counts.get(element));
}
Use a Set to avoid duplicates like below:
public static void StringCount(String [] Array)
{
int size = Array.length;
Set<String> existingElement = new HashSet<>();
for (int i = 0; i < size; i++)
{
int count = 0;
String element = Array[i];
for (int j = 0; j < size; j++)
{
if (Array[j].equals(element)){
count ++;
}
}
// This will print the result if and only if the element has not
// already been added into the Set
if (existingElement.add(Array[i])) {
System.out.println(Array[i] + " " + count);
}
}
}
Output:
One 2
Two 1
Three 1
Because you check every element and you have One two times, so it will be checked twice! you need to have a set of checked elements so when you check element you put it in set, and then before checking next element you check if it is in set, if it is, then skip it.

Getting the most "popular" number from array

I need for homework to get the most "popular" number in an array (the number in the highest frequency), and if there are several numbers with the same number of shows, get some number randomly.
After more then three hours of trying, and either searching the web, this is what I got:
public int getPopularNumber(){
int count = 1, tempCount;
int popular = array[0];
int temp = 0;
for ( int i = 0; i < (array.length - 1); i++ ){
if ( _buses[i] != null )
temp = array[i];
tempCount = 0;
for ( int j = 1; j < _buses.length; j++ ){
if ( array[j] != null && temp == array[j] )
tempCount++;
}
if ( tempCount > count ){
popular = temp;
count = tempCount;
}
}
return popular;
}
This code work, but don't take into account an important case- if there is more than one number with the same count of shows. Then it just get the first one.
for example: int[]a = {1, 2, 3, 4, 4, ,5 ,4 ,5 ,5}; The code will grab 4 since it shown first, and it's not random as it should be.
Another thing- since it's homework I can't use ArrayList/maps and stuff that we still didn't learn.
Any help would be appreciated.
Since they didn't give you any time complexity boundary, you can "brute force" the problem by scanning the the array N^2 times. (disclaimer, this is the most intuitive way of doing it, not the fastest or the most efficient in terms of memory and cpu).
Here is some psuedo-code:
Create another array with the same size as the original array, this will be the "occurrence array"
Zero its elements
For each index i in the original array, iterate the original array, and increment the element in the occurrence array at i each time the scan finds duplicates of the value stored in i in the original array.
Find the maximum in the occurrence array
Return the value stored in that index in the original array
This way you mimic the use of maps with just another array.
If you are not allowed to use collection then you can try below code :
public int getPopularNumber(){
int inputArr[] = {1, 2, 3, 4, 4, 5 ,4 ,5 ,5}; // given input array
int[] tempArr = new int[inputArr.length];
int[] maxValArr = new int[inputArr.length];
// tempArr will have number as index and count as no of occurrence
for( int i = 0 ; i < inputArr.length ; i++){
tempArr[inputArr[i]]++;
}
int maValue = 0;
// find out max count of occurrence (in this case 3 for value 4 and 5)
for( int j = 0 ; j < tempArr.length ; j++){
maValue = Math.max(maValue, tempArr[j]);
}
int l =0;
// maxValArr contains all value having maximum occurrence (in this case 4 and 5)
for( int k = 0 ; k < tempArr.length ; k++){
if(tempArr[k] == maValue){
maxValArr[l] = k;
l++;
}
}
return maxValArr[(int)(Math.random() * getArraySize(maxValArr))];
}
private int getArraySize(int[] arr) {
int size = 0;
for( int i =0; i < arr.length ; i++){
if(arr[i] == 0){
break;
}
size++;
}
return size;
}
that's hard as hell :D
After some trying, I guess I have it (If there will be 2 numbers with same frequency, it will return first found):
int mostPopNumber =0;
int tmpLastCount =0;
for (int i = 0; i < array.length-1; i++) {
int tmpActual = array[i];
int tmpCount=0;
for (int j = 0; j < array.length; j++) {
if(tmpActual == array[j]){
tmpCount++;
}
}
// >= for the last one
if(tmpCount > tmpLastCount){
tmpLastCount = tmpCount;
mostPopNumber = tmpActual;
}
}
return mostPopNumber;
--
Hah your code give me idea- you cant just remember last most popular number, btw I've found it solved there Find the most popular element in int[] array
:)
EDIT- after many, and many years :D, that works well :)
I've used 2D int and Integer array - you can also use just int array, but you will have to make more length array and copy actual values, Integer has default value null, so that's faster
Enjoy
public static void main(String[] args) {
//income array
int[] array= {1,1,1,1,50,10,20,20,2,2,2,2,20,20};
//associated unique numbers with frequency
int[][] uniQFreqArr = getUniqValues(array);
//print uniq numbers with it's frequency
for (int i = 0; i < uniQFreqArr.length; i++) {
System.out.println("Number: " + uniQFreqArr[i][0] + " found : " + uniQFreqArr[i][1]);
}
//get just most frequency founded numbers
int[][] maxFreqArray = getMaxFreqArray(uniQFreqArr);
//print just most frequency founded numbers
System.out.println("Most freq. values");
for (int i = 0; i < maxFreqArray.length; i++) {
System.out.println("Number: " + maxFreqArray[i][0] + " found : " + maxFreqArray[i][1]);
}
//get some of found values and print
int[] result = getRandomResult(maxFreqArray);
System.out.println("Found most frequency number: " + result[0] + " with count: " + result[1]);
}
//get associated array with unique numbers and it's frequency
static int[][] getUniqValues(int[] inArray){
//first time sort array
Arrays.sort(inArray);
//default value is null, not zero as in int (used bellow)
Integer[][] uniqArr = new Integer[inArray.length][2];
//counter and temp variable
int currUniqNumbers=1;
int actualNum = inArray[currUniqNumbers-1];
uniqArr[currUniqNumbers-1][0]=currUniqNumbers;
uniqArr[currUniqNumbers-1][1]=1;
for (int i = 1; i < inArray.length; i++) {
if(actualNum != inArray[i]){
uniqArr[currUniqNumbers][0]=inArray[i];
uniqArr[currUniqNumbers][1]=1;
actualNum = inArray[i];
currUniqNumbers++;
}else{
uniqArr[currUniqNumbers-1][1]++;
}
}
//get correctly lengthed array
int[][] ret = new int[currUniqNumbers][2];
for (int i = 0; i < uniqArr.length; i++) {
if(uniqArr[i][0] != null){
ret[i][0] = uniqArr[i][0];
ret[i][1] = uniqArr[i][1];
}else{
break;
}
}
return ret;
}
//found and return most frequency numbers
static int[][] getMaxFreqArray(int[][] inArray){
int maxFreq =0;
int foundedMaxValues = 0;
//filter- used sorted array, so you can decision about actual and next value from array
for (int i = 0; i < inArray.length; i++) {
if(inArray[i][1] > maxFreq){
maxFreq = inArray[i][1];
foundedMaxValues=1;
}else if(inArray[i][1] == maxFreq){
foundedMaxValues++;
}
}
//and again copy to correctly lengthed array
int[][] mostFreqArr = new int[foundedMaxValues][2];
int inArr= 0;
for (int i = 0; i < inArray.length; i++) {
if(inArray[i][1] == maxFreq){
mostFreqArr[inArr][0] = inArray[i][0];
mostFreqArr[inArr][1] = inArray[i][1];
inArr++;
}
}
return mostFreqArr;
}
//generate number from interval and get result value and it's frequency
static int[] getRandomResult(int[][] inArray){
int[]ret=new int[2];
int random = new Random().nextInt(inArray.length);
ret[0] = inArray[random][0];
ret[1] = inArray[random][1];
return ret;
}

Count the Number of Swaps in Selection Sort

I've read through all the discussions trying to find an answer but none of the answers have worked for me so I'm trying it this way.
public static int SelectionSort(long[] num)
{
int i, j, first;
long temp;
int swap = 0;
int pass = 0;
int count = 0;
boolean Mini = false;
for (i = num.length - 1; i > 0; i--)
{
for(int k = 0; k < num.length; k++)
{
System.out.println(" k = " + k
+ " \t X[i] = " + num[k] + " swap count: " + swap);
}
System.out.println("");
first = 0; //initialize to subscript of first element
for(j = 1; j <= i; j ++) //locate smallest element between positions 1 and i.
{
if(num[j] < num[first])
{
first = j;
//Mini = true;
}
}
//if(Mini){
// swap++;
//}
temp = num[first]; //swap smallest found with element in position i.
num[first] = num[i];
num[i] = temp;
}
return swap;
}
Using a simple array as my test case:
long[] X = {1, 4, 3, 2, 5};
The number of swaps should only equate to 1 because it's swapping the first and last elements only. However, it isn't working. While I know my if condition doesn't work, I can't think of what would. I can't seem to work the logic that it increments a swap when items are actually swapped.
Why not increment the counter when you actually perform a swap?
//swap smallest found with element in position i.
swap++
temp = num[first];
num[first] = num[i];
num[i] = temp;
EDIT:
Good point in the comment. The current code still performs a superfluous swap if the array is sorted (i.e., first and i are the same):
if (first != i) {
swap++
temp = num[first];
num[first] = num[i];
num[i] = temp;
}
With your implementation you will always have n swaps (where n is the number of elements in your array).
What I think you want is to only perform a swap when it actually makes a difference ... so when "first" and "i" have different values. Otherwise you switch the element with itself.
if (first != i) {
temp = num[first];
num[first] = num[i];
num[i] = temp;
swapp++;
}

SelectionSort and BubbleSort - how to count number of comparisons and number swapping?

First of all, I have seen a similar question relating to C++, but I didn't quite understand it - plus my question is about Java.
Basically I have coded two methods that can use SelectionSort and BubbleSort on an array parsed in. While I believe I have the methods working correctly (I have run tests and they all have sorted the numbers in ascending order), I am not sure if I am counting the number of comparisons and number swaps correctly. If someone is able to test my code below and offer some feedback, I will be very grateful.
Note: I can zip up my Java project files and send them to anyone if needed.
BubbleSort method:
public String bubbleSort(int[] numbers)
{
System.out.println("******|Bubble Sort|******");
StringBuilder originalArray = new StringBuilder();
for(int i = 0; i <= numbers.length - 1; i++)
{
originalArray.append(numbers[i] + " ");
}
System.out.println("Original array: " + originalArray);
int temp; // temporary variable
//Set boolean variable to true,
//to allow the first pass.
boolean pass = true;
int comparisons = 0;
int swaps = 0;
//While a pass can be made,
while(pass)
{
//Set the boolean value to false,
//indicating a number swap could
//be made.
pass = false;
for(int i = 0; i < numbers.length - 1; i++)
{
//increment the number of comparisons by 1.
comparisons++;
if(numbers[i] > numbers[i+1])
{
temp = numbers[i];
numbers[i] = numbers[i + 1];
numbers[i+1] = temp;
//increment the amount of swaps made by 1,
//to put numbers in correct order.
swaps++;
pass = true;
}
}
}
//Create a StringBuilder object - to hold
//the output of sorted numbers.
StringBuilder sb = new StringBuilder();
//Loop through the now sorted array - appending
//each subsequent number in the array to the
//StringBuilder object.
for(int i = 0; i < numbers.length; i++)
{
sb.append(numbers[i] + " ");
}
//Return the final results of the sorted array.
return "Sorted Array (asc): " + sb.toString() + "\nComparisons made: " + comparisons
+ "\nSwaps made: " + swaps;
}
SelectionSort method
public String selectionSort(int[] numbers)
{
System.out.println("******|Selection Sort|******");
StringBuilder originalArray = new StringBuilder();
int comparisons = 0;
int swaps = 0;
for(int i = 0; i <= numbers.length - 1; i++)
{
originalArray.append(numbers[i] + " ");
}
System.out.println("Original array: " + originalArray);
//Declare variable to hold first element
int first;
//declare temporary variable, to be used in
//swapping integers.
int temp;
for(int x = numbers.length - 1; x > 0; x--)
{
first = 0;
comparisons++;
for(int y = 1; y <= x; y++)
{
//comparisons++;
if(numbers[y] > numbers[first])
{
first = y;
//comparisons++;
swaps++;
}
temp = numbers[first];
numbers[first] = numbers[x];
numbers[x] = temp;
//swaps++;
}
}
//Create a StringBuilder object - to hold
//the output of sorted numbers.
StringBuilder sb = new StringBuilder();
//Loop through the now sorted array - appending
//each subsequent number in the array to the
//StringBuilder object.
for(int i = 0; i < numbers.length; i++)
{
sb.append(numbers[i] + " ");
}
//Return the final results of the sorted array.
return "Sorted Array (asc): " + sb.toString() + "\nComparisons made: " + comparisons
+ "\nSwaps made: " + swaps;
}
For BUBBLE SORT:
Key comparisons -> (n*(n-1))/2
Item assignments (swaps) -> 3*(n-1)
For SELECTION SORT:
Key comparisons -> (n*(n-1))/2 (same as bubble)
Item assignments (swaps) -> (n*(n-1))/4
(Note that n is the number of your array size)

Categories