find largest most frequent element - java

I have an ArrayList in Java with values of
4, 4, 3, 3, 5, 6
and I need to find the most frequent value. If multiple values have the same number of occurrences, return the largest one.
So in the example above, I need to return the value 4.
private int getFrequentNumber(ArrayList<Integer> arr){
int popular = arr.get(0);
int count = 1;
int tempcount = 0;
int temp = 0;
for(int i = 0; i < arr.size(); i++) {
temp = arr.get(i);
tempcount = 0;
for(int j = 1; j < arr.size(); j++) {
if(temp == arr.get(j))
tempcount++;
}
if (tempcount > count) {
popular = temp;
count = tempcount;
}
}
return popular;
}
Right now I have this code so it returns the most frequent number but I need help returning the largest most frequent number.

Step1: QuickSort on ArrayList<Integer> arr;
Step2: Iteration on ArrayList<Integer> arr as you have done.

Using a stream on the list, you can group entries on their frequency (counting collector), then find the max frequency. The comparator below is just comparing keys (actual entries) when frequencies are equal (for finding your highest value...
List<Integer> arr = Arrays.asList(4, 4, 3, 3, 5, 6);
Entry<Integer, Long> maxEntry = arr.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.max(
(e1, e2) ->
e1.getValue() == e2.getValue()
?
Long.compare(e1.getKey(), e2.getKey())
:
Long.compare(e1.getValue(), e2.getValue())
)
.get();
System.out.println(String.format("Most frequent key: %s. Frequency: %s",
maxEntry.getKey(), maxEntry.getValue()));
The output of this is
Most frequent key: 4. Frequency: 2

You can create an array store the frequencies of these numbers. After calculating all frequencies, return the largest most frequent number based on this array.
private static int getFrequentNumber(ArrayList<Integer> arr){
int tempcount = 0;
int temp = 0;
int[] frequency = new int[arr.size()];
for(int i = 0; i < arr.size(); i++) {
temp = arr.get(i);
tempcount = 0;
for(int j = 0; j < arr.size(); j++) {
if(temp == arr.get(j))
tempcount++;
}
frequency[i] = tempcount;
}
int maxIndex = 0;
for (int i = 0; i < frequency.length; i++) {
if (frequency[i] >= frequency[maxIndex] && arr.get(i) > arr.get(maxIndex)) {
maxIndex = i;
}
}
return arr.get(maxIndex);
}

One straightforward approach uses a map to keep track of frequencies:
Map<Integer, Integer> freq = new HashMap<>();
int maxCnt = 0;
int maxNum = 0;
for (int num : arr) {
int cnt = freq.get(num) == null ? 1 : freq.get(num) + 1;
if (cnt > maxCnt || (cnt == maxCnt && num > maxNum)) {
maxCnt = cnt;
maxNum = num;
}
freq.put(num, cnt);
}
if (arr.size() > 0) {
System.out.println("The number " + maxNum + " occurred " + maxCnt + " times.");
}
else {
System.out.println("There were no numbers available.");
}
Demo

public int getPopularElement(ArrayList<Integer> arr) {
int count = 1, tempCount;
int popular = arr.get(0);
int temp = 0;
for (int i = 0; i < (arr.size()- 1); i++) {
temp = a.get(i);
tempCount = 0;
for (int j = 1; j < arr.length; j++) {
if (temp == arr.get(j))
tempCount++;
}
if (tempCount >= count && temp>popular ) {
popular = temp;
count = tempCount;
}
if (tempCount > count) {
popular = temp;
count = tempCount;
}
}
return popular;
}
second way is to sort data as saied by #triffic but it is slower (still in same order i think?)
you should just sort array then all is ok
Collections.sort(arr);
your code
private int getFrequentNumber(ArrayList<Integer> arr) {
Collections.sort(arr);
int popular = arr.get(0);
int count = 1;
int tempCount ;
int temp ;
for (int i = 0; i < arr.size(); i++) {
temp = arr.get(i);
tempCount = 0;
for (int j = 1; j < arr.size(); j++) {
if (temp == arr.get(j))
tempCount++;
}
if (tempCount > count) {
popular = temp;
count = tempCount;
}
}
return popular;
}

Those who don't want to reinvent the bicycle might use Guava library with MultiSet collection which holds the elements (integers in our case) and their frequency.
Multiset<Integer> myMultiset = HashMultiset.create(listOfElements);
// Returns a copy of multiset as an ImmutableMultiset whose iteration order is highest frequency first
ImmutableMultiset<Integer> integersOrderedByFrequency = Multisets.copyHighestCountFirst(myMultiset);
int intWithHighestFrequency = integersOrderedByFrequency.iterator().next();
int highestFrequency = myMultiset.count(intWithHighestFrequency);
// Now we should find the largest Integer among those with the highest frequency
OptionalInt maxValueOpt = myMultiset.entrySet().stream()
.filter(entry -> entry.getCount() == highestFrequency)
.mapToInt(Multiset.Entry::getElement)
.max();
System.out.println(maxValueOpt.getAsInt());
Or similar solution:
Multiset<Integer> myMultiset = HashMultiset.create(listOfElements);
Optional<Integer> result = myMultiset.entrySet().stream()
.sorted((a, b) -> {
// If count is higher for the first element - rank it higher in the list
if (a.getCount() > b.getCount()) {
return -1;
// If count is lower for the first element - rank it lower in the list
} else if (a.getCount() < b.getCount()) {
return 1;
//If element counts are the same - the element with the higher value will be ranked higher
} else {
return b.getElement() - a.getElement();
}
})
.map(Multiset.Entry::getElement)
.findFirst();
System.out.println(result.get());

Related

Find the most common value from a 2D integer array

I am looking for the most common value from the 2D array and how many times it occurs. I tried this solution but it's not working. I tried searching but not able to find a proper example. Please help me solve this problem.
Here is my code:
private void commonElevation(int[][] data) {
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
if (i + 1 < data.length) {
if (data[i][j] == data[i + 1][j]) {
System.out.println(data[i][j] + " = " + data[i + 1][j]);
}
}
}
}
}
You could use the Stream API:
int[][] data = {{1, 2, 3}, {2, 2, 2}, {4, 5, 6}};
Map<Integer, Long> counts = Arrays.stream(data).flatMapToInt(Arrays::stream).boxed()
.collect(groupingBy(Function.identity(), counting()));
Optional<Map.Entry<Integer, Long>> max = counts.entrySet().stream().max(Comparator.comparing(Map.Entry::getValue));
max.ifPresent(System.out::println);
Output
2=4
Given the new constraints a brute-force approach will work:
// find the maximum
int value = 0, max = Integer.MIN_VALUE;
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
// search for counts
int currentCount = 0;
for (int k = 0; k < data.length; k++) {
for (int l = 0; l < data[k].length; l++) {
if(data[k][l] == data[i][j]) {
currentCount++;
}
}
}
if (currentCount > max) {
value = data[i][j];
max = currentCount;
}
}
}
System.out.println(value + "=" + max);
Output
2=4
Basically iter over all values and count the appearances of each of those values. This approach (brute-force) is very inefficient.
One possibility would be to use a hash map to keep track of the values along with the number of times each occurs:
private void commonElevation(int[][] data) {
Map<Integer, Integer> counts = new HashMap<>();
for (int i=0; i < data.length; i++) {
for (int j=0; j < data[i].length; j++) {
int count = counts.get(data[i][j]) == null ? 0 : counts.get(data[i][j]);
counts.put(data[i][j], ++count);
}
}
int frequent = Integer.MIN_VALUE;
for (Integer value : counts.values()) {
if (value > frequent) frequent = value;
}
System.out.println("most frequent value is: " + frequent);
}

