Find the element with highest occurrences in an array [java] - java

I have to find the element with highest occurrences in a double array.
I did it like this:
int max = 0;
for (int i = 0; i < array.length; i++) {
int count = 0;
for (int j = 0; j < array.length; j++) {
if (array[i]==array[j])
count++;
}
if (count >= max)
max = count;
}
The program works, but it is too slow! I have to find a better solution, can anyone help me?

Update:
As Maxim pointed out, using HashMap would be a more appropriate choice than Hashtable here.
The assumption here is that you are not concerned with concurrency. If synchronized access is needed, use ConcurrentHashMap instead.
You can use a HashMap to count the occurrences of each unique element in your double array, and that would:
Run in linear O(n) time, and
Require O(n) space
Psuedo code would be something like this:
Iterate through all of the elements of your array once: O(n)
For each element visited, check to see if its key already exists in the HashMap: O(1), amortized
If it does not (first time seeing this element), then add it to your HashMap as [key: this element, value: 1]. O(1)
If it does exist, then increment the value corresponding to the key by 1. O(1), amortized
Having finished building your HashMap, iterate through the map and find the key with the highest associated value - and that's the element with the highest occurrence. O(n)
A partial code solution to give you an idea how to use HashMap:
import java.util.HashMap;
...
HashMap hm = new HashMap();
for (int i = 0; i < array.length; i++) {
Double key = new Double(array[i]);
if ( hm.containsKey(key) ) {
value = hm.get(key);
hm.put(key, value + 1);
} else {
hm.put(key, 1);
}
}
I'll leave as an exercise for how to iterate through the HashMap afterwards to find the key with the highest value; but if you get stuck, just add another comment and I'll get you more hints =)

Use Collections.frequency option:
List<String> list = Arrays.asList("1", "1","1","1","1","1","5","5","12","12","12","12","12","12","12","12","12","12","8");
int max = 0;
int curr = 0;
String currKey = null;
Set<String> unique = new HashSet<String>(list);
for (String key : unique) {
curr = Collections.frequency(list, key);
if(max < curr){
max = curr;
currKey = key;
}
}
System.out.println("The number " + currKey + " happens " + max + " times");
Output:
The number 12 happens 10 times

The solution with Java 8
int result = Arrays.stream(array)
.boxed()
.collect(Collectors.groupingBy(i->i,Collectors.counting()))
.values()
.stream()
.max(Comparator.comparingLong(i->i))
.orElseThrow(RuntimeException::new));

I will suggest another method. I don't know if this would work faster or not.
Quick sort the array. Use the built in Arrays.sort() method.
Now compare the adjacent elements.
Consider this example:
1 1 1 1 4 4 4 4 4 4 4 4 4 4 4 4 9 9 9 10 10 10 29 29 29 29 29 29
When the adjacent elements are not equal, you can stop counting that element.

Solution 1: Using HashMap
class test1 {
public static void main(String[] args) {
int[] a = {1,1,2,1,5,6,6,6,8,5,9,7,1};
// max occurences of an array
Map<Integer,Integer> map = new HashMap<>();
int max = 0 ; int chh = 0 ;
for(int i = 0 ; i < a.length;i++) {
int ch = a[i];
map.put(ch, map.getOrDefault(ch, 0) +1);
}//for
Set<Entry<Integer,Integer>> entrySet =map.entrySet();
for(Entry<Integer,Integer> entry : entrySet) {
if(entry.getValue() > max) {max = entry.getValue();chh = entry.getKey();}
}//for
System.out.println("max element => " + chh);
System.out.println("frequency => " + max);
}//amin
}
/*output =>
max element => 1
frequency => 4
*/
Solution 2 : Using count array
public class test2 {
public static void main(String[] args) {
int[] a = {1,1,2,1,5,6,6,6,6,6,8,5,9,7,1};
int max = 0 ; int chh = 0;
int count[] = new int[a.length];
for(int i = 0 ; i <a.length ; i++) {
int ch = a[i];
count[ch] +=1 ;
}//for
for(int i = 0 ; i <a.length ;i++) {
int ch = a[i];
if(count[ch] > max) {max = count[ch] ; chh = ch ;}
}//for
System.out.println(chh);
}//main
}

