Need explanation on differences of permutation algorithms - java

I'm currently working on a problem that asks me to find the millionth lexicographic permutation of 0,1,2,3,4,5,6,7,8,9. I thought of a very crude solution at first glance that had a complexity of around O(n^3)
public static String permute(char[] a){
ArrayList<String> array = new ArrayList<String>();
int counter = 1;
for (int i = 0; i < a.length; i++){
array[counter] += a[i];
for (int j = 0; j < i; j++){
array[counter] += a[j];
for(int k = a.length; k > i; k--){
array[counter] += a[k];}counter++;}
}
}
The code may not be perfect but the idea is that a single digit is selected and then moves to the end of an array. The second array creates the numbers behind the selected digit and the third array creates numbers after it. This seems like a terrible algorithm and i remembered a past algorithm that's like this.
public static HashSet<String> Permute(String toPermute) {
HashSet<String> set = new HashSet<String>();
if (toPermute.length() <= 1 )
set.add(toPermute);
else {
for (int i = 0; i < toPermute.length(); i++ )
for (String s: Permute(toPermute.substring(0,i)+ toPermute.substring(i+1)))
{
set.add(toPermute.substring(i,i+1)+s);}
}
return set;
}
}
The problem is that this algorithm uses unordered sets and I have no idea about how it can become ordered enough for me to find the millionth permutation. I also do not know the complexity other than the fact it could be O(n^2) because it calls itself n times and then unstacks.

A couple of things in general about your code above:
You should implement to interfaces and not concrete classes I.e. List<String> array = .... Similarly with your Set.
Array's start at index 0, you are starting your counter at index 1.
Finally to answer your question there is a brute force way and a more elegant way that uses some principles in math. Have a look at this site which explains the approaches.