How to find max duplicate number count in given array using for loop

input: arr[]={4,3,6,6,4,8,1,9,3,6,7,8,6}
output: 6-count (4)
public static int countmaxDuplicate(int arr[]) {
int maxcount = 0;
int count = 0;
for (int i = 0; i < arr.length - 1; i++) {
for (int j = i + 1; j < arr.length - 1; j++) {
if (arr[i] == arr[j]) {
count++;
}
if (count > maxcount) {
count = maxcount;
}
}
}
return maxcount;
}
this code i am trying to implement to get max duplicate count but not able to get solution please suggest me how get output using for loop
There are few issues in your code
for (int j = i + 1; j < arr.length; j++) {
}
And
if (count > maxcount) {
maxcount = count;
}
Plus, you need to reinitialise count in every stage.
Full version:
public static int countmaxDuplicate(int arr[]) {
int maxcount = 0;
for (int i = 0; i < arr.length - 1; i++) {
int count = 1;
for (int j = i + 1; j < arr.length; j++) {
if (arr[i] == arr[j]) {
count++;
}
}
maxcount = Integer.max(maxcount, count);
}
return maxcount;
}
You can also add a boolean array check to avoid duplicating work
public static int countmaxDuplicate(int arr[]) {
int maxcount = 0;
boolean[]check = new boolean[arr.length];
for (int i = 0; i < arr.length - 1; i++) {
if(check[i]){
continue;
}
int count = 1;
for (int j = i + 1; j < arr.length; j++) {
if (arr[i] == arr[j]) {
check[j] = true;
count++;
}
}
maxcount = Integer.max(maxcount, count);
}
return maxcount;
}
Or even consider to use a HahsMap so this will have O(n) time complexity
HashMap<Integer, Integer> count = new HashMap();
for(int i : arr){
count.put(i, count.getOrDefault(count, 0) + 1);
}
int maxCount;
for(int i : count.values()){
maxCount = Integer.max(maxCount, i);
}
return maxCount;
In inner for loop, you are not inspecting last element every time. So change the for loop as:
for (int j = i + 1; j < arr.length ; j++) {
//your logic
}
Also other mistakes are you've to initialize count to 1 initially and also you need to reset count. Also your assignment is not right. You are maintaining maxcount as your final answer, so you need to update it instead of count. So following will work perfectly.
public static int countmaxDuplicate(int arr[]) {
int maxcount = 1;
for (int i = 0; i < arr.length - 1; i++) {
int count = 1;
for (int j = i + 1; j < arr.length; j++) {
if (arr[i] == arr[j]) {
count++;
}
}
if (count > maxcount) {
maxcount= count;
}
}
return maxcount;
}
Just gonna post it here, I don't like for loops.
int[] arr = {4, 3, 6, 6, 4, 8, 1, 9, 3, 6, 7, 8, 6};
Map<Integer, Long> map = Arrays.stream(arr)
.boxed()
.collect(Collectors.groupingBy(
Function.identity(), Collectors.counting()
));
Map.Entry<Integer, Long> max = Collections.max(
map.entrySet(), Map.Entry.comparingByValue()
);
System.out.println(max.getKey());
First you group them all by their count (maybe you need more than element with max count in the future? who knows), then you select max entry and print the key from that.

