Finding modes an an array - java

Does anyone know how to find the modes in an array when there are more then one mode? I have this code that finds one mode. But I'm dealing with an array which has more than one mode, a multimodal array and I have to print each mode exactly once. Here is my code, can someone help me out? Thanks.
public static int mode(int a[])
{
int maxValue=0, maxCount=0;
for (int i = 0; i < a.length; ++i)
{
int count = 0;
for (int j = 0; j < a.length; ++j)
{
if (a[j] == a[i]) ++count;
}
if (count > maxCount)
{
maxCount = count;
maxValue = a[i];
}
}
return maxCount;
}
public static Integer[] modes(int a[])
{
List<Integer> modes = new ArrayList<Integer>();
int maxCount=0;
for (int i = 0; i < a.length; ++i)
{
int count = 0;
for(int j = 0; j < a.length; ++j)
{
if (a[j] == a[i]) ++count;
}
if (count > maxCount)
{
maxCount = count;
modes.clear();
modes.add(a[i]);
}
else if (count == maxCount)
{
modes.add(a[i]);
}
}
return modes.toArray(new Integer[modes.size()]);
}

Since your elements will be between 10 and 1000, you can use a Counter array. In this Counter array, you can store the counts of the value of the a[i] element. I think you can understand this better in code:
public static List<Integer> mode(int[] a) {
List<Integer> lstMode = new ArrayList<Integer>();
final int MAX_RANGE = 1001;
int[] counterArray = new int[MAX_RANGE]; //can be improved with some maths :)!
//setting the counts for the counter array.
for (int x : a) {
counterArray[x]++;
}
//finding the max value (mode).
int maxCount = counterArray[0];
for(int i = 0; i < MAX_RANGE; i++) {
if (maxCount < counterArray[i]) {
maxCount = counterArray[i];
}
}
//getting all the max values
for(int i = 0; i < MAX_RANGE; i++) {
if (maxCount == counterArray[i]) {
lstMode.add(new Integer(i));
}
}
return lstMode;
}
If your input will have elements outside of 1000, you can look for the Map answer (like in other posts).

We should do this the easy way and utilize a Map data structure in the following format:
Map<Integer,Integer>
And then keep a running total, afterwards you iterate over the keyset and pull the highest value(s) from the Map.
If you want to stay with the List implementation you can do the following to remove dupes:
Set s = new HashSet(list);
list = new ArrayList(s);