Here's a java solution --
List<Integer> list = Arrays.asList(1, 2, 2, 3, 2, 1, 3);
Set<Integer> set = new HashSet(list);
int max = 0;
int maxtemp;
int currentNum = 0;
for (Integer k : set) {
maxtemp = Math.max(Collections.frequency(list, k), max);
currentNum = maxtemp != max ? k : currentNum;
max = maxtemp;
}
System.out.println("Number :: " + currentNum + " Occurs :: " + max + " times");

int[] array = new int[] { 1, 2, 4, 1, 3, 4, 2, 2, 1, 5, 2, 3, 5 };
Long max = Arrays.stream(array).boxed().collect(Collectors.groupingBy(i -> i, Collectors.counting())).values()
.stream().max(Comparator.comparing(Function.identity())).orElse(0L);

public static void main(String[] args) {
int n;
int[] arr;
Scanner in = new Scanner(System.in);
System.out.println("Enter Length of Array");
n = in.nextInt();
arr = new int[n];
System.out.println("Enter Elements in array");
for (int i = 0; i < n; i++) {
arr[i] = in.nextInt();
}
int greatest = arr[0];
for (int i = 0; i < arr.length; i++) {
if (arr[i] > greatest) {
greatest = arr[i];
}
}
System.out.println("Greatest Number " + greatest);
int count = 0;
for (int i = 0; i < arr.length; i++) {
if (greatest == arr[i]) {
count++;
}
}
System.out.println("Number of Occurance of " + greatest + ":" + count + " times");
in.close();
}

In continuation to the pseudo-code what you've written try the below written code:-
public static void fetchFrequency(int[] arry) {
Map<Integer, Integer> newMap = new TreeMap<Integer, Integer>(Collections.reverseOrder());
int num = 0;
int count = 0;
for (int i = 0; i < arry.length; i++) {
if (newMap.containsKey(arry[i])) {
count = newMap.get(arry[i]);
newMap.put(arry[i], ++count);
} else {
newMap.put(arry[i], 1);
}
}
Set<Entry<Integer, Integer>> set = newMap.entrySet();
List<Entry<Integer, Integer>> list = new ArrayList<Entry<Integer, Integer>>(set);
Collections.sort(list, new Comparator<Map.Entry<Integer, Integer>>() {
#Override
public int compare(Entry<Integer, Integer> o1, Entry<Integer, Integer> o2) {
return (o2.getValue()).compareTo(o1.getValue());
}
});
for (Map.Entry<Integer, Integer> entry : list) {
System.out.println(entry.getKey() + " ==== " + entry.getValue());
break;
}
//return num;
}

This is how i have implemented in java..
import java.io.*;
class Prog8
{
public static void main(String[] args) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.println("Input Array Size:");
int size=Integer.parseInt(br.readLine());
int[] arr= new int[size];
System.out.println("Input Elements in Array:");
for(int i=0;i<size;i++)
arr[i]=Integer.parseInt(br.readLine());
int max = 0,pos=0,count = 0;
for (int i = 0; i < arr.length; i++)
{
count=0;
for (int j = 0; j < arr.length; j++)
{
if (arr[i]==arr[j])
count++;
}
if (count >=max)
{
max = count;
pos=i;
}
}
if(max==1)
System.out.println("No Duplicate Element.");
else
System.out.println("Element:"+arr[pos]+" Occourance:"+max);
}
}

Find the element with the highest occurrences in an array using java 8 is given below:
final Long maxOccurrencesElement = arr.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.max((o1, o2) -> o1.getValue().compareTo(o2.getValue()))
.get()
.getKey();

You can solve this problem in one loop with without using HashMap or any other data structure in O(1) space complexity.
Initialize two variables count = 0 and max = 0 (or Integer.MIN_VALUE if you have negative numbers in your array)
The idea is you will scan through the array and check the current number,
if it is less than your current max...then do nothing
if it is equal to your max ...then increment the count variable
if it is greater than your max..then update max to current number and set count to 1
Code:
int max = 0, count = 0;
for (int i = 0; i < array.length; i++) {
int num = array[i];
if (num == max) {
count++;
} else if (num > max) {
max = num;
count = 1;
}
}