It seems to me (1) which permutation is the millionth depends absolutely on the order you use, and (2) permutations of this sort are ripe problems for recursion. I would write this as a recursive program and increment the count for each iteration. [was that your question? I didn't really see a question...]

Here is a solution that is more efficient:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class P24 {
static final int digits[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
static List<Integer> remainedDigits = new ArrayList(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
static final int factorials[] = new int[digits.length + 1];
static final int N = 1000_000;
static int low = -1;
static int lowIndex = -1;
static int highIndex = -1;
public static void main(String args[]) {
populateFactorials(digits.length);
validateN(N);
identifyMargins();
int n = N; // it will be changed
int fixedDigits = digits.length - highIndex;
String result = "";
for (int i = 0; i < fixedDigits; i++) {
result += remainedDigits.get(0);
remainedDigits.remove(0);
}
for (int i = fixedDigits; i < digits.length; i++) {
int pos = 0;
int firstDigit = remainedDigits.get(pos);
low = factorials[lowIndex];
while (n - low > 0) {
pos++;
n -= low;
}
lowIndex--;
result += remainedDigits.get(pos);
remainedDigits.remove(pos);
}
System.out.println(result);
}
private static void validateN(int n) {
if (n < 0 || n > factorials[factorials.length - 1]) {
System.out.println("The input number is not valid");
System.exit(0);
}
}
private static void identifyMargins() {
for (int i = 0; i < factorials.length - 1; i++) {
if (factorials[i] <= N && N < factorials[i + 1]) {
lowIndex = i;
highIndex = i + 1;
}
}
}
private static void populateFactorials(int max) {
for (int i = 0; i <= max; i++) {
factorials[i] = fact(i);
}
}
private static int fact(int x) {
if (x == 0 || x == 1) {
return 1;
}
int p = 1;
for (int i = 2; i <= x; i++) {
p *= i;
}
return p;
}
}
Time: 305 microseconds.
Explanation:
Because the total number of permutations for {a1, ..., an} is n!, I decided that I need a factorials array. I stored in it: {0!, ..., 10!}.
I identified where is the number placed in this sequence, and for our case (N = 1000000) it is between 9! and 10!. If it was lower than 9! I add a padding of fixedDigits digits taken from the remainedDigits array.
Because the number is bigger than 9!, I count how many times I can extract 9! from the number and the result helps me to obtain the first digit. Then, I have a similar approach for 8!, 7!, etc.
The above explanation is based on the following simple observation. If we have a set {a1,...,ai,...,an} and we fix a1, ..., ai, we can obtain (n-i)! different strings.
Notice that if you use:
static List<Integer> remainedDigits = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
you cannot remove elements from the list.
`

Related

Largest number in k swaps

Given a number K and string str of digits denoting a positive integer, build the largest number possible by performing swap operations on the digits of str at most K times.
Example 1:
Input:
K = 4
str = "1234567"
Output:
7654321
Explanation:
Three swaps can make the
input 1234567 to 7654321, swapping 1
with 7, 2 with 6 and finally 3 with 5
I am trying to solve it using two loops. For every index i, I am finding the largest integer between (i+1)th index to (N-1)th index, where N is the size of string. If the largest number is greater than arr[i], then swap it. Below is the code I have written.
public static String findMaximumNum(String str, int k) {
int N = str.length();
int[] arr = new int[N];
for (int i = 0; i < N; i++) {
arr[i] = Integer.valueOf(str.charAt(i) + "");
}
int swaps = 0;
for (int i = 0; i < N - 1; i++) {
if(swaps == k)
break;
int maxIndex = findMaxInRange(arr, i + 1, N - 1);
if (arr[i] < arr[maxIndex]) {
swap(arr, i, maxIndex);
swaps++;
}
}
String out = "";
for (int i = 0; i < N; i++) {
out = out + arr[i] + "";
}
return out;
}
private static int findMaxInRange(int[] arr, int i, int j) {
int max = Integer.MIN_VALUE;
int maxIndex = i;
for (int k = i; k <= j; k++) {
if (arr[k] >= max) {
max = arr[k];
maxIndex = k;
}
}
return maxIndex;
}
private static void swap(int[] arr, int i, int j) {
System.out.println("swapping "+arr[i]+" and "+arr[j]+" from "+Arrays.toString(arr));
int ch = arr[i];
arr[i] = arr[j];
arr[j] = ch;
}
public static void main(String[] args) {
System.out.println(findMaximumNum("61892795431", 4));
}
It is failing for few test cases. One of the test cases where it is failing is
Input:
4
61892795431
Its Correct output is:
99876215431
And MyCode's output is:
99876125431
I am not able to figure out how the output is '99876215431' and what is wrong in my approach. Please help me understand. Thanks a lot in advance :)
The basic steps how to solve this problem:
0. cast string to array of integers
make a loop K times
in this loop go from i+1 (LOOP VAR) to end of a collection and search for higher value
when we find higher value then collection[i], we will remember its value and index on witch it is. Important thing to note is that we want to swap biggest number but i also has to be last possible number.
at the end of iteration we swap the elements (i with best index)
we are done so all its left is convert our int list back to string.
code: (its python because java is pain)
def sort(swaps, string):
l = list(map(int, list(string)))
print(l)
for i in range(swaps):
best = l[i] + 1
bestIndex = i
for j in range(i+1, len(l)):
if best <= l[j]:
best = l[j]
bestIndex = j
print(i, bestIndex)
l[i], l[bestIndex] = l[bestIndex], l[i]
return "".join(map(str, l))
print(sort(4, "61892795431"))
Your code is correct. The problem comes from the parameter 4 (max number of swaps). If you use 10, the sorting is completed successfully.
Maybe the deeper problems comes from the fact that you are comparing the swaps of your algorithm with the swaps that you would do efficiently to sort the numbers. Your algorithm may work but probably it is not the most efficient, so the number of swaps needed is above the optimum.

Finding pairs in an sorted array with big values

I'm currently stuck on a problem with finding pairs in an sorted array with big values. Example: if i get the array sortedarr=[1, 2, 2, 2, 2, 2, 2, 3] as input. It should return pairs = 15.
I have written the below code, which works in O(N2) for both unsorted and sorted arrays. But the code is very basic and i would like for it to be able to manage sorted arrays in an faster time. I guess that the easiest way is to just compare the current element with the one next to it. But i don't know how i can do that. How can i manage to change the code so it will fulfill my requirements?
public static int countpairs(int[] sortedarr) {
int N = sortedarr.length;
int pairs = 0;
for (int i = 0; i < N; i++) {
for (int j = i + 1; j < N; j++) {
if (sortedarr[i] == sortedarr[j]) {
pairs++;
}
}
}
return pairs;
}
}
Here is one way to do it in O(N), instead of O(N^2):
public static void main(String[] args) {
int[] a= new int[] {1, 2, 2, 2, 2, 2, 2, 3};
int i = 0;
int n = a.length;
int ans = 0;
while(i < n - 1) {
int dupeCount = 1;
while(i < n - 1 && a[i] == a[i + 1]) {
dupeCount++;
i++;
}
if(dupeCount > 1) {
ans = ans + (dupeCount * (dupeCount-1) / 2);
}
i++;
}
System.out.println(ans);
}
Outputs 15.
The idea is somewhat similar to what Bubble sort uses. We just need to look at each item and its successor in the array to see if it is a duplicate or not. From there, the number of distinct pairs that can be created is just C(dupeCount,2) = dupeCount * (dupeCount - 1) / 2. And we sum all such occurrences to get the final answer.

Java - counting most common elements

The task is to write a code which counts the most common number. For example A[1,2,4,4,4,5,6,7,4] would be 4 with 4 counts.
I need to keep this code simple because I just tried to implement my code from algorithm and data structure to java.
My idea was this but somehow I never reach the last condition.
public class countingNumbers{
public static void main(String []args){
System.out.print(counting(new int[]{1,1,1,2,3,4,4,4,4,5,6}));
}
public static int counting(int[] x){
int memory = 0;
int counter = 0;
int mostCommon = 0;
for(int i = 0; i < x.length-1;i++){
for(int j = i+1; j < x.length-1; j++){
if(x[i] == x[j]){
counter = counter +1;
}
else if(j == x.length-1 && counter >= memory){
mostCommon = x[i];
memory = counter;
counter = 0;
}
}
}
return mostCommon;
}
}
-> Thanks in advance for all your answers, I appreciate that. I'am just looking for the logic not for stream, api's or whatever.
I tried do handwrite the code and the implementation in java is only for myself to see if it worked out but unfortunately it doesn't.
Update - the right Solution is this:
public class countingNumbers{
public static void main(String []args){
System.out.print(counting(new int[]{1,2,2,2,6,2}));
}
public static int counting(int[] x){
int memory = 0;
int counter = 1;
int mostCommon = 0;
for(int i = 0; i < x.length;i++){
for(int j = i+1; j <= x.length-1; j++){
if(x[i] == x[j]){
counter = counter + 1;
}
if(j == x.length-1 && counter >= memory){
mostCommon = x[i];
memory = counter;
counter = 1;
}
}counter = 1;
} return memory;
}
}
I'd stream the array and collect it in to a map the counts the occurrences of each element, and then just return the one with the highest count:
/**
* #return the element that appears most in the array.
* If two or more elements appear the same number of times, one of them is returned.
* #throws IllegalArgumentException If the array is empty
*/
public static int counting(int[] x){
return Arrays.stream(x)
.boxed()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.max(Map.Entry.comparingByValue())
.map(Map.Entry::getKey)
.orElseThrow(() -> new IllegalArgumentException("x must not be empty"));
}
If you are good with stream api.. or just for educational goals there is stream solution with groupingBy:
Integer[] arr = {1, 1, 1, 2, 3, 4, 4, 4, 4, 5, 6};
Map<Integer, Long> map = Arrays.stream(arr)
.collect(Collectors.groupingBy(o -> o, Collectors.counting()));
Integer common = map.entrySet().stream()
.max(Comparator.comparingLong(Map.Entry::getValue))
.map(Map.Entry::getKey).get();
System.out.println(common);
Update: If stream is not relevant for you:
It can be done by foor-loop but still it's quite convenient to use Map here:
public static int counting(int[] x) {
Map<Integer, Long> map = new HashMap<>(); // key is a number, value is how often does it appear in the array
for (int number : x) {
if (map.get(number) != null) {
map.put(number, map.get(number) + 1);
} else {
map.put(number, 1L);
}
}
return Collections.max(map.entrySet(), Map.Entry.comparingByKey()).getKey();
}
Note: there are many ways to get key from map associated with max value. See here to find the most suitable way: Finding Key associated with max Value in a Java Map
Also if else statement can be replaced by merge method from java8:
map.merge(number, 1L, (a, b) -> a + b);
Take a look at these two lines:
for (int j = i + 1; j < x.length - 1; j++) {
and
} else if (j == x.length - 1 && counter >= memory)
You loop while j is strictly less than x.length - 1, but your else if only triggers when j is exactly equal to x.length - 1. So you can never hit the code in your else if block.
Also, your counter should really start at one, since you're counting the number of entries that match the one you're looking at, so you skip counting the first one. But since you're not outputting the counter anywhere, it's not terribly relevant I guess.
So to fix your code, change your inner for loop to go to j <= x.length - 1.
Declare two variables to hold the most common number and its frequency:
int mostCommon =Integer.MIN_VALUE;
int highFreq = 0;
Itereate over your array. For each element iterate over your array again and count its frequency. If current count is greater than highFreq update mostCommon by seting it to current element and set highFreq current count. Example:
public class countingNumbers{
public static void main(String[] args) {
int[] res = counting(new int[]{6, 4, 5, 4, 5, 6, 4, 3, 2});
System.out.println("most common number is: " + res[0] + " with " + res[1] + " counts");
}
public static int[] counting(int[] x) {
int mostCommon = Integer.MIN_VALUE;
int highFreq = 0;
for (int i = 0; i < x.length; i++) {
int currFreq = 0;
for (int j = 0; j < x.length; j++) {
if (x[i] == x[j]) {
currFreq++;
}
}
if (highFreq < currFreq) {
highFreq = currFreq;
mostCommon = x[i];
}
}
return new int[]{mostCommon, highFreq};
}
}

Printing out the least occurring elements in an array

OK, so I found this question from a few days ago but it's on hold and it won't let me post anything on it.
***Note: The values or order in the array are completely random. They should also be able to be negative.
Someone recommended this code and was thumbed up for it, but I don't see how this can solve the problem. If one of the least occurring elements isn't at the BEGINNING of the array then this does not work. This is because the maxCount will be equal to array.length and the results array will ALWAYS take the first element in the code written below.
What ways are there to combat this, using simple java such as below? No hash-maps and whatnot. I've been thinking about it for a while but can't really come up with anything. Maybe using a double array to store the count of a certain number? How would you solve this? Any guidance?
public static void main(String[] args)
{
int[] array = { 1, 2, 3, 3, 2, 2, 4, 4, 5, 4 };
int count = 0;
int maxCount = 10;
int[] results = new int[array.length];
int k = 0; // To keep index in 'results'
// Initializing 'results', so when printing, elements that -1 are not part of the result
// If your array also contains negative numbers, change '-1' to another more appropriate
for (int i = 0; i < results.length; i++) {
results[i] = -1;
}
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array.length; j++) {
if (array[j] == array[i]) {
count++;
}
}
if (count <= maxCount) { // <= so it admits number with the SAME number of occurrences
maxCount = count;
results[k++] = array[i]; // Add to 'results' and increase counter 'k'
}
count = 0; // Reset 'count'
}
// Printing result
for (int i : results) {
if (i != -1) {
System.out.println("Element: " + i + ", Number of occurences: " + maxCount);
}
}
}
credit to: https://stackoverflow.com/users/2670792/christian
for the code
I can't thumbs up so I'd just like to say here THANKS EVERYONE WHO ANSWERED.
You can also use an oriented object approach.
First create a class Pair :
class Pair {
int val;
int occ;
public Pair(int val){
this.val = val;
this.occ = 1;
}
public void increaseOcc(){
occ++;
}
#Override
public String toString(){
return this.val+"-"+this.occ;
}
}
Now here's the main:
public static void main(String[] args) {
int[] array = { 1,1, 2, 3, 3, 2, 2, 6, 4, 4, 4 ,0};
Arrays.sort(array);
int currentMin = Integer.MAX_VALUE;
int index = 0;
Pair[] minOcc = new Pair[array.length];
minOcc[index] = new Pair(array[0]);
for(int i = 1; i < array.length; i++){
if(array[i-1] == array[i]){
minOcc[index].increaseOcc();
} else {
currentMin = currentMin > minOcc[index].occ ? minOcc[index].occ : currentMin;
minOcc[++index] = new Pair(array[i]);
}
}
for(Pair p : minOcc){
if(p != null && p.occ == currentMin){
System.out.println(p);
}
}
}
Which outputs:
0-1
6-1
Explanation:
First you sort the array of values. Now you iterate through it.
While the current value is equals to the previous, you increment the number of occurences for this value. Otherwise it means that the current value is different. So in this case you create a new Pair with the new value and one occurence.
During the iteration you will keep track of the minimum number of occurences you seen.
Now you can iterate through your array of Pair and check if for each Pair, it's occurence value is equals to the minimum number of occurences you found.
This algorithm runs in O(nlogn) (due to Arrays.sort) instead of O(n²) for your previous version.
This algorithm is recording the values having the least number of occurrences so far (as it's processing) and then printing all of them alongside the value of maxCount (which is the count for the value having the overall smallest number of occurrences).
A quick fix is to record the count for each position and then only print those whose count is equal to the maxCount (which I've renamed minCount):
public static void main(String[] args) {
int[] array = { 5, 1, 2, 2, -1, 1, 5, 4 };
int[] results = new int[array.length];
int minCount = Integer.MAX_VALUE;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array.length; j++) {
if (array[j] == array[i]) {
results[i]++;
}
}
if (results[i] <= minCount) {
minCount = results[i];
}
}
for (int i = 0; i < results.length; i++) {
if (results[i] == minCount) {
System.out.println("Element: " + i + ", Number of occurences: "
+ minCount);
}
}
}
Output:
Element: 4, Number of occurences: 1
Element: 7, Number of occurences: 1
This version is also quite a bit cleaner and removes a bunch of unnecessary variables.
This is not as elegant as Iwburks answer, but I was just playing around with a 2D array and came up with this:
public static void main(String[] args)
{
int[] array = { 3, 3, 3, 2, 2, -4, 4, 5, 4 };
int count = 0;
int maxCount = Integer.MAX_VALUE;
int[][] results = new int[array.length][];
int k = 0; // To keep index in 'results'
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array.length; j++) {
if (array[j] == array[i]) {
count++;
}
}
if (count <= maxCount) {
maxCount = count;
results[k++] = new int[]{array[i], count};
}
count = 0; // Reset 'count'
}
// Printing result
for (int h = 0; h < results.length; h++) {
if (results[h] != null && results[h][1] == maxCount ) {
System.out.println("Element: " + results[h][0] + ", Number of occurences: " + maxCount);
}
}
Prints
Element: -4, Number of occurences: 1
Element: 5, Number of occurences: 1
In your example above, it looks like you are only using ints. I would suggest the following solution in that situation. This will find the last number in the array with the least occurrences. I assume you don't want an object-oriented approach either.
int [] array = { 5, 1, 2, 40, 2, -1, 3, 2, 5, 4, 2, 40, 2, 1, 4 };
//initialize this array to store each number and a count after it so it must be at least twice the size of the original array
int [] countArray = new int [array.length * 2];
//this placeholder is used to check off integers that have been counted already
int placeholder = Integer.MAX_VALUE;
int countArrayIndex = -2;
for(int i = 0; i < array.length; i++)
{
int currentNum = array[i];
//do not process placeholders
if(currentNum == placeholder){
continue;
}
countArrayIndex = countArrayIndex + 2;
countArray[countArrayIndex] = currentNum;
int count = 1; //we know there is at least one occurence of this number
//loop through each preceding number
for(int j = i + 1; j < array.length; j++)
{
if(currentNum == array[j])
{
count = count + 1;
//we want to make sure this number will not be counted again
array[j] = placeholder;
}
}
countArray[countArrayIndex + 1] = count;
}
//In the code below, we loop through inspecting each number and it's respected count to determine which one occurred least
//We choose Integer.MAX_VALUE because it's a number that easily indicates an error
//We did not choose -1 or 0 because these could be actual numbers in the array
int minNumber = Integer.MAX_VALUE; //actual number that occurred minimum amount of times
int minCount = Integer.MAX_VALUE; //actual amount of times the number occurred
for(int i = 0; i <= countArrayIndex; i = i + 2)
{
if(countArray[i+1] <= minCount){
minNumber = countArray[i];
minCount = countArray[i+1];
}
}
System.out.println("The number that occurred least was " + minNumber + ". It occured only " + minCount + " time(s).");

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.

Categories

Resources