How to find number of tuples whose sum is equal or less than a given number?

I'm designing an algorithm to find the number of tuples whose sum is equal or less than a given number. I know other ways of solving it using LinkedList, so, not looking for that solution. I just want to traverse through the array and count the possible matches that satisfy the relation. I come up so far,
public static int numberOfPairs(int[] a, int k ){
int len = a.length;
if (len == 0){
return -1;
}
Arrays.sort(a);
int count = 0, left = 0, right = len -1;
while( left < right ){
if ( a[left] + a[right] <= k ){
// System.out.println(a[left] + "\t" + a[right]);
count++;
/*may be the same numbers will also satisfy the relation*/
if ( a[left] + a[left+1] <= k) {
count ++;
// System.out.println(a[left] + "\t"+a[left+1]);
}
/*now, use iteration to traverse the same elements*/
while (a[left] == a[left+1] && left < len-1 ){
left++;
}
/*may be the same numbers will also satisfy the relation*/
if ( a[right] + a[right-1] <= k) {
count ++;
// System.out.println(a[right] +"\t"+ a[right-1]);
}
/*now, use iteration to traverse
the same elements*/
while ( a[right] == a[right-1] && right >1 ){
right-- ;
}
}
// traverse through the array
left++;
right--;
}
return count;
}
This is not providing the correct solution, say, if I pass array and number as following,
int [] arr = { 3, 3, -1, 4, 2,5, 5, 1};
System.out.println(numberOfPairs(arr, 8));
The correct solution will be 15 pairs as following,
{
{-1,1}, {-1,2} , {3,-1}, {-1,4 }, {-1,5},
{2,1},{3,1 },{4,1}, { 5,1},
{3,2 },{4,2}, {2,5 },
{3,4 } , {3,5 },
{3,3}
}
How can I improve my code ? thanks.
Note: the other way I solve it using LinkedList is as following,
public static int numberOfPairs10(int[] arr, int sum){
/*1.can be the same values of i
2. can be the same valus of j for the same i*/
List<Integer> li = new ArrayList<Integer>();
List<Integer> lj;
int count = 0;
for ( int i =0; i < arr.length -1 ; i++){
if (li.contains(arr[i]) )
continue;
lj = new ArrayList<Integer>();
for (int j = i+1; j < arr.length; j++){
if (lj.contains(arr[j]))
continue;
// if ( arr[i]+ arr[j] <= sum){
if ( arr[i]+ arr[j] == sum){
count++;
lj.add(arr[j]);
}
}
li.add(arr[i]);
}
return count;
}
This is tested with just
int [] arr = { 3, 3, -1, 4, 2,5, 5, 1};
numberOfPairs(arr, 8);
and here is codes
public static int numberOfPairs(int[] a, int k ) {
int len = a.length;
int counter = 0;
boolean isCheckedLeft = false;
boolean isCheckedRight = false;
int i, j, h;
Arrays.sort(a);
for (i = 0; i < len; i++) {
isCheckedLeft = false;
for (j = i - 1; j >= 0; j--) {
if (a[i] == a[j]) {
isCheckedLeft = true;
break;
}
}
if (isCheckedLeft) {
continue;
}
for (j = i + 1; j < len; j++) {
isCheckedRight = false;
for (h = j - 1; h > i; h--) {
if (a[j] == a[h]) {
isCheckedRight = true;
break;
}
}
if (isCheckedRight) {
continue;
}
System.out.print("("+a[i]+", "+a[j]+") ");
if (a[i] + a[j] <= k) {
counter++;
}
}
}
return counter;
}
If you are not too worried about performance then you could just find all unique combinations and then filter according to your condition. For example, using Java 8 streams:
public int numberOfPairs(int[] values, int maxVal) {
return IntStream.range(0, values.length)
.flatMap(i1 -> IntStream.range(i1 + 1, values.length)
.map(i2 -> Arrays.asList(values[i1], values[i2])))
.distinct().filter(l -> l.stream().sum() <= maxVal).count();
}

