I have 999 numbers in my arrayList, some of the numbers are repeated. And i want to find the most frequent number in the list, what is the most efficient way of doing that?
Sort the list and than count which occurs the most by reading the sorted List.
Needs 0(n log n) Time
1 3 6 1 82 42 11 42 1 42 3 42
sorted
1 1 1 3 3 6 11 42 42 42 42 82
Read the list from left to right and remember which value was seen the most so far and how often
I assume, as you wrote in comment, that you read numbers from 0 to 100
from a text file, so you can use
int[] count = new int[101];
...
count[numberJustRead]++;
...
and after read all numbers
int max = 0;
int maxIndex = 0; //this is what you looking for
for(int i = 0, k = count.length; i < k; i++){
if(count[i] > max){
max = count[i];
maxIndex = i;
}
}
or you maybe like guava's Mulitset
Here are two simple implementations with different complexity (of course if you have only a few numbers performance gain is symbolic) :
import java.util.*;
public class Test
{
static AbstractMap.SimpleEntry<Integer, Integer> getMostFrequentN2(ArrayList<Integer> values)
{
ArrayList<AbstractMap.SimpleEntry<Integer, Integer>> frequencies = new ArrayList<>();
int maxIndex = 0;
main:
for (int i = 0; i < values.size(); ++i)
{
int value = values.get(i);
for (int j = 0; j < frequencies.size(); ++j)
{
if (frequencies.get(j).getKey() == value)
{
frequencies.get(j).setValue(frequencies.get(j).getValue() + 1);
if (frequencies.get(maxIndex).getValue() < frequencies.get(j).getValue())
{
maxIndex = j;
}
continue main;
}
}
frequencies.add(new AbstractMap.SimpleEntry<Integer, Integer>(value, 1));
}
return frequencies.get(maxIndex);
}
static AbstractMap.SimpleEntry<Integer, Integer> getMostFrequentNLogN(ArrayList<Integer> values)
{
ArrayList<Integer> tmp = new ArrayList(values);
Collections.sort(tmp);
AbstractMap.SimpleEntry<Integer, Integer> max = new AbstractMap.SimpleEntry<>(0, 0);
int current = tmp.get(0);
int count = 0;
for (int i = 0; i < tmp.size(); ++i)
{
if (tmp.get(i) == current)
{
count++;
}
else
{
if (count > max.getValue())
{
max = new AbstractMap.SimpleEntry<Integer, Integer>(current, count);
}
current = tmp.get(i);
count = 1;
}
}
if (count > max.getValue())
{
max = new AbstractMap.SimpleEntry<Integer, Integer>(current, count);
}
return max;
}
public static void main(String[] args)
{
ArrayList<Integer> numbers = new ArrayList(99);
for (int i = 0; i < 99; ++i)
{
numbers.add((int)(Math.random() * 10));
}
System.out.println(numbers);
System.out.println(getMostFrequentN2(numbers));
System.out.println(getMostFrequentNLogN(numbers));
}
}
Yes, slowly.
You could do this with a List of Lists; an inner list contains the numbers you have seen, and the index of the outer list is the number of occurrences. So after processing "1,2,1,3,1,2,3,4" you would have
[ [4], [2, 3], [1] ]
Once you are done processing the input list, you can get the last inner list contained by the highest index of the outer list, which in this case is [1]. All elements in that list are tied for the maximum number of occurrences.
Related
Basically, if I have an ArrayList<Integer> containing <0, 1, 5, 5, 4, 2>, I need to create a separate ArrayList of <2, 3> for the indexes.
I understand how to get the index for the first appearance of the largest number, but I don't know how to get all of them at the same time.
I was originally thinking:
int highest = 0;
for (int b = 0; b < arrlst.size(); b++) {
int p = arrlst.get(b);
if (highest <= p) {
highest = p;
highestindex.add(b);
}
}
But then I realised that would automatically add the first one, as well as any that were higher than the current max, even if they were not the overall max.
I then thought of putting the highestindex.add(...) part outside the loop but then it would only add the last index and not all of them.
I'd go for adding to and clearing a List<Integer>:
public ArrayList<Integer> getIndexesOfHighestNum(List<Integer> list) {
List<Integer> indexes = new ArrayList<Integer>();
int highest = Integer.MIN_VALUE;
for (int i = 0; i < list.size(); i++) {
int value = list.get(i);
if (value > highest) {
indexes.clear();
indexes.add(i);
highest = value;
} else if (value == highest)
indexes.add(i);
}
return indexes;
}
You can do it with stream as,
int max = intArr.stream().reduce(Integer::max).get();
IntStream.range(0, intArr.size()).boxed()
.filter(i -> max == intArr.get(i))
.collect(Collectors.toList());
You can first get the max number and then save the indices of the elements having this value as follows:
private static List<Integer> getMaxIndices(int[] list){
int max = list[0];
for(int i = 1; i < list.length; i++)
if(max < list[i])
max = list[i];
List<Integer> res = new ArrayList<>();
for(int i = 0; i < list.length; i++)
if(list[i] == max)
res.add(i);
return res;
}
To simplify the code, we can make use of Collections#max to get the maximum value.
To better express our intention(filter index with maximum value), we can use IntStream instead of a for loop.
public static List<Integer> getMultipleMaxIndex(final List<Integer> from) {
if (from.isEmpty()) {
return Collections.emptyList();
}
final Integer max = Collections.max(from);
IntStream indexes = IntStream.range(0, from.size() - 1);
return indexes.filter(index -> from.get(index).equals(max)).boxed().collect(Collectors.toList());
}
I hope this will print one largest value. but it need 10 largest elements in an 3D array.
public class foo{
Public static void main(String[] args){
int row,col,dep=3;
int[][][] value=new int[row][col][dep];
/* insert the value from user or initialize the matrix*/
int max=0;
for(row=0;row<3;row++)
for(col=0;col<3;col++)
for(dep=0;dep<3;dep++)
if(value[row][col][dep]>max)
max=value[row][col][dep];
System.out.println(max);
}
}
You can add all integers into a List<Integer>, sort it, and then get the X max numbers of it:
public class foo {
public static void main(String[] args) {
int row = 3, col = 3, dep = 3;
int[][][] value = new int[row][col][dep];
value[1][2][1] = 10;
value[1][0][1] = 15;
List<Integer> listWithAll = new ArrayList<>();
/* insert the value from user or initialize the matrix*/
int max = 0;
for (row = 0; row < 3; row++)
for (col = 0; col < 3; col++)
for (dep = 0; dep < 3; dep++)
listWithAll.add(value[row][col][dep]);
listWithAll.sort(Collections.reverseOrder());
for (int i = 0; i < 10; i++) {
System.out.println(listWithAll.get(i));
}
}
}
which prints:
15 10 0 0 0 0 0 0 0 0
or using Java 8 streams only:
List<Integer> max10 = listWithAll.stream()
.sorted(Collections.reverseOrder())
.limit(10)
.collect(Collectors.toList());
max10.forEach(System.out::println);
Here is a way to do it with streams. I used a complete 2 x 2 x 2 array to make it easier but it would work with any int[][][] array. Instead of using nested loops, I just flatMapped the arrays.
Initialize the array.
int[][][] v = {{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}};
Now get the top4 values (or top N values) and put them in a list.
int top4 = 4;
List<Integer> top4Max =
Arrays.stream(v).flatMap(Arrays::stream).flatMapToInt(
Arrays::stream).boxed().sorted(
Comparator.reverseOrder()).limit(top4).collect(
Collectors.toList());
System.out.println(top4Max);
Prints
8 7 6 5
The Arrays.stream strips one level of array. The flatMap takes those and further flattens them into a single dimenion array. The flatMapToInt flattens that into a stream of ints where they are sorted and processed into a limited collection.
If required, you could also put them in an array instead of a list.
Alternatively, one could create a small array and use it as with a normal findmax function.
public class Array_3D {
public static void main(String[] args) {
int row = 3, col = 3, dep = 3;
int[][][] value = new int[row][col][dep];
value[1][2][1] = 10;
value[1][0][1] = 15;
int[] topten = new int[10]; //array to hold max values
int count = 0;
int candidate = 0;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
for (int k = 0; k < dep; k++) {
if (count < 10) { //start with first ten values
topten[count] = value[i][j][k];
count++;
}
else {
candidate = value[i][j][k];
for (int x = 0; x < 10; x++) { //loop for loading top values
if (candidate > topten[x]) {
topten[x] = candidate;
break; //exit on first hit
}
}
}
}
}
}
for (int i = 0; i < 10; i++) {
System.out.print(topten[i] + " ");
}
System.out.println();
}
}
I don't know which method is faster for large 3D arrays; here we have to run a small loop at every point in the 3D array, vs creating an entirely new list and sorting it. Clearly this wins in memory usage, but not sure about speed. [Edit note this returns an unsorted array of the top ten values as is].
int num_threads = 4;
List<List<Integer>> seq;
//created four new magnetization thread
Magnetizationthread myt[] = new Magnetizationthread[num_threads];
//go through the newlycreated thread
for (int i = 0; i < myt.length; ++i) {
//initializes the thread one by one
myt[i] = new Magnetizationthread(i + 1);
myt[i].start();
//store the sequences genarted in a List
seq = myt[i].generateSequences(2);
for (i = 0; i < seq.size(); i++) {
//gets the sequence generated by the threads
System.out.println(seq.get(i) + "configuration " + i);
}
** Not sure how to get the sum of individual thread and then get their total from an array
I have generated the threads for each configuration and tried adding sum method but getting type mismatch
expect to show sum of each configuration thread and their total sum in the end
[-1, -1]configuration 0
[-1, 1]configuration 1
[1, -1]configuration 2
[1, 1]configuration 3
all threads spawned
thread #, sum = 0 0
Someone suggested storing return values in an array then assigning Id to each thread and using the Id as index of array not sure how to go about it. Any help would be appreciated, Thank you
**
class Magnetizationthread extends Thread {
public int sum;
public int len = 0;
Magnetizationthread(int n) {
len = n;
}
// Computes the total sum of all elements of the given array.
public static int sum(int a[]) {
int result = 0;
for (int i = 0; i < a.length; i++) {
result += a[i];
}
return result;
}
public List<List<Integer>> generateSequences(int seq_size) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
// for our recursion base case
if (seq_size == 1) {
List<Integer> new_seq_1 = new ArrayList<>(); // add -1 once
new_seq_1.add(-1);
List<Integer> new_seq_2 = new ArrayList<>(); // add 1 once
new_seq_2.add(1);
result.add(new_seq_1);
result.add(new_seq_2);
return result;
}
List<List<Integer>> sub_ans = generateSequences(seq_size - 1);
for (int i = 0; i < sub_ans.size(); ++i) {
List<Integer> new_seq_1 = new ArrayList<>(sub_ans.get(i)); // add -1 once
new_seq_1.add(-1);
List<Integer> new_seq_2 = new ArrayList<>(sub_ans.get(i)); // add 1 once
new_seq_2.add(1);
result.add(new_seq_1);
result.add(new_seq_2);
}
return result;
}
}
I am given an array and a value x.
Input example:
2 3
1 2
Where n (length of array) = 2, the value x = 3, and the next line (1, 2) contains the values in the array. I have to find the pairs of indices i, j so that a[i] XOR a[j] = x.
What I have implemented:
import java.util.HashSet;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int x = sc.nextInt();
int[] arr = new int[n];
HashSet<Integer> hash = new HashSet<Integer>();
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
hash.add(arr[i]);
}
int count = 0;
for (int i = 0; i < n; i++) {
if (hash.contains(arr[i]^x)) {
count++;
}
}
System.out.println(count/2);
}
}
I have the divided the result by two because we only want to count a given pair once (only count [1, 2] not [1, 2] and [2, 1]).
I pass the given test above where the output is 1, and this supplementary one where the output is 2.
6 1
5 1 2 3 4 1
However I seem to fail some extra ones which I cannot see.
The problem is that you check "contains", but for duplicate values this only returns a single occurrence. By using a set you throw duplicates away. Instead you should have a HashMap with number of occurrences:
Map<Integer, Integer> hash = new HashMap<>();
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
if (!hash.containsKey(arr[i])) {
hash.put(arr[i], 0)
}
hash.put(arr[i], hash.get(arr[i]) + 1);
}
int count = 0;
for (int i = 0; i < n; i++) {
if (hash.containsKey(arr[i]^x)) {
count += hash.get(arr[i]^x);
}
}
Your logic of dividing the count by 2 as the final answer, is not correct.
Replace your logic by the following:
HashSet<Integer> hash = new HashSet<Integer>();
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
}
int count = 0;
for (int i = 0; i < n; i++) {
if (hash.contains(arr[i]^x)) {
count++;
}
hash.add(arr[i]);
}
System.out.println(count);
Your program doesn't handle duplicate numbers properly. It deals with 5 1 2 3 4 1 okay because 1 isn't part of the solution. What if it is?
Let's say number a[i] ^ a[j] is a solution as is a[i] ^ a[k]. In other words, a[j] == a[k]. The line hash.contains(arr[i]^x) will only count a[i] once.
You can solve this by having nested for loops.
for (int i = ...) {
for (int j = ...) {
if (a[i] ^ a[j] == x) {
count++;
}
}
}
This approach lets you get rid of the hash set. And if you're clever enough filling out the ... parts you can avoid double counting the pairs and won't have to divide count by 2.
i'm new to this, Say if you typed 6 6 6 1 4 4 4 in the command line, my code gives the most frequent as only 6 and i need it to print out 6 and 4 and i feel that there should be another loop in my code
public class MostFrequent {
//this method creates an array that calculates the length of an integer typed and returns
//the maximum integer...
public static int freq(final int[] n) {
int maxKey = 0;
//initiates the count to zero
int maxCounts = 0;
//creates the array...
int[] counts = new int[n.length];
for (int i=0; i < n.length; i++) {
for (int j=0; j < n[i].length; j++)
counts[n[i][j]]++;
if (maxCounts < counts[n[i]]) {
maxCounts = counts[n[i]];
maxKey = n[i];
}
}
return maxKey;
}
//method mainly get the argument from the user
public static void main(String[] args) {
int len = args.length;
if (len == 0) {
//System.out.println("Usage: java MostFrequent n1 n2 n3 ...");
return;
}
int[] n = new int[len + 1];
for (int i=0; i<len; i++) {
n[i] = Integer.parseInt(args[i]);
}
System.out.println("Most frequent is "+freq(n));
}
}
Thanks...enter code here
Though this may not be a complete solution, it's a suggestion. If you want to return more than one value, your method should return an array, or better yet, an ArrayList (because you don't know how many frequent numbers there will be). In the method, you can add to the list every number that is the most frequest.
public static ArrayList<Integer> freq(final int[] n) {
ArrayList<Integer> list = new ArrayList<>();
...
if (something)
list.add(thatMostFrequentNumber)
return list;
}
The solutions looks like this:
// To use count sort the length of the array need to be at least as
// large as the maximum number in the list.
int[] counts = new int[MAX_NUM];
for (int i=0; i < n.length; i++)
counts[n[i]]++;
// If your need more than one value return a collection
ArrayList<Integer> mf = new ArrayList<Integer>();
int max = 0;
for (int i = 0; i < MAX_NUM; i++)
if (counts[i] > max)
max = counts[i];
for (int i = 0; i < MAX_NUM; i++)
if (counts[i] == max)
mf.add(i);
return mf;
Well you can just do this easily by using the HashTable class.
Part 1. Figure out the frequency of each number.
You can do this by either a HashTable or just a simple array if your numbers are whole numbrs and have a decent enough upper limit.
Part 2. Find duplicate frequencies.
You can just do a simple for loop to figure out which numbers are repeated more than once and then print them accordingly. This wont necessarily give them to you in order though so you can store the information in the first pass and then print it out accordingly. You can use a HashTable<Integer,ArrayList<Integer> for this. Use the key to store frequency and the ArrayList to store the numbers that fall within that frequency.
You can maintain a "max" here while inserting into our HashTable if you only want to print out only the things with most frequency.
Here is a different way to handle this. First you sort the list, then loop through and keep track of the largest numbers:
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
int n[] = { 6, 4, 6, 4, 6, 4, 1 };
List<Integer> maxNums = new ArrayList<Integer>();
int max = Integer.MIN_VALUE;
Integer lastValue = null;
int currentCount = 0;
Arrays.sort(n);
for( int i : n ){
if( lastValue == null || i != lastValue ){
if( currentCount == max ){
maxNums.add(lastValue);
}
else if( currentCount > max ){
maxNums.clear();
maxNums.add(lastValue);
max = currentCount;
}
lastValue = i;
currentCount = 1;
}
else {
currentCount++;
}
System.out.println("i=" + i + ", currentCount=" + currentCount);
}
if( currentCount == max ){
maxNums.add(lastValue);
}
else if( currentCount >= max ){
maxNums.clear();
maxNums.add(lastValue);
}
System.out.println(maxNums);
}
}
You can try it at: http://ideone.com/UbmoZ5