Here is Ruby SOlution:
def maxOccurence(arr)
m_hash = arr.group_by(&:itself).transform_values(&:count)
elem = 0, elem_count = 0
m_hash.each do |k, v|
if v > elem_count
elem = k
elem_count = v
end
end
"#{elem} occured #{elem_count} times"
end
p maxOccurence(["1", "1","1","1","1","1","5","5","12","12","12","12","12","12","12","12","12","12","8"])
output:
"12 occured 10 times"

Related

How to delete minimum and maximum from array?

I'm a newbie in java. I'm trying to find minimum maximum element in array and then delete the minimum and maximum. This is the code I wrote, it's only working for maximum not for minimum.
public class delminmax {
public static void main(String[] args) {
int [] nums = {10,50,20,90,22};
int max = 0;
int min = 0;
for (int i=0; i<nums.length; i++) {
if (nums[i]> max)
max = nums[i];
}
System.out.println("The max number is "+ max);
for (int i=0;i<nums.length;i++)
if (max==nums[i]) {
for (int j=i; j<nums.length-1;j++)
nums[j]= nums[j+1];
}
for (int i=0;i<nums.length-1;i++)
System.out.print(nums[i]+ " " + "\n");
for (int i=0; i<nums.length; i++) {
if (nums[i]< min)
min = nums[i];
}
System.out.println("The min number is "+ min);
for (int i=0;i<nums.length;i++)
if (min==nums[i]) {
for (int j=i; j<nums.length-1;j++)
nums[j]= nums[j+1];
}
for (int i=0;i<nums.length-1;i++)
System.out.println(nums[i] + " ");
}
}
You can't delete elements from an array, an array has a fixed length determined at creation time. You can instead create a new array with two fewer elements. You only need one loop to determine the min and max, but instead of doing so directly it's cleaner in my opinion to track the indices of the min and max elements. Then you can use a second loop to skip those elements when you copy nums to the new array. Like,
int[] nums = { 10, 50, 20, 90, 22 };
int mini = 0, maxi = 0;
for (int i = 1; i < nums.length; i++) {
if (nums[i] < nums[mini]) {
mini = i;
}
if (nums[i] > nums[maxi]) {
maxi = i;
}
}
System.out.printf("The min = %d, the max = %d%n", nums[mini], nums[maxi]);
int[] newNums = new int[nums.length - 2]; // A new array, with two fewer elements
int p = 0;
for (int i = 0; i < nums.length; i++) {
if (i != mini && i != maxi) {
newNums[p++] = nums[i];
}
}
System.out.println(Arrays.toString(newNums));
Which outputs
The min = 10, the max = 90
[50, 20, 22]
Using Java 8
You can try by using streams with the approach below:
Approach Here:
I have converted the given array of Integers in the sorted list and then find the minimum and maximum integer from that list using any of the below method and then filtered the nums Array with these min and max integers and converted the filtered list back to Array of Integers.
To find the minimum and maximum integer in an array
1) By using IntSummaryStatistics from stream
IntSummaryStatistics statistics = Arrays.stream(nums).summaryStatistics();
int minNum = statistics.getMin();
int maxNum = statistics.getMax();
2) By Sorting the array
List<Integer> mainList = Arrays.stream(nums).boxed().sorted()
.collect(Collectors.toList());
int minNum = mainList.get(0);
int maxNum = mainList.get(mainList.size()-1);
Note: It will remove all the occurrences of minimum and maximum integer from the given array.
public class Test {
public static void main(String[] args) {
int [] nums = {10,50,90,20,5,90,22,5};
IntSummaryStatistics statistics = Arrays.stream(nums).summaryStatistics();
int minNum = statistics.getMin();
int maxNum = statistics.getMax();
int[] num = Arrays.stream(nums)
.filter(x -> x != minNum && x != maxNum).toArray();
for(int i:num){
System.out.print(i + " ");
}
}
}
Testcases:
Input: {10,50,90,20,5,90,22,5}
Output: 10 50 20 22
Input: {10, 50, 20, 90, 22}
Output: 50 20 22
Arrays are something whose length/size can't be changed. They are created with a fixed size which can't be modified. If you want to use the functionality you mentioned, it's better to go for a list, preferably ArrayList
List<Integer> list= new ArrayList<Integer>();
You can always return an ArrayList as an array if need be. You can search for functions like
list.toArray()