How do I find the median of an unsorted array of integers in Java?

I have to find the sum of the elements before and after the median, that are close as possible. For example:
Input: {4,5,99,-1,5,6}
Output: 3 (element with index 3) //we start counting from 1
public int median(int[] array) {
int index = 0;
int minSum;
int sum = 0;
int leftSum = 0;
int rightSum = 0;
int[] subtraction = new int[array.length];
for (int i = 1; i < array.length; i++) {
sum = array[i] + sum;
}
rightSum = sum;
subtraction[0] = rightSum - leftSum;
for (int i = 1; i < array.length; i++) {
leftSum = leftSum + array[i - 1];
rightSum = sum - array[i];
if (leftSum > rightSum) {
subtraction[i] = leftSum - rightSum;
} else {
subtraction[i] = rightSum - leftSum;
}
}
minSum = subtraction[0];
for (int i = 1; i < subtraction.length; i++) {
if (subtraction[i] < minSum) {
minSum = subtraction[i];
index = i;
}
}
return index + 1;
}
I know i don't have to look for the minimum value but i can't find another way.My question is how to i find the closest numbers?
OUTPUT:
median is: 5 at index: 3
public class Hello {
static int[] integerArray = {4,5,99,-1,5,6};
public static void main(String[] args){
List<Integer> sortedArray = new ArrayList<Integer>();
//fill up a Collection (ArrayList<Integer>) with your array values
for(int integer : integerArray){
sortedArray.add(integer);
}
//sort the collection
Collections.sort(sortedArray);
//get the index of the median (middle item of a sorted list)
int index = sortedArray.size() / 2;
//print the median and it's index
System.out.println("median is: " + sortedArray.get(index) + " at index: " + index);
}
}