One approach is to run (approximately) your current code twice: the first time, find maxCount, and the second time, print out each value that occurs maxCount times. (You'll need to make some modifications in order to print each mode only once, instead of printing it maxCount times.)

Instead of having a single maxValue, store the modes in an ArrayList<Integer>.
if (count == maxCount)
{
modes.add(a[i]);
}
else if (count > maxCount)
{
modes.clear(); // discard all the old modes
modes.add(a[i]);
maxCount = count;
}
and start with j = i instead of j = 0.

Since your array values only range from [10,1000], you could use a Map<Integer,Integer> to store a mapping between each discovered array value (map key) and its count (map value). A HashMap would work very well here.
To increment the count:
int count = (map.contains(a[i]) ? map.get(a[i]) : 1;
map.put(a[i],count);
Continue to track the max count like you already do, and at the end, just iterate over the map and collect all map keys with a map value equal to the max count.

Related

Search minimum absolute value difference in java

How can I optimize my algorithm to find the minimum absolute value difference in a given array. Here is my approach which checks each and every element and returning the value.
static int minAbsVal(int[] myArray){
ArrayList<Integer> diffs= new ArrayList(); // all absolute value differences
for (int i = 0; i < myArray.length; i++) {
for (int j = 0; j < myArray.length; j++) {
if (myArray[j]!=myArray[i]){
int absVal =Math.abs( myArray[i]- myArray[j]);
diffs.add(absVal);
}
}
}
int min = diffs.get(0);
for (int i = 1; i < diffs.size(); i++) {
if (min>diffs.get(i)){
min = diffs.get(i);
}
}
return min;
}
Check this solution. If array contains duplicates than it returns 0 if you wanna avoid than you can add conditions also.
static int minAbsVal(int[] myArray){
Arrays.sort(myArray);
ArrayList<Integer> diffs= new ArrayList<Integer>(); // all absolute value differences
for (int i = 0; i < myArray.length-1; i++) {
diffs.add(Math.abs( myArray[i+1] - myArray[i]));
}
Collections.sort(diffs);
return diffs.get(0);
}
Or you can also use :-
static int minAbsVal(int[] myArray){
Arrays.sort(myArray);
int minimum=Math.abs( myArray[1] - myArray[0]);
for (int i = 1; i < myArray.length-1; i++) {
int diff = Math.abs( myArray[i+1] - myArray[i]);
if (diff == 0)
return 0;
else if (minimum > diff)
minimum = diff;
}
return minimum;
}
Check the following solution,
static int minimumAbsoluteDifference(int n, int[] arr) {
int a = Math.abs(arr[1]-arr[0]);
Arrays.sort(arr);
for(int x=0;x<n-1;x++){
if(Math.abs(arr[x]-arr[x+1])<a){
a = Math.abs(arr[x]-arr[x+1]);
if(a==0){
return a;
}
}
}
return a;
}
Dependson the size of your array a good approach would be to divide it in different smaller arrays and look for the minimum of each in pararell and then compare those results .
Anyways you dont need so many iterations, you can just set the baseValue to the first element of the array and when iterating the array compare the baseValue vs the current, if the current is smaller then asign baseValue to current (I would rename baseValue to minValue in that case)

Java - Find maximum number of duplicates within an array

I am utilizing a HashSet for finding the maximum number of duplicates of a value in a sorted Integer array. But my algorithm doesn't seem to work, not returning the desired results.
Set variables storing the number of duplicates found (0), and the maximum number of duplicates (0).
Set a HashSet that stores the unique values of an array.
Sort the array to be ready for comparison.
Loop through each value of the array
If the HashSet of unique values contains the current value:
Increment the duplicate Count
If the currentValue is not equal to the previous value:
If the duplicateCount is greater than the maximum Count:
maximumCount becomes duplicateCount
Reset duplicateCount to 0
Java Code:
HashSet<Integer> uniqueValues = new HashSet<Integer>(valueSequenceList);
int duplicateCount = 0;
int maxCount = 0;
Arrays.sort(valueSequence);
for (int i = 0; i < valueSequence.length; i++)
{
if (uniqueValues.contains(valueSequence[i]))
{
duplicateCount++;
}
if (i > 0 && valueSequence[i] != valueSequence[i-1])
{
if (duplicateCount > maxCount)
{
maxCount = duplicateCount;
duplicateCount = 0;
}
}
}
Example:
Input: [4, 4, 10, 4, 10]
Output: 4 Duplicates (There are supposed to be a maximum of 3 duplicates - Total number of values that are the same).
This is the Element Distinctness Problem - which is explained with details in the thread: Find duplicates in an array.
The mentiones thread discusses solutions to the problem, and shows lower bounds as well (cannot be done better than O(nlogn) without using a hash table.
So, if your data is not sorted - you could sort and iterate (as follows), or use a hash set - and then you don't need to sort the array.
If you first sort the array, or the array is already sorted, a single iteration will do:
Single iteration on a sorted array:
if (arr == null || arr.length == 0) return 0;
int last = arr[0];
int numDupes = 1;
for (int i = 1; i < arr.length; i++) {
if (arr[i] == last) numDupes++;
last = arr[i];
}
Using a HashSet (no need to sort):
if (arr == null) return 0;
Set<Integer> set = new HashSet<>();
int numDupes = 0;
for (int x : arr) {
if (set.contains(x)) numDupes++;
set.add(x);
}
If you are looking for the maximal number some element repeats (and not total number of repeats), you can use the same approach but slightly different:
Hashing solution - use a histogram:
Map<Integer,Integer> histogram = new HashMap<>();
for (int x : arr) {
if (!histogram.containsKey(x)) histogram.put(x,1);
else histogram.put(x,histogram.get(x) + 1);
}
int max = 0;
for (int x : histogram.values) max = max > x ? max : x;
return max;
Sorted array solution:
if (arr == null || arr.length == 0) return 0;
int last = arr[0];
int max = 0;
int currNumDupes = 1;
for (int i = 1; i < arr.length; i++) {
if (arr[i] == last) currNumDupes++;
else {
max = max > currNumDupes ? max : currNumDupes;
currNumDupes = 1;
}
last = arr[i];
}
max = max > currNumDupes ? max : currNumDupes; //if the most dupes is from the highest element
check the following code which returns the max count of duplicates
public static void main(String args[]) {
int[] inputArray = { 4, 4, 10, 4, 10 };
Map<Integer, Integer> hMap = new HashMap<Integer, Integer>();
HashSet<Integer> hSet = new HashSet<Integer>();
for (int i : inputArray) {
if (hSet.add(i)) {
hMap.put(i, 1);
} else {
hMap.put(i, hMap.get(i) + 1);
}
}
Iterator<Integer> iter = hMap.values().iterator();
int temp = 0;
while (iter.hasNext()) {
int max = iter.next();
if (max > temp) {
temp = max;
}
}
System.out.println(temp);
}
Suggestion:
You could use a simple Map<Integer, Integer> where the key is the item value, and the value is the count of that item.
This would make the code simple - no need to sort:
Map<Integer, Integer> count = new HashMap<Integer, Integer>();
for (Integer item : list){
if (count.containsKey(item)){
// increate count
count.put(item, count.get(key) + 1);
} else {
// no item yet - set count to 1
count.put(item, 1);
}
}
You could now use something like Collections.max to find the maximum Integer value on count.values() - or even write a Comparator<Entry<Integer, Integer>> for the entries to find the maximal Map.Entry<Integer, Integer> from count.entrySet() (preferable, can be used with Collections.max).
Note: You could use something like MutableInt (Apache commons) or even AtomicInt for mutable map values. I haven't tested the differences but it may be faster.
EDIT : I'm assuming (based on your code) that the goal is to find the number of appearances of the number that appears the most in the array. Calling it "maximum number of duplicates" is misleading.
First of all, the HashSet is useless. You add all the elements to it up front, which means uniqueValues.contains(valueSequence[i]) is always true.
Now, you only want to increment the duplicateCount if you still haven't moved to the next element :
for (int i = 0; i < valueSequence.length; i++)
{
if (i == 0 || valueSequence[i] == valueSequence[i-1])
{
duplicateCount++;
}
else
{
if (duplicateCount > maxCount)
{
maxCount = duplicateCount;
}
duplicateCount = 1; // another small fix
}
}
if (duplicateCount > maxCount)
maxCount = duplicateCount;
}
If the goal is to find the number of duplicates, you can do it without any loop (since the number of duplicates is the total number of elements minus the number of unique elements) :
HashSet<Integer> uniqueValues = new HashSet<Integer>(valueSequenceList);
int duplicateCount = valueSequenceList.size() - uniqueValues.size();
String[] Csssplit = Css.split("====");
HashMap<String,Integer> Spancsslist = new HashMap<String,Integer>();
for(int c=0;c<Csssplit.length;c++){
Css = Csssplit[c];
//System.out.println("css::"+Css);
int count = Spancsslist.getOrDefault(Css, 0);
Spancsslist.put(Css,count+1);
}
if(Spancsslist.size()==0){ continue; }
Spancsslist = Spancsslist.entrySet().stream().sorted(Collections.reverseOrder(Map.Entry.comparingByValue())).collect(toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e2,LinkedHashMap::new));
Css = Spancsslist.keySet().stream().findFirst().get();
using Integer.MIN_VALUE to find max array, then count duplicate max int array.
public static int main(int[] ar) {
int count = 0;
int max = Integer.MIN_VALUE;
int lastMax = 0;
for(int i = 0; i < ar.length; i++) {
if(ar[i] > max) {
max = ar[i];
if(lastMax != max){
count = 0;
}
lastMax = max;
}
if(ar[i] == max) {
count += 1;
}
}
return count;
}

Finding uniques integers in an array

i have an array of integers like this one :
A={1,1,4,4,4,1,1}
i want to count the each number once , for this example the awnser is 2 becuase i want to count 1 once and 4 once
i dont want to use sorting methods
i am unable to find a way to solve it using java.
i did this but it gives me 0
public static void main(String args[]) {
int a[] = { 1,1,4,4,4,4,1,1};
System.out.print(new Test4().uniques(a));
}
public int uniques(int[] a) {
int unique = 0;
int tempcount = 0;
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a.length; j++) {
if (a[i] == a[j]) {
tempcount++;
}
}
if (tempcount <= 2) {
unique=a[i];
}
tempcount = 0;
}
return unique;
}
the purpose of the question is to understand the logic of it but not solving it using ready methods or classes
This one should work. I guess this might be not the most elegant way, but it is pretty straightforward and uses only simple arrays. Method returns number of digits from array, but without counting duplicates - and this I believe is your goal.
public int uniques(int[] a) {
int tempArray[] = new int[a.length];
boolean duplicate = false;
int index = 0;
int digitsAdded = 0;
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < tempArray.length; j++) {
if (a[i] == tempArray[j]) {
duplicate = true;
}
}
if(!duplicate) {
tempArray[index] = a[i];
index++;
digitsAdded++;
}
duplicate = false;
}
//this loop is needed if you have '0' in your input array - when creating temp
//array it is filled with 0s and then any 0 in input is treated as a duplicate
//again - not most elegant solution, maybe I will find better later...
for(int i = 0; i < a.length; i++) {
if(a[i] == 0) {
digitsAdded++;
break;
}
}
return digitsAdded;
}
Okay first of all in your solution you are returning the int unique, that you are setting as the value that is unique a[i]. So it would only return 1 or 4 in your example.
Next, about an actual solution. You need to check if you have already seen that number. What you need to check is that for every number in the array is only appears in front of your position and not before. You can do this using this code below.
public int uniques(int[] a) {
int unique = 1;
boolean seen = false;
for (int i = 1; i < a.length; i++) {
for (int j = 0; j < i; j++) {
if (a[i] == a[j]) {
seen = true;
}
}
if (!seen) {
unique++;
}
seen = false;
}
return unique;
}
In this code you are iterating over the number you have seen and comparing to the number you are checking (a[i]). You know that for it to be unique you cant have seen it before.
I see two possible solutions:
using set
public int unique(int[] a) {
Set<Integer> set = new HashSet<>();
for (int i : a) {
set.add(i);
}
return set.size();
}
using quick sort
public int unique(int[] a) {
Arrays.sort(a);
int cnt = 1;
int example = a[0];
for (int i = 1; i < a.length; i++) {
if (example != a[i]) {
cnt++;
example = a[i];
}
}
return cnt;
}
My performance tests say that second solution is faster ~ 30%.
if restricted to only arrays, consider trying this:
Lets Take a temporary array of the same size of orignal array, where we store each unique letter and suppose a is your orignal array,
int[] tempArray= new int[a.length];
int tempArraycounter = 0;
bool isUnique = true;
for (int i = 0; i < a.length; i++)
{
isUnique = true;
for (int j = 0; j < tempArray.length; j++)
{
if(tempArray[j] == a[i])
isUnique = false;
}
if(isUnique)
{
tempArray[tempArraycounter] = a[i];
tempArraycounter++;
isUnique = false;
}
}
now tempArraycounter will be your answer ;)
Try Following code:
int test[]={1,1,4,4,4,1,1};
Set<Integer> set=new LinkedHashSet<Integer>();
for(int i=0;i<test.length;i++){
set.add(test[i]);
}
System.out.println(set);
Output :
[1, 4]
At the end set would contain unique integers.