Maximum items to retain after removing k items from array

I have an array of numbers, I want to delete k items such that they are next to each other such that the number of distinct elements in the array after deletion is maximum.
Example:
Input:
arr = [2,3,1,1,2]
k = 2
Ans: 3
Explanation:
Remove elements at index 3 & 4 which are 1 and 2 in array. Then array becomes [2,3,1] so it has 3 different elements.
This is my code:
int delete(int[] arr, int k) {
int n = arr.length;
int max = -1;
for (int i = 0; i < n - k + 1; i++) {
Set<Integer> set = new HashSet<>();
for (int j = 0; j < n; j++) {
if (i == j) {
j = j + k - 1;
} else {
set.add(arr[j]);
}
}
max = Math.max(set.size(), max);
}
return max;
}
How to reduce the time complexity for this problem. Because the size of array can be upto 1000000 and also the size of k is upto the array size. Each arraycelement can be upto 1000000
Here's a solution in O(N): It uses a map containing the number of occurrences of each number:
You start by filling the map with the elements from k to n-1 (in other words, the array without the first k elements), then you iterate and the first element and remove the last.
static int delete2(int[] arr, int k) {
int n = arr.length;
Map<Integer,Integer> map = new HashMap<>();
for (int i = k; i < n; i++) {
Integer value = arr[i];
if (!map.containsKey(value)) {
map.put(value, 1);
} else {
map.put(value, map.get(value)+1);
}
}
int max = map.size();
for (int i = 0; i < n-k; ++i) {
Integer value = arr[i];
if (!map.containsKey(value)) {
map.put(value, 1);
} else {
map.put(value, map.get(value)+1);
}
value = arr[i+k];
Integer count = map.get(value);
if (count == 1) {
map.remove(value);
} else {
map.put(value, count-1);
}
max = Math.max(map.size(), max);
}
return max;
}
If I understand correctly, you want to delete k adjacent elements such that the resulting set of set of arr - k elements is as large as possible.
Just test each candidate set (there are n sets to try).
So something like this should work
int delete(int[] arr, int k) {
int n = arr.length;
int max = -1;
Set<Integer> rem = new HashSet<>();
for (int i= 0; i<n; i++) {
rem.add(arr[i]);
}
for (int i = 0; i < n - k + 1; i++) {
Set<Integer> candidate = new HashSet<>();
for (int j = i; j < i + k; j++) {
candidate.add(arr[j]);
}
rem.removeAll(candidate);
if (rem.size() > max){
max = rem.size();
} else {
candidate.forEach((e) -> {
rem.add(e);
});
}
}
// you could also return the actual candidate set that produces the maximum
return max;
}
The set operation in the loop are all order k. So resulting time is order n*k.
int delete(int[] arr, int k) {
// step 1: traverse the array exactly once and make a hashtable
// with counts of each unique element
Map<Integer, Integer> elemCounts = new HashMap<>();
for (int e : arr) {
int ct = elemCounts.getOrDefault(e, 0);
elemCounts.put(e, ct + 1);
}
// step 2: traverse through the array exactly once more, and
// keep track of the adjacent elements which produce the least
// disturbance.
// step 2a: for the first k elements, see what removing them would
// do to the overall uniqueness of the array
int numPermanentRemovals = 0;
for (int i = 0; i < k; i++) {
int ct = elemCounts.get(arr[i]);
elemCounts.put(arr[i], ct - 1);
if (ct - 1 == 0) {
numPermanentRemovals += 1;
}
}
// step 2b: for the remainder of the array, track the rolling
// numPermanentRemovals for k adjacent elements
int minDisruption = numPermanentRemovals;
int minDisruptionIndex = 0;
for (int i = k; i < arr.length; i++) {
// put back the element at the start of the current window
int stct = elemCounts.get(arr[i - k]);
elemCounts.put(arr[i - k], stct + 1);
if (stct == 0) {
numPermanentRemovals -= 1;
}
// take out the element being added to the new window
int edct = elemCounts.get(arr[i]);
elemCounts.put(arr[i], edct - 1);
if (edct - 1 == 0) {
numPermanentRemovals += 1;
}
// if this minimum disruption index is a new floor, then
// replace the original
if (numPermanentRemovals < minDisruption) {
minDisruption = numPermanentRemovals;
minDisruptionIndex = i - k + 1;
}
// short-circuit if we find a perfect solution
if (minDisruption == 0) {
break;
}
}
return minDisruptionIndex;
}

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;
}

