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);
}
Related
Is there some elegant ways to remove duplicated list (list with same values) from a list of list?
I tried with Set<List<Integer>> but it's not working, it still shows the duplicated lists. It seems that Set only checks the object reference.
the example code:
int[] nums = {-1, 0, 1, 2, -1, -4};
Set<List<Integer>> set = new HashSet<>();
for (int i = 0; i < nums.length; i++) {
for (int j = i + 1; j < nums.length; j++) {
for (int k = j + 1; k < nums.length; k++) {
if (nums[i] + nums[j] + nums[k] == 0) {
set.add(Arrays.asList(nums[i], nums[j], nums[k]));
}
}
}
}
then the set will contain 3 elements but two of them have the same values.
A repair:
record Triple(int x, int y, int z) {};
int[] nums = {-1, 0, 1, 2, -1, -4};
Set<Triple> set = new HashSet<>();
for (int i = 0; i < nums.length; i++) {
for (int j = i + 1; j < nums.length; j++) {
for (int k = j + 1; k < nums.length; k++) {
if (nums[i] + nums[j] + nums[k] == 0) {
set.add(new Triple(nums[i], nums[j], nums[k]));
}
}
}
}
However the algorithm is suboptimal O(n³).
record Triple(int x, int y, int z) {};
int[] nums = {-1, 0, 1, 2, -1, -4};
Arrays.sort(nums);
Set<Triple> set = new HashSet<>();
for (int i = 0; i < nums.length; i++) {
int numI = num[i];
for (int j = i + 1; j < nums.length; j++) {
int numJ = num[j];
int numK = -(numI + numK);
int k = Arrays.binarySearch(nums, j + 1, nums.length, numK);
if (k >= 0) { // Found
set.add(new Triple(numI, numJ, numK));
}
}
}
binarySearch delivers a non-negative index when it finds the search key. When negative, it delivers the 1s complement of the "insert" position.
This has complexity O(n².log n). You determine the found resp. insert position in the for-i loop and in the for-j loop decrement k a couple of times to find the sum. That would not be difficult but less readable.
Mind the resulting numbers are ordered.
I have to sort an array using a sorting algorithm and show in which index the values were originally placed. (see expected result vs actual result: https://i.imgur.com/GpIpkPE.png).
I managed to sort correctly the values. BUT the index is HALF correct? Which is confusing me.
public static void sortNumbers(double[] averageNotes) {
for (int i = 0; i < averageNotes.length; i++) {
double max = averageNotes[i];
int maxId = i;
for (int j = i+1; j < averageNotes.length; j++) {
if (averageNotes[j] > max) {
max = averageNotes[j];
maxId = j;
}
}
double temp = averageNotes[i];
averageNotes[i] = max;
averageNotes[maxId] = temp;
System.out.println(averageNotes[i] + " (" + maxId + ")");
}
Any help is highly appreciated. Thank you.
Use an extra array for your indices and sort simultaneously:
public static void sortNumbers(double[] averageNotes) {
//create an array for your indices
int[] indices = new int[averageNotes.length];
//fill indices
for (int i = 0; i < averageNotes.length; i++) {
indices[i] = i;
}
//sort both arrays simultaneously
for (int i = 0; i < averageNotes.length; i++) {
for (int j = i+1; j < averageNotes.length; j++) {
if (averageNotes[i] < averageNotes[j]) {
double temp = averageNotes[i];
averageNotes[i] = averageNotes[j];
averageNotes[j] = temp;
int t = indices[i];
indices[i] = indices[j];
indices[j] = t;
}
}
}
//print
for (int i = 0; i < averageNotes.length; i++) {
System.out.println(averageNotes[i] + " (" + indices[i] + ")");
}
}
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.
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());
I need a simple java program that can generate me the custom sets for a set,say for {'1','2','3','4'}. The result should be:
{'1','2'},{'2','3'},{'3','4'},{'1','2','3'},{'2','3','4'}.
I have tried codes for powerset,but the output isn't desirable. It would be appreciable if the code could be something like:
for(j=2;j<set.size()-1;j++)
{
for(i=0;i<set.size()-1;i++)
{
//a[i],a[i+1] when j=2
//a[i],a[i+1],a[i+2] when j=3
}
}
I know .size() is for ArrayList and a[i] is for simple array and i've written both as any approach will do!! Thanks In Advance!! :)
This code should print the values you want:
final int[] values = {1, 2, 3, 4};
for (int size = 2; size < values.length; size++) {
for (int i = 0; i + size <= values.length; i++) {
for (int j = 0; j <= size - 1; j++) {
System.out.print(values[i + j]);
}
System.out.println();
}
}
From the example, we see that you want to print sets of values whose length is greater than 1 and smaller than the total set, so that 's what the following line does:
for (int size = 2; size < values.length; size++) {
After that we compute the starting index of the subset, watching not to run into a IndexArrayOutOfBounds exception (see the line below)
for (int i = 0; i + size <= values.length; i++) {
From there we just print the values starting at i index and with the subset length of size
for (int j = 0; j <= size - 1; j++)
This is the sample code which is generating the desired result:
int[] array = { 1, 2, 3, 4 };
int size = 2;
for (int j = 0; j < array.length; j++) {
for (int i = 0; i <= array.length - size; i++) {
int[] temp = Arrays.copyOfRange(array, i, i + size);
for (int x : temp) {
System.out.print(x + ",");
}
System.out.println();
}
size++;
if (size == array.length) {
break;
}
}
Output:
1,2,
2,3,
3,4,
1,2,3,
2,3,4,