Finding the mode of an array

Ok so I am stuck once again here is what I have
public static int mode(int[][] arr) {
List<Integer> list = new ArrayList<Integer>();
List<Integer> Mode = new ArrayList<Integer>();
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
list.add(arr[i][j]);
}
}
for(int i = 0; i < list.size(); i ++) {
Mode.add((Mode.indexOf(i)+1));
}
System.out.println(Mode);
return 0;
}
What I am trying to do is in order to find the mathematical mode of this array what I intend to do is for every number I encounter in the array increment the corresponding index by 1 eventually ending up with a new array with "tally" marks in the corresponding indexes, I am not sure } am going about this in the right way I need a dynamic array I assume in order to reach any number that may be encountered so one that can grow to whatever size I need, if my code is complete gibberish feel free to criticize at will :)
Have you considered using a Map instead of a List? That way you can eliminate the ugly indexOf call, and just refer to each instance of the elements by their value, not by doing a linear search each time. Then, all you have to do is find the key with the highest value in your map.
public static Set<Double> getMode(double[] data) {
if (data.length == 0) {
return new TreeSet<>();
}
TreeMap<Double, Integer> map = new TreeMap<>(); //Map Keys are array values and Map Values are how many times each key appears in the array
for (int index = 0; index != data.length; ++index) {
double value = data[index];
if (!map.containsKey(value)) {
map.put(value, 1); //first time, put one
}
else {
map.put(value, map.get(value) + 1); //seen it again increment count
}
}
Set<Double> modes = new TreeSet<>(); //result set of modes, min to max sorted
int maxCount = 1;
Iterator<Integer> modeApperance = map.values().iterator();
while (modeApperance.hasNext()) {
maxCount = Math.max(maxCount, modeApperance.next()); //go through all the value counts
}
for (double key : map.keySet()) {
if (map.get(key) == maxCount) { //if this key's value is max
modes.add(key); //get it
}
}
return modes;
}