Efficient way to count unique pairs in int array

This is my first post, hope it complies with posting guidelines of the site.
First of all a generic thanks to all the community: reading you from some months and learned a lot :o)
Premise: I'm a first years student of IT.
Here's the question: I'm looking for an efficient way to count the number of unique pairs (numbers that appear exactly twice) in a given positive int array (that's all I know), e.g. if:
int[] arr = {1,4,7,1,5,7,4,1,5};
the number of unique pairs in arr is 3 (4,5,7).
I have some difficulties in... evaluating the efficiency of my proposals let's say.
Here's the first code I did:
int numCouples( int[] v ) {
int res = 0;
int count = 0;
for (int i = 0 ; i < v.length; i++){
count = 0;
for (int j = 0; j < v.length; j++){
if (i != j && v[i] == v[j]){
count++;
}
}
if (count == 1){
res++;
}
}
return res/2;
}
This shoudn't be good cause it checks the whole given array as many times as the number of elements in the given array... correct me if I'm wrong.
This is my second code:
int numCouples( int[] v) {
int n = 0;
int res = 0;
for (int i = 0; i < v.length; i++){
if (v[i] > n){
n = v[i];
}
}
int[] a = new int [n];
for (int i = 0; i < v.length; i++){
a[v[i]-1]++;
}
for (int i = 0; i < a.length; i++){
if (a[i] == 2){
res++;
}
}
return res;
}
I guess this should be better than the first one since it checks only 2 times the given array and 1 time the n array, when n is the max value of the given array. May be not so good if n is quite big I guess...
Well, 2 questions:
am I understanding good how to "measure" the efficiency of the code?
there's a better way to count the number of unique pairs in a given array?
EDIT:
Damn I've just posted and I'm already swamped by answers! Thanks! I'll study each one with care, for the time being I say I don't get those involving HashMap: out of my knowledge yet (hence thanks again for the insight:o) )
public static void main(String[] args) {
int[] arr = { 1, 4, 7, 1, 5, 7, 4, 1, 5 };
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i = 0; i < arr.length; i++) {
Integer count = map.get(arr[i]);
if (count == null)
map.put(arr[i], 1);
else
map.put(arr[i], count + 1);
}
int uniqueCount = 0;
for (Integer i : map.values())
if (i == 2)
uniqueCount++;
System.out.println(uniqueCount);
}
Well, here's another answer to your's 2 questions:
am I understanding good how to "measure" the efficiency of the code?
There are various ways to measure efficiency of the code. First of all, people distinguish between memory efficiency and time efficiency. The usual way to count all these values is to know, how efficient are the building blocks of your algorithm. Have a look at the wiki.
For instance, sorting using quicksort would need n*log(n) operations. Iterating through the array would need just n operations, where n is number of elements in the input.
there's a better way to count the number of unique pairs in a given array?
Here's another solution for you. The complixity of this one would be: O(n*log(n)+n), where O(...) is Big O notation.
import java.util.Arrays;
public class Ctest {
public static void main(String[] args) {
int[] a = new int[] { 1, 4, 7, 1, 7, 4, 1, 5, 5, 8 };
System.out.println("RES: " + uniquePairs(a));
}
public static int uniquePairs(int[] a) {
Arrays.sort(a);
// now we have: [1, 1, 1, 4, 4, 5, 5, 7, 7]
int res = 0;
int len = a.length;
int i = 0;
while (i < len) {
// take first number
int num = a[i];
int c = 1;
i++;
// count all duplicates
while(i < len && a[i] == num) {
c++;
i++;
}
System.out.println("Number: " + num + "\tCount: "+c);
// if we spotted number just 2 times, increment result
if (c == 2) {
res++;
}
}
return res;
}
}
public static void main(String[] args) {
int[] arr = {1,4,7,1,7,4,1,5};
Map<Integer, Integer> counts = new HashMap<Integer,Integer>();
int count = 0;
for(Integer num:arr){
Integer entry = counts.get(num);
if(entry == null){
counts.put(num, 1);
}else if(counts.get(num) == 1){
count++;
counts.put(num, counts.get(num) + 1);
}
}
System.out.println(count);
}
int [] a = new int [] {1, 4, 7, 1, 7, 4, 1, 5, 1, 1, 1, 1, 1, 1};
Arrays.sort (a);
int res = 0;
for (int l = a.length, i = 0; i < l - 1; i++)
{
int v = a [i];
int j = i + 1;
while (j < l && a [j] == v) j += 1;
if (j == i + 2) res += 1;
i = j - 1;
}
return res;
you can use HashMap for easy grouping. here is my code.
int[] arr = {1,1,1,1,1,1,4,7,1,7,4,1,5};
HashMap<Integer,Integer> asd = new HashMap<Integer, Integer>();
for(int i=0;i<arr.length;i++)
{
if(asd.get(arr[i]) == null)
{
asd.put(arr[i], 1);
}
else
{
asd.put(arr[i], asd.get(arr[i])+1);
}
}
//print out
for(int key:asd.keySet())
{
//get pair
int temp = asd.get(key)/2;
System.out.println(key+" have : "+temp+" pair");
}
added for checking the unique pair, you can delete the print out one
//unique pair
for(int key:asd.keySet())
{
if(asd.get(key) == 2)
{
System.out.println(key+" are a unique pair");
}
}
after some time another solution, which should work great.
public getCouplesCount(int [] arr) {
int i = 0, i2;
int len = arr.length;
int num = 0;
int curr;
int lastchecked = -1;
while (i < len-1) {
curr = arr[i];
i2 = i + 1;
while (i2 < len) {
if (curr == arr[i2] && arr[i2] != lastchecked) {
num++; // add 1 to number of pairs
lastchecked = curr;
i2++; // iterate to next
} else if (arr[i2] == lastchecked) {
// more than twice - swap last and update counter
if (curr == lastchecked) {
num--;
}
// swap with last
arr[i2] = arr[len-1];
len--;
} else {
i2++;
}
i++;
}
return num;
}
i am not shure if it works, but it is more effective than sorting the array first, or using hashmaps....
A Java8 parallel streamy version which uses a ConcurrentHashMap
int[] arr = {1,4,7,1,5,7,4,1,5};
Map<Integer,Long> map=Arrays.stream(arr).parallel().boxed().collect(Collectors.groupingBy(Function.identity(),
ConcurrentHashMap::new,Collectors.counting()));
map.values().removeIf(v->v!=2);
System.out.println(map.keySet().size());
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int arr[9] = {1,4,7,1,5,7,4,1,5}; // given array
int length=9; // this should be given
int count=0;
map<int,int> m;
for(int i=0;i<length;i++)
m[arr[i]]++;
cout<<"List of unique pairs : ";
for(auto it=m.begin();it!=m.end();it++)
if(it->second==2)
{
count++;
cout<<it->first<<" ";
}
cout<<"\nCount of unique pairs(appears exactly twice) : "<<count;
return 0;
}
OUTPUT :
List of unique pairs : 4 5 7
Count of unique pairs(appears exactly twice) : 3
Time Complexity : O(N) where N is the number of elements in array
Space Complexity : O(N) total no. of unique elements in array always <=N
var sampleArray = ['A','B','C','D','e','f','g'];
var count = 0;
for(var i=0; i<=sampleArray.length; i++) {
for(var j=i+1; j<sampleArray.length; j++) {
count++;
console.log(sampleArray[i] , sampleArray[j]);
}
}
console.log(count);
This is the simple way I tried.

