Help with how to implement searching on n 2-dimenssional arrays. To be more specific:
If I have 6 tables and I am putting these into a 2-dimensional array.I will provide a value say 10 like how val=0 here. I need to search from these tables all the combination values that make up 10. The value will be computed taking values from all these tables.
public static int Main() {
int[] a = {2,1,4,7};
int[] b = {3,-3,-8,0};
int[] c = {-1,-4,-7,6};
int sum;
int i; int j; int k;
int val = 0;
for(i = 0; i < 4; i++) {
for(j = 0;j<4;j++) {
for(k = 0;k<4;k++) {
sum = a[i]* b[j]* c[k];
if(sum == val)
System.out.printf("%d %d %d\n",a[i],b[j],c[k]);
}
}
}
}
Following will be the code you require:
(The solution includes recursion making your problem go easier)
private ArrayList numbers = new ArrayList();
public void CalculateSum(int tableNumber)
{
if(!Tables.isLast(tableNumber))
{
int[][] a = Tables.Get(tableNumber);
for(int y = 0; y < a.length; y++)
{
for(int x = 0; x < a[y].length; x++)
{
numbers.add(a[y][x]);
CalculateSum(tableNumber + 1);
numbers.remove(tableNumber - 1);
}
}
}else
{
int[][] a = Tables.Get(tableNumber);
for(int y = 0; y < a.length; y++)
{
for(int x = 0; x < a[y].length; x++)
{
if((sum(numbers) + a[y][x]) == checkValue)
{
PrintNumbers(numbers);
System.out.print(a[y][x]);
System.out.println();
}
}
}
}
}
You need to implement a class ('Tables' as my solution) write methods:
boolean isLast(int tableNo): to check whether the given table is the last table your tables list
int[][] Get(int tableNo): to get the table with the specified index
Also the method sum should sum the values in the numbers ArrayList.
PrintNumbers method should print the numbers in the numbers ArrayList in a row.
checkValue is the value you want to check.
Hope this helps....
Please write if you want any clarification on this algorithm.
You can consider a table as list of values. Then, if you have N tables, your problem is to find lists of N integers (each one taken from one of the N tables) whose product is equal to a value p. You can solve the problem recursively:
given a non-empty list of tables {t1, t2, t3, ...}
given a product value p that you look for
for every value v in t1 you must look for solutions of the sub-problem with a product value p / v and and tables {t2, t3, ...} (this assumes that p % v == 0, because we're dealing with integers
etc.
Some java code below:
public class SO6026472 {
public static void main(String[] args) {
// define individual tables
Integer[] t1 = new Integer[] {2,-2,4,7};
Integer[] t2 = new Integer[] {3,-3,-8,0};
Integer[] t3 = new Integer[] {-1,-4,-7,6};
Integer[] t4 = new Integer[] {1,5};
// build list of tables
List<List<Integer>> tables = new ArrayList<List<Integer>>();
tables.add(Arrays.asList(t1));
tables.add(Arrays.asList(t2));
tables.add(Arrays.asList(t3));
tables.add(Arrays.asList(t4));
// find solutions
SO6026472 c = new SO6026472();
List<List<Integer>> solutions = c.find(36, tables);
for (List<Integer> solution : solutions) {
System.out.println(
Arrays.toString(solution.toArray(new Integer[0])));
}
}
/**
* Computes the ways of computing p as a product of elements taken from
* every table in tables.
*
* #param p the target product value
* #param tables the list of tables
* #return the list of combinations of elements (one from each table) whose
* product is equal to p
*/
public List<List<Integer>> find(int p, List<List<Integer>> tables) {
List<List<Integer>> solutions = new ArrayList<List<Integer>>();
// if we have no tables, then we are done
if (tables.size() == 0)
return solutions;
// if we have just one table, then we just have to check if it contains p
if (tables.size() == 1) {
if (tables.get(0).contains(p)) {
List<Integer> solution = new ArrayList<Integer>();
solution.add(p);
solutions.add(solution);
return solutions;
} else
return solutions;
}
// if we have several tables, then we take the first table T, and for
// every value v in T we search for (p / v) in the rest of the tables;
// we do this only if p % v is equal to 0, because we're dealing with
// ints
List<Integer> table = tables.remove(0);
for (Integer value : table) {
if (value != 0 && p % value == 0) {
List<List<Integer>> subSolutions = find(p / value, tables);
if (! subSolutions.isEmpty()) {
for (List<Integer> subSolution : subSolutions) {
subSolution.add(0, value);
}
solutions.addAll(subSolutions);
}
}
}
tables.add(0, table);
return solutions;
}
}
The code prints solutions for a slightly modified version of your example:
[2, 3, 6, 1]
[-2, -3, 6, 1]
The solutions work for any number of tables. There are ways to improve the algorithm, for example by using memoization and dynamic programming. But I think that the recursive solution is more clear.
Related
I am a beginner(first year uni student) programmer trying to solve this problem which i'm finding somewhat difficult. If you are to answer this question, don't provide me with a complex daunting algorithm that will leave me scratching my head. I'll really appreciate it if you explain it step my step (both logically/conceptually then through code)
The problem is as follows:image
I have tried to attempt it and my code only works for a certain case that i tested.
package com.company;
import java.lang.Math;
public class Main {
public static int[][] binary_partition(int array[], int k){
int x = (int) Math.pow(2,k);
int[][] partition = new int[((array.length/x)*2)][array.length/x];
int divisor = array.length/x;
if ((array.length % 2) != 0){
return partition;
}
if (divisor >= array.length-1){
return partition;
}
if (k==1){
return partition;
}
int p = 0;
for(int i=0;i<((array.length/x)*2);i++)
{
for (int j = 0; j<array.length/x;j++)
{
partition[i][j] = array[p];
p += 1;
}
}
return partition;
}
public static void main(String[] args){
int[] array = {3, 2, 4, 7, 8, 9, 2, 3};
int[][] result = binary_partition(array,2);
for (int[] x : result){
for (int y : x)
{
System.out.print(y + " ");
}
System.out.println();
}
}
}
Your question is unclear, but this solution creates a function that partitions an array with the right length into 2^k sets.
First, an interesting fact: using the bitshift operator << on an integer increases its value by a power of two. So to find out the size of your partition, you could write
int numPartitions = 1 << k; // Equivalent to getting the integer value of 2^k
With this fact, the function becomes
public static int[][] partition(int[] set, int k) {
if (set == null)
return null; // Don't try to partition a null reference
// If k = 0, the partition of the set is just the set
if (k == 0) {
int[][] partition = new int[1][set.length];
// Copy the original set into the partition
System.arraycopy(set, 0, partition[0], 0, set.length);
return partition;
}
int numPartitions = 1 << k; // The number of sets to partition the array into
int numElements = set.length / numPartitions; // The number of elements per partition
/* Check if the set has enough elements to create a partition and make sure
that the partitions are even */
if (numElements == 0 || set.length % numElements != 0)
return null; // Replace with an error/exception of your choice
int[][] partition = new int[numPartitions][numElements];
int index = 0;
for (int r = 0; r < numPartitions; r++) {
for (int c = 0; c < numElements; c++) {
partition[r][c] = set[index++]; // Assign an element to the partition
}
}
return partition;
}
There are a few lines of your code where the intention is not clear. For example, it is not clear why you are validating divisor >= array.length-1. Checking k==1 is also incorrect because k=1 is a valid input to the method. In fact, all your validation checks are not needed. All you need to validate is that array.length is divisible by x.
The main problem that you have seems to be that you mixed up the lengths of the resulting array.
The resulting array should have a length of array.length / x, and each of the subarrays should have a length of x, hence:
int[][] partition = new int[array.length/x][x];
If you also fix your bounds on the for loops, your code should work.
Your nested for loop can be rewritten as a single for loop:
for(int i = 0 ; i < array.length ; i++)
{
int index = i / x;
int subArrayIndex = i % x;
partition[index][subArrayIndex] = array[i];
}
You just need to figure out which indices a an element array[i] belongs by dividing and getting the remainder.
Its an assignment task,I have spend 2 days to come up with a solution but still having lots of confusion,however here I need to make few points clear. Following is the problem:
Yuckdonald’s is considering opening a series of restaurant along QVH. n possible locations are along a straight line and the distances of these locations from the start of QVH are in miles and in increasing order m1, m2, ...., mn. The constraints are as follows:
1. At each location, Yuckdonald may open one restaurant and expected profit from opening a restaurant at location i is given as pi
2. Any two restaurants should be at least k miles apart, where k is a positive integer
My solution:
public class RestaurantProblem {
int[] Profit;
int[] P;
int[] L;
int k;
public RestaurantProblem(int[] L , int[] P, int k) {
this.L = L;
this.P = P;
this.k = k;
Profit = new int[L.length];
}
public int compute(int i){
if(i==0)
return 0;
Profit[i]= P[i]+(L[i]-L[i-1]< k ? 0:compute(i-1));//if condition satisfies then adding previous otherwise zero
if (Profit[i]<compute(i-1)){
Profit[i] = compute(i-1);
}
return Profit[i];
}
public static void main(String args[]){
int[] m = {0,5,10,15,19,25,28,29};
int[] p = {0,10,4,61,21,13,19,15};
int k = 5;
RestaurantProblem rp = new RestaurantProblem(m, p ,k);
rp.compute(m.length-1);
for(int n : rp.Profit)
System.out.println(n);
}
}
This solution giving me 88 however if I exclude (Restaurant at 25 with Profit 13) and include (Restaurant 28 with profit 19) I can have 94 max...
point me if I am wrong or how can I achieve this if its true.
I was able to identify 2 mistakes:
You are not actually using dynamic programming
, you are just storing the results in a data structure, which wouldn't be that bad for performance if the program worked the way you have written it and if you did only 1 recursive call.
However you do at least 2 recursive calls. Therefore the program runs in Ω(2^n) instead of O(n).
Dynamic programming usually works like this (pseudocode):
calculate(input) {
if (value already calculated for input)
return previously calculated value
else
calculate and store value for input and return result
}
You could do this by initializing the array elements to -1 (or 0 if all profits are positive):
Profit = new int[L.length];
Arrays.fill(Profit, -1); // no need to do this, if you are using 0
public int compute(int i) {
if (Profit[i] >= 0) { // modify the check, if you're using 0 for non-calculated values
// reuse already calculated value
return Profit[i];
}
...
You assume the previous restaurant can only be build at the previous position
Profit[i] = P[i] + (L[i]-L[i-1]< k ? 0 : compute(i-1));
^
Just ignores all positions before i-1
Instead you should use the profit for the last position that is at least k miles away.
Example
k = 3
L 1 2 3 ... 100
P 5 5 5 ... 5
here L[i] - L[i-1] < k is true for all i and therefore the result will just be P[99] = 5 but it should be 34 * 5 = 170.
int[] lastPos;
public RestaurantProblem(int[] L, int[] P, int k) {
this.L = L;
this.P = P;
this.k = k;
Profit = new int[L.length];
lastPos = new int[L.length];
Arrays.fill(lastPos, -2);
Arrays.fill(Profit, -1);
}
public int computeLastPos(int i) {
if (i < 0) {
return -1;
}
if (lastPos[i] >= -1) {
return lastPos[i];
}
int max = L[i] - k;
int lastLastPos = computeLastPos(i - 1), temp;
while ((temp = lastLastPos + 1) < i && L[temp] <= max) {
lastLastPos++;
}
return lastPos[i] = lastLastPos;
}
public int compute(int i) {
if (i < 0) {
// no restaurants can be build before pos 0
return 0;
}
if (Profit[i] >= 0) { // modify the check, if you're using 0 for non-calculated values
// reuse already calculated value
return Profit[i];
}
int profitNoRestaurant = compute(i - 1);
if (P[i] <= 0) {
// no profit can be gained by building this restaurant
return Profit[i] = profitNoRestaurant;
}
return Profit[i] = Math.max(profitNoRestaurant, P[i] + compute(computeLastPos(i)));
}
To my understanding, the prolem can be modelled with a two-dimensional state space, which I don't find in the presented implementation. For each (i,j) in{0,...,n-1}times{0,...,n-1}` let
profit(i,j) := the maximum profit attainable for selecting locations
from {0,...,i} where the farthest location selected is
no further than at position j
(or minus infinity if no such solution exist)
and note that the recurrence relation
profit(i,j) = min{ p[i] + profit(i-1,lastpos(i)),
profit(i-1,j)
}
where lastpos(i) is the location which is farthest from the start, but no closer than k to position i; the first case above corresponds to selection location i into the solution while the second case corresponds to omitting location j in the solution. The overall solution can be obtained by evaluating profit(n-1,n-1); the evaluation can be done either recursively or by filling a two-dimensional array in a bottom-up manner and returning its contents at (n-1,n-1).
As in the title, I want to use Knuth-Fisher-Yates shuffle algorithm to select N random elements from a List but without using List.toArray and change the list. Here is my current code:
public List<E> getNElements(List<E> list, Integer n) {
List<E> rtn = null;
if (list != null && n != null && n > 0) {
int lSize = list.size();
if (lSize > n) {
rtn = new ArrayList<E>(n);
E[] es = (E[]) list.toArray();
//Knuth-Fisher-Yates shuffle algorithm
for (int i = es.length - 1; i > es.length - n - 1; i--) {
int iRand = rand.nextInt(i + 1);
E eRand = es[iRand];
es[iRand] = es[i];
//This is not necessary here as we do not really need the final shuffle result.
//es[i] = eRand;
rtn.add(eRand);
}
} else if (lSize == n) {
rtn = new ArrayList<E>(n);
rtn.addAll(list);
} else {
log("list.size < nSub! ", lSize, n);
}
}
return rtn;
}
It uses list.toArray() to make a new array to avoid modifying the original list. However, my problem now is that my list could be very big, can have 1 million elements. Then list.toArray() is too slow. And my n could range from 1 to 1 million. When n is small (say 2), the function is very in-efficient as it still need to do list.toArray() for a list of 1 million elements.
Can someone help improve the above code to make it more efficient when dealing with large lists. Thanks.
Here I assume Knuth-Fisher-Yates shuffle is the best algorithm to do the job of selecting n random elements from a list. Am I right? I would be very glad to if there is other algorithms better than Knuth-Fisher-Yates shuffle to do the job in terms of the speed and the quality of the results (guarantee real randomness).
Update:
Here is some of my test results:
When selection n from 1000000 elements.
When n<1000000/4 the fastest way to through using Daniel Lemire's Bitmap function to select n random id first then get the elements with these ids:
public List<E> getNElementsBitSet(List<E> list, int n) {
List<E> rtn = new ArrayList<E>(n);
int[] ids = genNBitSet(n, 0, list.size());
for (int i = 0; i < ids.length; i++) {
rtn.add(list.get(ids[i]));
}
return rtn;
}
The genNBitSet is using the code generateUniformBitmap from https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/blob/master/2013/08/14/java/UniformDistinct.java
When n>1000000/4 the Reservoir Sampling method is faster.
So I have built a function to combine these two methods.
You are probably looking for something like Resorvoir Sampling.
Start with an initial array with first k elements, and modify it with new elements with decreasing probabilities:
java like pseudo code:
E[] r = new E[k]; //not really, cannot create an array of generic type, but just pseudo code
int i = 0;
for (E e : list) {
//assign first k elements:
if (i < k) { r[i++] = e; continue; }
//add current element with decreasing probability:
j = random(i++) + 1; //a number from 1 to i inclusive
if (j <= k) r[j] = e;
}
return r;
This requires a single pass on the data, with very cheap ops every iteration, and the space consumption is linear with the required output size.
If n is very small compared to the length of the list, take an empty set of ints and keep adding a random index until the set has the right size.
If n is comparable to the length of the list, do the same, but then return items in the list that don't have indexes in the set.
In the middle ground, you can iterate through the list, and randomly select items based on how many items you've seen, and how many items you've already returned. In pseudo-code, if you want k items from N:
for i = 0 to N-1
if random(N-i) < k
add item[i] to the result
k -= 1
end
end
Here random(x) returns a random number between 0 (inclusive) and x (exclusive).
This produces a uniformly random sample of k elements. You could also consider making an iterator to avoid building the results list to save memory, assuming the list is unchanged as you're iterating over it.
By profiling, you can determine the transition point where it makes sense to switch from the naive set-building method to the iteration method.
Let's assume that you can generate n random indices out of m that are pairwise disjoint and then look them up efficiently in the collection. If you don't need the order of the elements to be random, then you can use an algorithm due to Robert Floyd.
Random r = new Random();
Set<Integer> s = new HashSet<Integer>();
for (int j = m - n; j < m; j++) {
int t = r.nextInt(j);
s.add(s.contains(t) ? j : t);
}
If you do need the order to be random, then you can run Fisher--Yates where, instead of using an array, you use a HashMap that stores only those mappings where the key and the value are distinct. Assuming that hashing is constant time, both of these algorithms are asymptotically optimal (though clearly, if you want to randomly sample most of the array, then there are data structures with better constants).
Just for convenience: A MCVE with an implementation of the Resorvoir Sampling proposed by amit (possible upvotes should go to him (I'm just hacking some code))
It seems like this is indeed a algorithm that nicely covers the cases of where the number of elements to select is low compared to the list size, and the cases where the number of elements is high compared to the list size (assumung that the properties about the randomness of the result that are stated on the wikipedia page are correct).
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.TreeMap;
public class ReservoirSampling
{
public static void main(String[] args)
{
example();
//test();
}
private static void test()
{
List<String> list = new ArrayList<String>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
list.add("E");
int size = 2;
int runs = 100000;
Map<String, Integer> counts = new TreeMap<String, Integer>();
for (int i=0; i<runs; i++)
{
List<String> sample = sample(list, size);
String s = createString(sample);
Integer count = counts.get(s);
if (count == null)
{
count = 0;
}
counts.put(s, count+1);
}
for (Entry<String, Integer> entry : counts.entrySet())
{
System.out.println(entry.getKey()+" : "+entry.getValue());
}
}
private static String createString(List<String> list)
{
Collections.sort(list);
StringBuilder sb = new StringBuilder();
for (String s : list)
{
sb.append(s);
}
return sb.toString();
}
private static void example()
{
List<String> list = new ArrayList<String>();
for (int i=0; i<26; i++)
{
list.add(String.valueOf((char)('A'+i)));
}
for (int i=1; i<=26; i++)
{
printExample(list, i);
}
}
private static <T> void printExample(List<T> list, int size)
{
System.out.printf("%3d elements: "+sample(list, size)+"\n", size);
}
private static final Random random = new Random(0);
private static <T> List<T> sample(List<T> list, int size)
{
List<T> result = new ArrayList<T>(Collections.nCopies(size, (T) null));
int i = 0;
for (T element : list)
{
if (i < size)
{
result.set(i, element);
i++;
continue;
}
i++;
int j = random.nextInt(i);
if (j < size)
{
result.set(j, element);
}
}
return result;
}
}
If n is way smaller then size, you could use this algorith, witch is unfortunatly quadratic with n, but doest depend on size of array at all.
Example with size = 100 and n = 4.
choose random number from 0 to 99, lets say 42, and add it to result.
choose random number from 0 to 98, lets say 39, and add it to result.
choose random number from 0 to 97, lets say 41, but since 41 is bigger or equal than 39, increment it by 1, so you have 42, but that is bigger then equal than 42, so you have 43.
...
Shortly, you choose from remaining numbers and then compuce what number have you acctualy chosen. I would use link list for this, but maybe there are better data structures.
Summarizing Changwang's update. If you want more than 250,000 items, use amit's answer. Otherwise use Knuth-Fisher-Yates Shuffle as shown in entirety here
NOTE: The result is always in the original order as well
public static <T> List<T> getNRandomElements(int n, List<T> list) {
List<T> subList = new ArrayList<>(n);
int[] ids = generateUniformBitmap(n, list.size());
for (int id : ids) {
subList.add(list.get(id));
}
return subList;
}
// https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/blob/master/2013/08/14/java/UniformDistinct.java
private static int[] generateUniformBitmap(int num, int max) {
if (num > max) {
DebugUtil.e("Can't generate n ints");
}
int[] ans = new int[num];
if (num == max) {
for (int k = 0; k < num; ++k) {
ans[k] = k;
}
return ans;
}
BitSet bs = new BitSet(max);
int cardinality = 0;
Random random = new Random();
while (cardinality < num) {
int v = random.nextInt(max);
if (!bs.get(v)) {
bs.set(v);
cardinality += 1;
}
}
int pos = 0;
for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) {
ans[pos] = i;
pos += 1;
}
return ans;
}
If you want them randomized, I use:
public static <T> List<T> getNRandomShuffledElements(int n, List<T> list) {
List<T> randomElements = getNRandomElements(n, list);
Collections.shuffle(randomElements);
return randomElements;
}
I needed something for this in C#, here's my solution which works on a generic List.
It selects N random elements of the list and places them at the front of the list.
So upon returning, the first N elements of the list are randomly selected. It is fast and efficient even when you're dealing with a very large number of elements.
static void SelectRandom<T>(List<T> list, int n)
{
if (n >= list.Count)
{
// n should be less than list.Count
return;
}
int max = list.Count;
var random = new Random();
for (int i = 0; i < n; i++)
{
int r = random.Next(max);
max = max - 1;
int irand = i + r;
if (i != irand)
{
T rand = list[irand];
list[irand] = list[i];
list[i] = rand;
}
}
}
How might I approach solving the following problem:
Create an array of integers that are contained in at least two of the given arrays.
For example:
int[] a1 = new int[] { 1, 2, 3, 4, 5 };
int[] a2 = new int[] { 5, 10, 11, 8 };
int[] a3 = new int[] { 1, 7, 6, 4, 5, 3, 11 };
must give a result array
int[] result = new int[] {1, 3, 4, 5, 11}
P.S. i'm interested in suggestions on how I might approach this ("algorithm"), not what Java utils might give me the answer
put a1 numbers in a Map<Integer,Integer> count, using the value as the key, and setting the count to 1
Put a2 numbers into the same map. If an item does not exist, assign the count of 1, otherwise assign it the existing count + 1
Put a3 numbers into the same map. If an item does not exist, assign the count of 1, otherwise assign it the existing count + 1
Go through the entries in a map, and output all keys where the value is greater than one.
This algorithm is amortized linear time in the combined number of elements in the three arrays.
If the numbers in the three arrays are limited to, say, 1000 or another relatively small number, you could avoid using collections at all, but use a potentially more expensive algorithm based on the upper limit of your numbers: replace the map with an array counts[MAX_NUM+1], and then run the same algorithm, like this:
int[] counts = new int[MAX_NUM+1];
for (int a : a1) counts[a]++;
for (int a : a2) counts[a]++;
for (int a : a3) counts[a]++;
for (int i = 0 ; i != MAX_NUM+1 ; i++) {
if (counts[i] > 1) {
System.out.println(i);
}
}
You can look at the 3 arrays as sets and find each element that is in the intersection of some pair of sets.
basically, you are looking for (set1 [intersection] set2) [union] (set2 [intersection] set3) [union] (set1 [intersection] set2)
I agree that it might not be the easiest way to achieve what you are after, but being able to reduce one problem to another is a technique every programmer should master, and this solution should be very educating.
The only way to do this without collections would be to take an element from an array, iterate over the remaining two arrays to see if a duplicate is found (and then break and move to the next element). You need to do this for two out of the three arrays as by the time you move to the third one, you would already have your answer.
Mathematically this can be solved as follows:
You can construct three sets using each of the three arrays, so duplicated entries in each array will only occur once in each set. And then the entries that appear at least in two of the three sets are solutions. So they are given by
(S_1 intersect S_2) union (S_2 intersect S_3) union (S_3 intersect S_1)
Think about the question and the different strategies you might use:
Go through each entry in each array, if that entry is NOT already in the "duplicates" result, then see if that entry is in each of the remaining arrays. Add to duplicates if it is and return to next integer
Create an array of non-duplicates by adding an entry from each array (and if it is already there, putting it in the duplicates array).
Use another creative strategy of your own
I like drawing Venn diagramms. You know that diagram with three intersecting circles, e.g. see here.
You then see that the complement is easier to describe:
Those elements which only exist in one array, are not interesting.
So you could build a frequency list (i.e. key = element, value = count of in how many arrays you found it [for the first time]) in a hash map, and then in a final pass pick all elements which occured more than once.
For simplicity I used sets. If your arrays contain multiple entries of the same value, you have to ignore those extra occurences when you build the frequency list.
An approach could be like this:
1.Sort all the arrays.
2.For each combination of arrays do this
Let us consider the first two arrays A,B. Let a be A's size.
Also take a third array or vector to store our result
for i=0-->a-1 {
Search for A[i] in B using binarySearch.
if A[i] exists in B then insert A[i] into our result vector
}
Repeat the same process for (B,C) and (C,A).
Now sort & Traverse the result vector from the end, remove the elements which have the property
result[i] = result[i-1]
The final vector is the required result.
Time Complexity Analysis:
T(n) = O(nlog(n)) for Sorting where n is the highest array size among the given three
For searching each element of an array in other sorted array T(n) = n * O(log n)
T(n) = O(n (log n)) for sorting the result and O(n) for traversing
So overall time complexity is O(n log(n)); and space complexity is O(n)
Please correct me of I am wrong
In Java:
Will write one without using java.utils shortly.
Meantime a solution using java.utils:
public static void twice(int[] a, int[] b, int[] c) {
//Used Set to remove duplicates
Set<Integer> setA = new HashSet<Integer>();
for (int i = 0; i < a.length; i++) {
setA.add(a[i]);
}
Set<Integer> setB = new HashSet<Integer>();
for (int i = 0; i < b.length; i++) {
setB.add(b[i]);
}
Set<Integer> setC = new HashSet<Integer>();
for (int i = 0; i < c.length; i++) {
setC.add(c[i]);
}
//Logic to fill data into a Map
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (Integer val : setA) {
map.put(val, 1);
}
for (Integer val : setB) {
if (map.get(val) != null) {
int count = map.get(val);
count++;
map.put(val, count);
} else {
map.put(val, 1);
}
}
for (Integer val : setC) {
if (map.get(val) != null) {
int count = map.get(val);
count++;
map.put(val, count);
} else {
map.put(val, 1);
}
}
for (Map.Entry<Integer, Integer> entry2 : map.entrySet()) {
//if (entry2.getValue() == 2) { //Return the elements that are present in two out of three arrays.
if(entry2.getValue() >= 2) { //Return elements that are present **at least** twice in the three arrays.
System.out.print(" " + entry2.getKey());
}
}
}
Change condition in last for loop in case one need to return the elements that are present in two out of three arrays. Say:
int[] a = { 2, 3, 8, 4, 1, 9, 8 };
int[] b = { 6, 5, 3, 7, 9, 2, 1 };
int[] c = { 5, 1, 8, 2, 4, 0, 5 };
Output: { 3, 8, 4, 5, 9 }
Here goes without any java.util library:
public static void twice(int[] a, int[] b, int[] c) {
int[] a1 = removeDuplicates(a);
int[] b1 = removeDuplicates(b);
int[] c1 = removeDuplicates(c);
int totalLen = a1.length + b1.length +c1.length;
int[][] keyValue = new int[totalLen][2];
int index = 0;
for(int i=0; i<a1.length; i++, index++)
{
keyValue[index][0] = a1[i]; //Key
keyValue[index][1] = 1; //Value
}
for(int i=0; i<b1.length; i++)
{
boolean found = false;
int tempIndex = -1;
for(int j=0; j<index; j++)
{
if (keyValue[j][0] == b1[i]) {
found = true;
tempIndex = j;
break;
}
}
if(found){
keyValue[tempIndex][1]++;
} else {
keyValue[index][0] = b1[i]; //Key
keyValue[index][1] = 1; //Value
index++;
}
}
for(int i=0; i<c1.length; i++)
{
boolean found = false;
int tempIndex = -1;
for(int j=0; j<index; j++)
{
if (keyValue[j][0] == c1[i]) {
found = true;
tempIndex = j;
break;
}
}
if(found){
keyValue[tempIndex][1]++;
} else {
keyValue[index][0] = c1[i]; //Key
keyValue[index][1] = 1; //Value
index++;
}
}
for(int i=0; i<index; i++)
{
//if(keyValue[i][1] == 2)
if(keyValue[i][1] >= 2)
{
System.out.print(keyValue[i][0]+" ");
}
}
}
public static int[] removeDuplicates(int[] input) {
boolean[] dupInfo = new boolean[500];//Array should not have any value greater than 499.
int totalItems = 0;
for( int i = 0; i < input.length; ++i ) {
if( dupInfo[input[i]] == false ) {
dupInfo[input[i]] = true;
totalItems++;
}
}
int[] output = new int[totalItems];
int j = 0;
for( int i = 0; i < dupInfo.length; ++i ) {
if( dupInfo[i] == true ) {
output[j++] = i;
}
}
return output;
}
It's very simple and could be done for n different arrays the same way:
public static void compute(int[] a1, int[] a2, int[] a3) {
HashMap<Integer, Integer> map = new HashMap<>();
fillMap(map, a1);
fillMap(map, a2);
fillMap(map, a3);
for (Integer key : map.keySet()) {
System.out.print(map.get(key) > 1 ? key + ", " : "");
}
}
public static void fillMap(HashMap<Integer, Integer> map, int[] a) {
for (int i : a) {
if (map.get(i) == null) {
map.put(i, 1);
continue;
}
int count = map.get(i);
map.put(i, ++count);
}
}
fun atLeastTwo(a: ArrayList<Int>, b: ArrayList<Int>, c: ArrayList<Int>): List<Int>{
val map = a.associateWith { 1 }.toMutableMap()
b.toSet().forEach { map[it] = map.getOrDefault(it, 0) + 1 }
c.toSet().forEach{ map[it] = map.getOrDefault(it, 0) + 1 }
return map.filter { it.value == 2 }.map { it.key }
}
In Javascript you can do it like this:
let sa = new Set(),
sb = new Set(),
sc = new Set();
A.forEach(a => sa.add(a));
B.forEach(b => sb.add(b));
C.forEach(c => sc.add(c));
let res = new Set();
sa.forEach((a) => {
if (sb.has(a) || sc.has(a)) res.add(a);
})
sb.forEach((b) => {
if (sa.has(b) || sc.has(b)) res.add(b);
})
sc.forEach((c) => {
if (sa.has(c) || sb.has(c)) res.add(c);
})
let arr = Array.from(res.values());
arr.sort((i, j) => i - j)
return arr
I have an array of numbers and I need the biggest of three number with respective index value. I have an array like this:
int [] value = new int[5];
value[0] = 8;
value[1] = 3;
value[2] = 5;
value[3] = 2;
value[4] = 7;
How to find the largest numbers and their index values?
I suspsect this is homework, so I'm going to give some help, but not a full solution.
You need the biggest three numbers, as well as their index values?
Well, walk over the array, keeping track of the highest three numbers you have found so far. Also keep track of their index numbers.
You could start by doing this for only the biggest number and its index. That should be easy.
It takes two variables, e.g. BiggestNumber and indexOfBiggestNumber. Start with finding the biggest number (trivial), then add some code to remember it's index.
Once you have that, you can add some more code to keep track of the second biggest number and it's index as well.
After that, you do the same for the third biggest number.
I have done it for you, and this works.
here goes the complete code:
import java.util.Arrays;
class tester {
public static void main(String[] args) {
int[] value = new int[5];
value[0] = 8;
value[1] = 3;
value[2] = 5;
value[3] = 2;
value[4] = 7;
int size = value.length;
int[] temp = (int[]) value.clone();
Arrays.sort(temp);
for (int i = 0; i < 3; i++) {
System.out.println("value: " + temp[size - (i + 1)] +
" index " + getIndex(value, temp[size - (i + 1)]));
}
}
static int getIndex(int[] value, int v) {
int temp = 0;
for (int i = 0; i < value.length; i++) {
if (value[i] == v) {
temp = i;
break;
}
}
return temp;
}
}
No need to traverse through array and keep tracking of so many variables , you can take advantage of already implemented methods like below.
I would suggest to use a List of Map.Entry<key,value > (where key=index and value=number) and then implement Comparator interface with overridden compare method (to sort on values). Once you have implemented it just sort the list .
public static void main(String[] args) {
int[] value = {5, 3, 12, 12, 7};
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int k = 0; k < value.length; k++)
map.put(k, value[k]);
List<Map.Entry<Integer, Integer>> list =
new LinkedList<Map.Entry<Integer, Integer>>(map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<Integer, Integer>>() {
#Override
public int compare(
Entry<Integer, Integer> e1,
Entry<Integer, Integer> e2) {
return e2.getValue().compareTo(e1.getValue());
}
});
for (Entry<Integer, Integer> lValue : list)
System.out.println("value = " + lValue.getValue()
+ " , Index = " + lValue.getKey());
}
Results:
value = 12 , Index = 2
value = 12 , Index = 3
value = 7 , Index = 4
value = 5 , Index = 0
value = 3 , Index = 1
By this approach you can get top N largest numbers with their index.
To get the three biggest, basically, you sort, and pick the last three entries.
Getting their indexes takes a little more work, but is definitely doable. Simply bundle the number and its index together in a Comparable whose compareTo function only cares about the number. Sort, get the last three items, and now you have each number and its index.
class IntWithIndex implements Comparable<IntWithIndex> {
public int number, index;
public IntWithIndex(number, index) {
this.number = number;
this.index = index;
}
public int compareTo(IntWithIndex other) {
return number - other.number;
}
}
...
IntWithIndex iwi[] = new IntWithIndex[yourNumbers.length];
for (int i = 0; i < yourNumbers.length; ++i) {
iwi[i] = new IntWithIndex(yourNumbers[i], i);
}
Arrays.sort(iwi);
int largest = iwi[iwi.length - 1].number;
int largestIndex = iwi[iwi.length - 1].index;
// and so on
Sort the array in descending order and show the first 3 element.