Find the mode (most frequent value in an array) using a simple for loop?

How do I find the mode (most frequent value in an array) using a simple for loop?
The code compiles with a wrong output.
Here is what I have:
public static void mode(double [] arr)
{
double mode=arr[0];
for(int i = 1; i<arr.length; i++)
{
if(mode==arr[i])
{
mode++;
}
}
return mode;
}
First I sort the array by order and then I count occurrences of one number. No hashmaps only for loop and if statements.
My code:
static int Mode(int[] n){
int t = 0;
for(int i=0; i<n.length; i++){
for(int j=1; j<n.length-i; j++){
if(n[j-1] > n[j]){
t = n[j-1];
n[j-1] = n[j];
n[j] = t;
}
}
}
int mode = n[0];
int temp = 1;
int temp2 = 1;
for(int i=1;i<n.length;i++){
if(n[i-1] == n[i]){
temp++;
}
else {
temp = 1;
}
if(temp >= temp2){
mode = n[i];
temp2 = temp;
}
}
return mode;
}
-Just use a HashMap which contains the array index values as the keys and their occurrence numbers as the values.
-Update the HashMap as you traverse the for loop by checking to see if the current index already exists in the HashMap. IF IT DOES then find that double in the hash map and see how many times it has already occurred and put it back in the HashMap with one more occurrence.
-I did it in Java because that's what it looks like you are using. What's also good is that the time complexity is O(n) which is the best you could possibly get for this type of scenario because you have to visit every element at least once.
-So if you have an array like this of doubles: { 1,2,3,1,1,1,5,5,5,7,7,7,7,7,7,7,7,7}
Then the hash map will look something like this at the end: { 1->4, 2->1, 3->1, 5->3, 7->9 }
Meaning that "1 occurred 4 times, 2 occured 1 time .... 7 occurred 9 times" etc.
public static double mode(double [] arr)
{
HashMap arrayVals = new HashMap();
int maxOccurences = 1;
double mode = arr[0];
for(int i = 0; i<arr.length; i++)
{
double currentIndexVal = arr[i];
if(arrayVals.containsKey(currentIndexVal)){
int currentOccurencesNum = (Integer) arrayVals.get(currentIndexVal);
currentOccurencesNum++;
arrayVals.put(currentIndexVal, currentOccurencesNum );
if(currentOccurencesNum >= maxOccurences)
{
mode = currentIndexVal;
maxOccurences = currentOccurencesNum;
}
}
else{
arrayVals.put(arr[i], 1);
}
}
return mode;
}
This code is a different way that does not use hashmaps. This method, created in java, takes an array as the parameter and creates another array called "numberCount" within the method. This array "numberCount" will set its index to the value in the array. The index of "numberCount"that contains the value in the array passed will add 1 to the value of "numberCount" ("++numberCount[array[i]]") then will go to the next value in the array (repeat until the end of the array). Then creates another for loop to go through each value of the array in "numberCount", which ever index has the highest value/count will be stored and return as "max." This method will have to undergo some difficult changes to use a double array. but seems to work great with an int array.
public static int findMostFrequentValue(int[] array) {
int i;
int[] numberCount = new int[100];
for (i = 0; i < array.length; i++)++numberCount[array[i]];
int max = 0;
int j;
for (j = 0; j < numberCount.length; j++) {
if (numberCount[j] > max) max = j;
}
return max;
}
You should check the number of occurances of every element in your array. You can do it by comparing every element of array with herself and others via 2 inner for loops.
Remember, if the array is not sorted and contains more then 1 modal value (thus repeating number of occurances) this will return the first one. It maybe wise to order the array first by Arrays.sort(array) so that you can pick the smallest or biggest modal value.
public static int modeOfArray(int[] array){
int mode;
int maxOccurance = 0;
for(int i=0; i<array.length; i++){
int occuranceOfThisValue = 0;
for(int j=0; j<array.length; j++){
if(array[i] == array[j])
occuranceOfThisValue++;
}
if(occuranceOfThisValue > maxOccurance){
maxOccurance = occuranceOfThisValue;
mode = array[i];
}
}
return mode;
}

Categories

Resources