how to get the most common character in an array?

Suppose I have an integer array like this:
{5,3,5,4,2}
and I have a method which returns the most common character
public int highestnumber(String[] num) {
int current_number = Integer.parseInt(num[0]);
int counter = 0;
for (int i = 1; i < num.length; ++i) {
if (current_number == Integer.parseInt(num[i])) {
++counter;
} else if (counter == 0) {
current_number = Integer.parseInt(num[i]);
++counter;
} else {
--counter;
}
}
return current_number;
}
but if I have multiple common character then i need to get the number which is closest to one(1), like if i have an array like this:
{5,5,4,4,2};
then the method should return 4, what should I do for this?
As per what I understand your question,
What you have to done is,
1. Create ArrayList from your int[]
2. Use HashMap for find duplicates, which one is unique
3. Sort it as Ascending order,
4. First element is what you want..
EDIT: Answer for your question
int[] arr = {5, 4, 5, 4, 2};
ArrayList<Integer> resultArray = new ArrayList<Integer>();
Set<Integer> set = new HashSet<Integer>();
for (int i = 0; i < arr.length; i++)
{
if (set.contains(arr[i]))
{
System.out.println("Duplicate value found at index: " + i);
System.out.println("Duplicate value: " + arr[i]);
resultArray.add(arr[i]);
}
else
{
set.add(arr[i]);
}
}
Collections.sort(resultArray);
for (int i = 0; i < resultArray.size(); i++)
{
Log.e("Duplicate Values:", resultArray.get(i) + "");
}
Your need is,
int values = resultArray.get(0);
Sort the array then count runs of values.
Fast way.
Create a counter int array one element for each number. Go through the array once and increment corresponding counter array for each number. Set highest number to first counter element then go through and change highest number to current element only if it is bigger than highest number, return highest number.
public int highestNumber(String[] num){
int[] count = new int[10];
int highest_number = 0;
int highest_value = 0;
for(int i = 0; i < num.length; i++)
count[Integer.parseInt(num[i])]++;;
for(int i = 0; i < count.length; i++)
if(count[i] > highest_value){
highest_number = i;
highest_value = count[i];
}
return highest_number;
}
10x slower but without other array.
Create three ints one for number and two for counting. Go through the array once for each int and increment current counting each time it shows up, if bigger that highest count, set to highest count and set highest number to current count. Return highest number.
public int highestNumber(String[] num){
int highest_number = 0;
int highest_value = 0;
int current_value = 0;
for(int i = 0; i < 10; i++){
for(int j = 0; j < num.length; j++)
if(i == Integer.parseInt(num[j]))
current_value++;
if(current_value > highest_value){
highest_value = current_value;
highest_number = i;
}
current_value = 0;
}
return highest_number;
}
The first is obviously much faster but if for whatever reason you don't want another array the second one works too.
You can also try this:
import java.util.TreeMap;
public class SmallestFrequentNumberFinder {
public static int[] stringToIntegerArray(String[] stringArray) {
int[] integerArray = new int[stringArray.length];
for (int i = 0; i < stringArray.length; i++) {
integerArray[i] = Integer.parseInt(stringArray[i]);
}
return integerArray;
}
public static int getSmallestFrequentNumber(int[] numbers) {
int max = -1;
Integer smallestFrequentNumber = null;
TreeMap<Integer, Integer> frequencyMaper = new TreeMap<Integer, Integer>();
for (int number : numbers) {
Integer frequency = frequencyMaper.get(number);
frequencyMaper.put(number, (frequency == null) ? 1 : frequency + 1);
}
for (int number : frequencyMaper.keySet()) {
Integer frequency = frequencyMaper.get(number);
if (frequency != null && frequency > max) {
max = frequency;
smallestFrequentNumber = number;
}
}
return smallestFrequentNumber;
}
public static void main(String args[]) {
String[] numbersAsString = {"5", "5", "4", "2", "4", "4", "2", "2"};
final int[] integerArray = stringToIntegerArray(numbersAsString);
System.out.println(getSmallestFrequentNumber(integerArray));
}
}

Categories

Resources