I am almost at end of code. I am supposed to find number of times numbers appeared in a given array. The for loop is not working as expected.
They contain numbers in an array, I am able to extract individual numbers which are repeating. Then I am trying to find how many time that an individual number is appeared by using for loop and store it into another array which will give me the count.
Everything is declared like d[], b[], c[]
for (i = 0; i < k; i++) {
for (j = 0; j < l; j++) {
if (d[i] == c[j]) {
b[i]++;
}
}
}
Expected output should be, like if if's condition to be true, b[i] should increment the number of times a number appeared but it is giving me array of ones, like it is only passing through the if condition once per i.
You can do that using for example a Hashtable saving the array numbers as keys and the number of repetitions as value. This function receive an array of Integers, and returns the Hashtable with the repetitions:
public static Hashtable<Integer, Integer> getRepitedNumbers( Integer[] numbers) {
Hashtable<Integer, Integer> Result = new Hashtable<Integer, Integer>();
for( int i = 0; i < numbers.length; i++) {
if( Result.containsKey( numbers[ i])) {
//If the current number is saved in the hashtable, you need to increment the
//value (repetitions counter for this number)
Result.put( numbers[ i], Result.get( numbers[ i]) + 1);
} else {
//If the current number doesn't exist, is the first occurrence.
Result.put( numbers[ i], 1);
}
}
//At the end you have a hashtable with each number and the number of occurrences
return Result;
}
https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html
public static void main(String[] args) {
List<Integer> listOfIntegers = Arrays.asList(1, 2, 3, 1, 2, 3, 3, 3, 3, 8, 9);
Map<Integer, Long> integerToCount = listOfIntegers.stream().collect(Collectors.groupingBy(it -> it, Collectors.counting()));
System.out.println(integerToCount);
}
What about using Streams:
public static Map<Integer, Long> countItems(Integer[] arr) {
return Arrays.stream(arr).collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
}
In an array A of size 2N, there are N+1 unique elements, and exactly one of these elements is repeated N times.
Return the element repeated N times.
I am trying to solve this algorithm but I can't seem to figure out why my count keeps getting reset. Any inputs will really be appreciated.
public class RepeatedElementInSize2NArray {
public static void main(String[] args) {
int[] inputArr = new int[] {1,2,3,3};
int repeatedElement = findRepeatedElement(inputArr);
System.out.println("Repeated element : "+repeatedElement);
}
public static int findRepeatedElement(int[] inputArr) {
Map<Integer, Integer> repeatedElementMap = new HashMap<Integer, Integer>();
int count = 0;
for (int i = 0; i < inputArr.length; i++) {
if (repeatedElementMap.containsKey(inputArr[i])) {
count = repeatedElementMap.get(inputArr[i]);
repeatedElementMap.put(inputArr[i], count++);
} else {
repeatedElementMap.put(inputArr[i], 1);
}
}
int length = inputArr.length;
int repeatedElement = 0;
if (repeatedElementMap.containsValue(length % 2)) {
repeatedElement = repeatedElementMap.get(length % 2);
}
return repeatedElement;
}
}
It should be ++count instead of count++ in the line repeatedElementMap.put(inputArr[i], count++);
The reason is that the latter returns the value of count first before incrementing the value, whereas the former increments the value first and then returns it.
The problem is in the line repeatedElementMap.put(inputArr[i], count++);
The expression count++ will increment the value of count, but return the old value of count.
So the code repeatedElementMap.put(inputArr[i], count++); could also be written like this:
repeatedElementMap.put(inputArr[i], count);
count += 1;
The effect would be the same, but in the second code you clearly see that there is a problem.
Solution:
Replace the line like this: repeatedElementMap.put(inputArr[i], count + 1);
Edit
Like azurefrog mentioned in the comments there is another problem in the lookup of the repeated element:
In the last if statement you search for a containing value, and if the value is found you try to get the element. But the get method searchs for a key, not a value. Also I don't realy get why you use modulo 2 instead of just dividing by 2. A better way would be to just run through the entries and search for one that has the searched number of elements like this:
for (Map.Entry<Integer, Integer> entry : repeatedElementMap.entrySet()) {
if (entry.getValue() == length / 2) {
repeatedElement = entry.getKey();
}
}
So the complete working code would look like this:
import java.util.HashMap;
import java.util.Map;
public class test {
public static void main(String[] args) {
int[] inputArr = new int[] {1, 2, 3, 3};
int repeatedElement = findRepeatedElement(inputArr);
System.out.println("Repeated element : " + repeatedElement);
}
public static int findRepeatedElement(int[] inputArr) {
Map<Integer, Integer> repeatedElementMap = new HashMap<Integer, Integer>();
int count = 0;
for (int i = 0; i < inputArr.length; i++) {
if (repeatedElementMap.containsKey(inputArr[i])) {
count = repeatedElementMap.get(inputArr[i]);
repeatedElementMap.put(inputArr[i], count+1);
}
else {
repeatedElementMap.put(inputArr[i], 1);
}
}
int length = inputArr.length;
int repeatedElement = 0;
for (Map.Entry<Integer, Integer> entry : repeatedElementMap.entrySet()) {
if (entry.getValue() == length / 2) {
repeatedElement = entry.getKey();
}
}
return repeatedElement;
}
}
count++ is a post-increment, meaning the value you insert to the hashmap is the value of count, and then count is incremented.
++count is a pre-increment. The value you insert to the hashmap is count + 1 since count is incremented beforehand.
Of course you want the pre-increment in this case. Your problem is that you are never inserting a value into the hashmap greater the value of 1 from the initial insertion since you are doing post-increment.
But honestly, it's unnecessary to update count at all since it's just a temporary variable for the value in the hashmap. Instead, it would be clearer to just have
repeatedElementMap.put(inputArr[i], count + 1);
I have an array containing some duplicate elements like this :
find the first duplicate number for which the second occurrence has the minimal index. In other words, if there are more than 1 duplicated numbers, return the number for which the second occurrence has a smaller index than the second occurrence of the other number does. If there are no such elements, return -1
For a = [2, 1, 3, 5, 3, 2], the output should be
firstDuplicate(a) = 3.
There are 2 duplicates: numbers 2 and 3. The second occurrence of 3 has a smaller index than the second occurrence of 2 does, so the answer is 3.
I tried this :
int firstDuplicate(int[] a) {
Set<Integer> set = new HashSet<>();
Map<Integer, Integer> hm = new HashMap<Integer,Integer>();
Map.Entry<Integer, Integer> min = null;
for(int i=0;i<a.length;i++){
// if(!hm.containsKey(a[i]))
hm.put(a[i],i);
}
for(Map.Entry<Integer,Integer> entry : hm.entrySet()){
if(min == null || entry.getValue() < min.getValue()){
min = entry;
}
}
return min == null ? new Integer(-1) : min.getKey();
}
It's not working out, but I got another solution online which is like this :
int firstDuplicate(int[] a) {
Set<Integer> set = new HashSet<>();
Map<Integer, Integer> hm = new HashMap<Integer,Integer>();
Map.Entry<Integer, Integer> min = null;
for(int i=0;i<a.length;i++){
if(set.add(a[i])==false && !hm.containsKey(a[i]))
hm.put(a[i],i);
}
for(Map.Entry<Integer,Integer> entry : hm.entrySet()){
if(min == null || entry.getValue() < min.getValue()){
min = entry;
}
}
return min == null ? new Integer(-1) : min.getKey();
}
Can anyone please explain me the use of Hashset here, as it doesn't allow the duplicates so how that if condition will be workable.
The reason your first attempt failed is that you add the array elements as keys to the Map without checking if they are already there, which means you can't know if there are any duplicates by the time you finish populating the Map.
The alternative code you found does something different. It uses the Set to determine if the current array element already appeared earlier in the array, and if that's the case, it adds it as key to the Map only if it's not already there. This means that the Map will only contain elements that appear multiple times in the array, and the index associated with each element is the occurrence of the first duplicate. I.e. for the array {2, 1, 3, 5, 3, 2}, the Map will contain {2=5, 3=4}. Then it will return the key having the smallest value (which corresponds with the index of the first duplicate).
However, the Map is unnecessary, since you only need to find one duplicate, not all of them. Use the Set to locate the first duplicate and return it:
int firstDuplicate(int[] a)
{
Set<Integer> set = new HashSet<>();
for(int i=0;i<a.length;i++){
if(!set.add(a[i])) {
return a[i];
}
}
return -1; // no duplicates found
}
This relies on set.add() returning false if the Set already contains the element you wish to add. Once it returns false for the first time, you found the first duplicate.
I would strongly recommend you to try this to get the correct results
you can make it more efficient time complexity O(n)
int firstDuplicate(int[] a){
int n = a.length;
for(int i=0; i<n; i++)
{
if(a[Math.abs(a[i])-1]<0) return Math.abs(a[i]);
else a[Math.abs(a[i])-1] = - a[Math.abs(a[i])-1];
}
return -1;
}
int firstDuplicate(int[] a){
int n = a.length;
for(int i=0; i<n; i++)
{
if(a[Math.abs(a[i])-1]<0) return Math.abs(a[i]);
else a[Math.abs(a[i])-1] = - a[Math.abs(a[i])-1];
}
return -1;
}
I will explain why and how this one works.
It's important that this constrain: 1 ≤ a[i] ≤ a.length is present, meaning that in an array like this: a = [2,8,2] this algorithm WILL NOT work because 8 is bigger than a.length in this case 3.
You'll find the explanation here as well:
Hashmap
This solution follows the idea of a hashmap. Another structure where you count hash[arr[i]-1]++ the number of occurrences for any given index i in the array. Example:
If you have arr[2,1,3,5,3,2] hashmap will begin in an 6 zero array: hashmap[0,0,0,0,0,0] because that's the size of arr. As the algorithm progress it will sum +1 in the position arr[i]-1. It's using the value as the index of the sum. At then end you get: arr[1,2,2,0,1,0].
This has O(n) in time complexity because it runs the full arr, and O(n) in time because it runs the array at least 1 time.
Without Hashmap
The idea of the algorithm above is that you don't need the extra structure of a hashmap but can use the same array to count the frequency. This might lead to a problem. Let i-th element be a or (arr[i]=a) then the count should be stored at arr[arr[i]-1] or (arr[a-1]), but when the frequency will be stored the element will be lost.
Example iteration:
a[2,1,3,5,3,2] -> a[2,1,3,5,3,2]
a[2,1,3,5,3,2] -> a[1,1,3,5,3,2]
a[1,1,3,5,3,2] -> a[1,1,1,5,3,2]
a[1,1,1,5,3,2] -> a[1,1,1,5,1,2] As you can see we lost the value of 3 when we read 5 as it stored the frequency in arr[arr[4]-1] or (arr[5-1]).
Solve the missing problem
To solve this problem first we put replace the i-th element with arr[arr[i]-1] or (arr[a-1]) then put -1 at array arr[arr[i]-1] or (arr[a-1]).
The algorithm:
Traverse the array from start to end.
For each element check if the element is less than or equal to zero or not. If negative or zero skip the element as it is frequency.
If an element (a = arr[i] – 1) is positive, then check if arr[a] is positive or not. If positive then that means it is the first occurrence of a in the array and replace arr[i] with arr[a], and assign arr[a] = -1. If arr[a] is negative, then it is not the first occurrence, then update arr[a] as arr[a]-- and update arr[i] as arr[i] = 0. You use an auxiliary value to save arr[a] that will be used in the next iteration.
Again, traverse the array and print i+1 as value and arr[i] as frequency.
Example iteration:
a[2,1,3,5,3,2] -> a[1,1,3,5,3,2] -> a[1,-1,3,5,3,2]
a[1,-1,3,5,3,2] -> a[1,-1,3,5,3,2] -> a[1,-1,-1,5,3,2]
a[1,-1,-1,5,3,2] -> a[1,-1,-1,0,3,2]
a[1,-1,-1,0,3,2] -> a[1,-1,-1,0,-1,2] -> a[1,-1,-2,0,-1,2]
a[1,-1,-2,0,-1,2] -> a[1,-1,-2,0,-1,0]
a[1,-1,-2,0,-1,0] -> a[1,-2,-2,0,-1,0]
firstDuplicate
After knowing this we can now grasp how firstDuplicate works. The idea is not to count the frequency but instead just print the index that has already a negative in frequency. When we get a negative frequency we return.
So running the algorithm we get:
With if(a[2-1]<0) or if(1<0) this comparation is between arr[arr[0]-1] or (arr[1]) and 0 so we don't return. a[2,1,3,5,3,2] -> a[2,-1,3,5,3,2]
With if(a[1-1]<0) or if(2<0) we don't return a[2,-1,3,5,3,2] -> a[-1,-1,3,5,3,2].
With if(a[3-1]<0) or if(3<0) we don't return. a[-1,-1,3,5,3,2] -> a[-2,-1,-3,5,3,2]
With if(a[5-1]<0) or if(3<0) we don't return. a[-2,-1,-3,5,3,2] -> a[-2,-1,-3,5,-3,2]
With if(a[3-1]<0) or if(-3<0) we return.
All of this is based on the idea that element-1 is the index.
You can use java 8 with lambda and stream.
Here is the code in one line :
Set<Integer> allItems = new HashSet<>();
Arrays.stream(a).filter(i -> !allItems.add(i)).findFirst().orElse(-1)
it returns what you expect
There are two ways to implement this problem, by using a HashSet with time complexity o(n) and by using nested loops o(n2)
for(int i = 0; i < a.length; i++){
for(int j = i +1; j < a.length; j++){
if(a[i] == a[j]){
System.out.println(a[i]);
return;
}
}
}
Or you can make it more efficient time complexity O(n)
int index -1;
Set<Integer> hashSet = new HashSet<Integer>();
for(int i = a.length-1; i >= 0; i--){
if(hashSet.contains(a[i])){
index = i;
}else{
hashSet.add(a[i]);
}
}
System.out.println(a[index]);
int firstDuplicate(int[] a)
{
int DupIndex = 0;
int DupValue = 0;
for (int i = 0; i < a.Length; i++)
{
for (int j = i + 1; j < a.Length; j++)
{
if (a[i] == a[j])
{
if (j < DupIndex)
{
DupIndex = j;
DupValue = a[i];
}
else if (DupIndex == 0)
{
DupIndex = j;
DupValue = a[i];
}
}
};
};
return (DupValue == 0) ? -1 : DupValue;
}
public static void main(String[] args){
int array[]={2, 1, 3, 5, 3, 2};
int tempArray[]=new int[array.length];
int index=0;
while(index< array.length){
if(++(tempArray[array[index]])==2)
break;
index++;
}
if(index> array.length){
System.out.println("No Duplicate");
}else {
System.out.println("First Duplicate " + array[index]);
}
}
Use counting sort, sweet and simple :)
Java implementation
Time complexity O(n) -- Linear
Space Complexity O(n) -- Linear
//Approach
//run a loop and try to insert it into a map.
//check if map contains key for arr[nextValue]
//if contains key, break loop and return value.
//if not, keep on adding in the map.
import java.util.HashMap;
import java.util.Map;
public class ReturnFirstRecurringCharacter {
public static void main(String[] args) {
int[] arr1 = {2,5,5,2};
Integer recurringNumber = checkForRecurringNumber(arr1);
if (recurringNumber != null) {
System.out.println(recurringNumber);
} else {
System.out.println("Undefined");
}
}
private static Integer checkForRecurringNumber(int[] arr1) {
try {
if (arr1 != null) {
Map<Integer, Integer> dataMap = new HashMap<>();
for (int i = 0; i < arr1.length; i++) {
if (dataMap.containsKey(arr1[i])) {
return arr1[i];
}
dataMap.put(arr1[i], i);
}
}
} catch (Exception e) {
System.out.println(e);
e.getStackTrace();
}
return null;
}
}
JS solution:
function solution(a) {
const map = {};
for(let i=0; i<a.length; i++) {
if(map[a[i]]) {
if(map[a[i]][0] === 1) {
map[a[i]][0]++ ;
map[a[i]][1] = i;
}
} else {
map[a[i]] = [1, i];
}
}
const data = Object.keys(map).filter(key => map[key][0] == 2).map(el => parseInt(el));
let smallest = Infinity;
let smallestData = -1;
for(let i=0; i<data.length; i++) {
if(map[data[i]][1] < smallest) {
smallest = map[data[i]][1];
smallestData = data[i];
}
}
return smallestData;
}
Solution in Javascript
function solution(a) {
let i = -1;
while (++i < a.length)
if (a.indexOf(a[i]) !== i)
return a[i];
return -1;
}
console.log(solution([2, 1, 3, 5, 3, 2])); // 3
console.log(solution([2, 2])); // 2
console.log(solution([2, 4, 3, 5, 1])); // -1
I just had an online coding interview and one of the questions asked there is for a given array of integers, find out the number of pairs whose summation is equal to a certain number (passed as parameter inside the method ). For example an array is given as,
int[] a = {3, 2, 1, 45, 27, 6, 78, 9, 0};
int k = 9; // given number
So, there will be 2 pairs (3, 6) and (9, 0) whose sum is equal to 9. It's good to mention that how the pairs are formed doesn't matter. The means (3,6) and (6,3) will be considered as same pair. I provided the following solution (in Java) and curious to know if I missed any edge cases?
public static int numberOfPairs(int[] a, int k ){
int len = a.length;
if (len == 0){
return -1;
}
Arrays.sort(a);
int count = 0, left = 0, right = len -1;
while( left < right ){
if ( a[left] + a[right] == k ){
count++;
if (a[left] == a[left+1] && left < len-1 ){
left++;
}
if ( a[right] == a[right-1] && right >1 ){
right-- ;
}
right--; // right-- or left++, otherwise, will get struck in the while loop
}
else if ( a[left] + a[right] < k ){
left++;
}
else {
right--;
}
}
return count;
}
Besides, can anyone propose any alternative solution of the problem ? Thanks.
Following solution will return the number of unique pairs
public static int numberOfPairs(Integer[] array, int sum) {
Set<Integer> set = new HashSet<>(Arrays.asList(array));
// this set will keep track of the unique pairs.
Set<String> uniquePairs = new HashSet<String>();
for (int i : array) {
int x = sum - i;
if (set.contains(x)) {
int[] y = new int[] { x, i };
Arrays.sort(y);
uniquePairs.add(Arrays.toString(y));
}
}
//System.out.println(uniquePairs.size());
return uniquePairs.size();
}
The time complexity will be O(n).
Hope this helps.
You can use the HashMap<K,V> where K: a[i] and V: k-a[i]
This may result in an incorrect answer if there are duplicates in an array.
Say for instances:
int a[] = {4, 4, 4, 4, 4, 4, 4, 4, 4}
where k = 8 or:
int a[] = {1, 3, 3, 3, 3, 1, 2, 1, 2}
where k = 4.
So in order to avoid that, we can have a List<List<Integer>> , which can check each pair and see if it is already in the list.
static int numberOfPairs(int[] a, int k)
{
List<List<Integer>> res = new ArrayList<>();
Map<Integer, Integer> map = new HashMap<>();
for(int element:a)
{
List<Integer> list = new ArrayList<>();
if(map.containsKey(element))
{
list.add(element);
list.add(map.get(element));
if(!res.contains(list))
res.add(list);
}
else
map.put(k - element, element);
}
return res.size();
}
Your solution is overly complex, you can do this exercise in a much easier manner:
public static int numberOfPairs(int[] a, int k ){
int count=0;
List<Integer> dedup = new ArrayList<>(new HashSet<>(Arrays.asList(a)));
for (int x=0 ; x < dedup.size() ; x++ ){
for (int y=x+1 ; y < dedup.size() ; y++ ){
if (dedup.get(x)+dedup.get(y) == k)
count++;
}
}
return count;
}
The trick here is to have a loop starting after the first loop's index to not count the same values twice, and not compare it with your own index. Also, you can deduplicate the array to avoid duplicate pairs, since they don't matter.
You can also sort the list, then break the loop as soon as your sum goes above k, but that's optimization.
This code will give you count of the pairs that equals to given sum and as well as the pair of elements that equals to sum
private void pairofArrayElementsEqualstoGivenSum(int sum,Integer[] arr){
int count=0;
List numList = Arrays.asList(arr);
for (int i = 0; i < arr.length; i++) {
int num = sum - arr[i];
if (numList.contains(num)) {
count++;
System.out.println("" + arr[i] + " " + num + " = "+sum);
}
}
System.out.println("Total count of pairs "+count);
}
Given an array of integers and a target value, determine the number of pairs of array elements with a difference equal to a target value.
The function has the following parameters:
k: an integer, the target difference
arr: an array of integers
Using LINQ this is nice solution:
public static int CountNumberOfPairsWithDiff(int k, int[] arr)
{
var numbers = arr.Select((value) => new { value });
var pairs = from num1 in numbers
join num2 in numbers
on num1.value - k equals num2.value
select new[]
{
num1.value, // first number in the pair
num2.value, // second number in the pair
};
foreach (var pair in pairs)
{
Console.WriteLine("Pair found: " + pair[0] + ", " + pair[1]);
}
return pairs.Count();
}
I've just been looking at the following piece of code
package test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(final String[] args) {
final int sizeA = 3;
final int sizeB = 5;
final List<int[]> combos = getAllCombinations(sizeA-1, sizeB);
int counter = 1;
for(final int[] combo : combos) {
System.out.println("Combination " + counter);
System.out.println("--------------");
for(final int value : combo) {
System.out.print(value + " ");
}
System.out.println();
System.out.println();
++counter;
}
}
private static List<int[]> getAllCombinations(final int maxIndex, final int size) {
if(maxIndex >= size)
throw new IllegalArgumentException("The maximum index must be smaller than the array size.");
final List<int[]> result = new ArrayList<int[]>();
if(maxIndex == 0) {
final int[] array = new int[size];
Arrays.fill(array, maxIndex);
result.add(array);
return result;
}
//We'll create one array for every time the maxIndex can occur while allowing
//every other index to appear, then create every variation on that array
//by having every possible head generated recursively
for(int i = 1; i < size - maxIndex + 1; ++i) {
//Generating every possible head for the array
final List<int[]> heads = getAllCombinations(maxIndex - 1, size - i);
//Combining every head with the tail
for(final int[] head : heads) {
final int[] array = new int[size];
System.arraycopy(head, 0, array, 0, head.length);
//Filling the tail of the array with i maxIndex values
for(int j = 1; j <= i; ++j)
array[size - j] = maxIndex;
result.add(array);
}
}
return result;
}
}
I'm wondering, how do I eliminate recursion from this, so that it returns a single random combination, rather than a list of all possible combinations?
Thanks
If I understand your code correctly your task is as follows: give a random combination of numbers '0' .. 'sizeA-1' of length sizeB where
the combination is sorted
each number occurs at least once
i.e. in your example e.g. [0,0,1,2,2].
If you want to have a single combination only I'd suggest another algorithm (pseudo-code):
Randomly choose the step-up positions (e.g. for sequence [0,0,1,1,2] it would be steps (1->2) & (3->4)) - we need sizeA-1 steps randomly chosen at sizeB-1 positions.
Calculate your target combination out of this vector
A quick-and-dirty implementation in java looks like follows
// Generate list 0,1,2,...,sizeB-2 of possible step-positions
List<Integer> steps = new ArrayList<Integer>();
for (int h = 0; h < sizeB-1; h++) {
steps.add(h);
}
// Randomly choose sizeA-1 elements
Collections.shuffle(steps);
steps = steps.subList(0, sizeA - 1);
Collections.sort(steps);
// Build result array
int[] result = new int[sizeB];
for (int h = 0, o = 0; h < sizeB; h++) {
result[h] = o;
if (o < steps.size() && steps.get(o) == h) {
o++;
}
}
Note: this can be optimized further - the first step generates a random permutation and later strips this down to desired size. Therefore it is just for demonstration purpose that the algorithm itself works as desired.
This appears to be homework. Without giving you code, here's an idea. Call getAllCombinations, store the result in a List, and return a value from a random index in that list. As Howard pointed out in his comment to your question, eliminating recursion, and returning a random combination are separate tasks.