check number of maximum and minimum element in a array

I am trying to check whether the given array has equal number of maximum and minimum array element. If their number are equal should return 1 else return 0. But instead of which return always zero.
Could you please help me?
public class MaxMinEqual {
public static void main(String[] args) {
System.out.println(MaxMinEqual.ismaxminequal(new int[]{11, 4, 9, 11, 8, 5, 4, 10}));
System.out.println(MaxMinEqual.ismaxminequal(new int[]{11, 11, 4, 9, 11, 8, 5, 4, 10}));
}
public static int ismaxminequal(int[] a) {
int maxcount = 0;
int mincount = 0;
int largest = a[0];
for (int i = 0; i < a.length; i++) {
if (a[i] > largest) {
largest = a[i];
}
if (a[i] == largest) {
maxcount = maxcount + 1;
}
}
int smallest = a[0];
for (int j = 0; j < a.length; j++) {
if (a[j] < smallest) {
smallest = a[j];
}
if (a[j] == smallest) {
mincount = mincount + 1;
}
}
if (maxcount == mincount) {
return 1;
} else {
return 0;
}
}
}
You did not reset maxcount and mincount when you find a greater or smaller value.
public static boolean isMaxMinEqual(int[] a) {
int maxcount, mincount = 0;
int largest, smallest = a[0];
for (int i = 0: a) {
if (i > largest) {
largest = i;
maxcount = 0;
}
if (i == largest) {
maxcount++;
}
if (i < smallest) {
smallest = i;
mincount = 0;
}
if (i == smallest) {
mincount++;
}
}
return maxcount == mincount;
}
Not sure if you're supposed to learn this without Data Structures, but why not take advantage of an Algorithm Efficiency Technique called presorting.
We could do something like this:
public static int ismaxminequal(int[] a) {
Arrays.sort(a);
This puts the smallest elements at the 'head' of the array and the largest elements at the 'tail'.
So, now, we must iterate from both ends to see how many of each are available (max and min).
int num_min = 1;
int num_max = 1;
int cur_value = 0; //holds a reference for comparison
cur_value = a[0];
for (int i = 1; i < a.length; i++) {
if (a[I] == cur_value)
num_min++;
else
break;
}
cur_value = a[a.length - 1];
for (int i = a.length - 1; i > 0; I--) {
if (a[I] == cur_value)
num_min++;
else
break;
}
if (num_max == num_min) {
return 1;
} else {
return 0;
}
}
}
Java 8 way. Very readable and with big arrays can be quicker that O(N) single thread implementation.
public boolean isMaxMinEqual(int[] a) {
int max = Arrays.stream(a).parallel().max().getAsInt();
int min = Arrays.stream(a).parallel().min().getAsInt();
long maxCount = Arrays.stream(a).parallel().filter(s -> s == max).count();
long minCount = Arrays.stream(a).parallel().filter(s -> s == min).count();
return maxCount == minCount;
}

Categories