I'm working on the following problem:
Given an array of integers and a sum B, find all unique combinations in the array where the sum is equal to B. The same number may be chosen from the array any number of times to make B.
Note:
All numbers will be positive integers.
Elements in a combination (a1, a2, …, ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak).
The combinations themselves must be sorted in ascending order. Example:
Input:
N = 4
arr[] = {7,2,6,5}
B = 16
Output:
(2 2 2 2 2 2 2 2)
(2 2 2 2 2 6)
(2 2 2 5 5)
(2 2 5 7)
(2 2 6 6)
(2 7 7)
(5 5 6)
The problem is for the input arr[] = {8, 1, 8, 6, 8}, B = 12
I am getting (1 1 1 1 1 1 1 1 1 1 1 1)(1 1 1 1 1 1 6)(1 1 1 1 8)(1 1 1 1 8)(1 1 1 1 8)(6 6) as output but the correct output is (1 1 1 1 1 1 1 1 1 1 1 1)(1 1 1 1 1 1 6)(1 1 1 1 8)(6 6)
My code:
static void findCombination(int idx, int target, int[] arr, ArrayList<ArrayList<Integer>> ans, List<Integer> ds){
//base case
if(idx == arr.length){
if(target == 0){
ans.add(new ArrayList<>(ds));
}
return;
}
//recursion
if(arr[idx] <= target){
ds.add(arr[idx]);
findCombination(idx,target-arr[idx],arr,ans,ds); //function call
ds.remove(ds.size()-1); //backtracking step
}
findCombination(idx+1,target,arr,ans,ds);
}
//Function to return a list of indexes denoting the required
//combinations whose sum is equal to given number.
static ArrayList<ArrayList<Integer>> combinationSum(ArrayList<Integer> A, int B)
{
// add your code here
ArrayList<ArrayList<Integer>> ans = new ArrayList<>();
int[] arr = new int[A.size()];
int i = 0;
for(int val : A){
arr[i++] = val;
}
Arrays.sort(arr);
findCombination(0, B, arr, ans, new ArrayList<>());
return ans;
}
}
You should be dealing with unique values.
static ArrayList<ArrayList<Integer>> combinationSum(ArrayList<Integer> A, int B) {
ArrayList<ArrayList<Integer>> ans = new ArrayList<>();
findCombination(0, B,
A.stream().mapToInt(Integer::intValue).distinct().sorted().toArray(),
ans, new ArrayList<>());
return ans;
}
You can use a Set or Hashset instead of the ArrayList. It will provide you with unique results only.
Related
Given some array nums and a positive integer k, determine if its possible to divide this array into sets of k consecutive numbers.
Example:
nums = [1,2,3,4] k = 2
Output true since [1,2], [3, 4]
My thoughts is that that size of the array nums has to be divisible by the integer k. But when I use that as the test I fail for this test case:
[15,16,17,18,19,16,17,18,19,20,6,7,8,9,10,3,4,5,6,20] k = 5
I get true but the answer is false and I am not sure why. Any ideas?
Here is my code:
int n = nums.size();
if(n % k == 0)
return true;
return false;
Here are more examples if that helps:
The problem can be solved by sorting the array, counting duplicates, and then verifying the consecutive sequences.
Consider example 2, where k=3 and the array is
[3,2,1,2,3,4,3,4,5,9,10,11]
After sorting:
[1,2,2,3,3,3,4,4,5,9,10,11]
After counting duplicates (the top line has the unique numbers in the array, the bottom line has the duplicate count for each number):
1 2 3 4 5 9 10 11
1 2 3 2 1 1 1 1
Now check the sequences. The lowest number is 1, so the sequence [1,2,3] must exist in the array, or the output is false. 1, 2, and 3 all have non-zero counts, so the array does contain that sequence. Update the counts to remove that sequence:
1 2 3 4 5 9 10 11
0 1 2 2 1 1 1 1
Now 2 is the lowest number with a non-zero count, so the next sequence is [2,3,4] and the updated counts are:
1 2 3 4 5 9 10 11
0 0 1 1 1 1 1 1
Finish up with [3,4,5] and [9,10,11]
Solution:
step1. Use TreeMap to store array elements and their occurrence. Treemap helps us to store the element in sorting orders.
step2. Iterate over treemap until it's not empty.
step3. Takeout the first key (firstKey) from treemap and start searching next K consecutive element.
public static boolean isPossibleDivide(int[] arr, int k) {
TreeMap<Integer, Integer> map = new TreeMap<Integer, Integer>();
for (int i = 0; i < arr.length; i++) {
map.put(arr[i], map.get(arr[i]) != null ? map.get(arr[i]) + 1 : 1);
}
while (!map.isEmpty()) {
int firstKey = map.firstKey();
for (int i = 0; i < k; i++) {
int key = firstKey + i;
if (!map.containsKey(key)) {
return false;
} else {
map.put(key, map.get(key) - 1);
if (map.get(key) == 0)
map.remove(key);
}
}
}
return true;
}
bool isPossibleDivide(vector<int>& nums, int k) {
int n = nums.size();
if(n%k != 0)return false;
sort(nums.begin(),nums.end());
map<int,int> m;
for(int i=0;i<n;i++){
m[nums[i]]++;
}
int nu = m.size() - k + 1;
for(auto it=m.begin();it!=m.end();it++){
if(!nu)break;
int x = it->second;
int l=0;
map<int,int> :: iterator s = it;
map<int,int> :: iterator s1 = s ;
while(l<k){
s->second = s->second - x;
s++;
if(s->first - s1->first !=1 && l<k-1)return false;
s1++;
l++;
}
nu--;
}
/*for(auto it=m.begin();it!=m.end();it++){
cout << it->first <<" "<<it->second <<endl;
}*/
for(auto it=m.begin();it!=m.end();it++){
if(it->second != 0) return false;
}
return true;
}
I have done this, but I don't know why it is not working
I want to generate all subsets of a set from 0 to n.
My code works successfully in c++, but in Java I've got different result
My code in c++:
#include <bits/stdc++.h>
using namespace std;
vector <vector<int>> v;
vector <int> u;
int n,i,j;
void f(vector <int> m,int k){
if(k==n+1){v.push_back(m);return;}
f(m,k+1);
m.push_back(k);
f(m,k+1);
}
int main() {
cin>>n;
f(u,0);
for(i=0;i<v.size();i++){
for(j=0;j<v[i].size();j++)cout<<v[i][j]<<' ';
cout<<endl;
}
}
input in c++: 2
output:
2
1
1 2
0
0 2
0 1
0 1 2
and my code in Java:
import java.util.*;
public class Main {
public static int c=0,j,i,n,l,r,x;
public static Vector <Vector<Integer>> v = new Vector();
public static void f(Vector <Integer> m,int k){
if (k==n+1) {v.add(m);return;}
f(m,k+1);
m.add(k);
f(m,k+1);
}
public static void main(String[] args) {
Scanner scan = new Scanner (System.in);
n=scan.nextInt();
Vector<Integer> u = new Vector<Integer>();
f(u,0);
for(i=0;i<v.size();i++){
for(int j:v.get(i))System.out.print(j+" ");
System.out.print("\n");
}
}
}
input in Java: 2
output:
2 1 2 0 2 1 2
2 1 2 0 2 1 2
2 1 2 0 2 1 2
2 1 2 0 2 1 2
2 1 2 0 2 1 2
2 1 2 0 2 1 2
2 1 2 0 2 1 2
2 1 2 0 2 1 2
As you see code in java is based on same logic but I cannot understand why java version gives me wrong result.
As you see code in java is based on same logic but I cannot Understand Why java code gives me wrong result
There is a big difference between C++ and Java here. In C++, unless you explicitly use vector<int> & v to use the same vector, it will automatically make a copy while in Java you have to explicitly do the copy yourself. Java uses pass-by-value mechanism and you only created one vector and then use it all the way which actually using the same vector.
Your problem lies: using the same vector to collect the elements all the way through.
To solve this problem, you should create a new vector to store the elements when passing in the method as:
public class HelloWorld {
public static int c = 0, j, i, n, l, r, x;
public static Vector<Vector<Integer>> v = new Vector();
// each combination of the elements should have an independent vector;
public static void f(Vector<Integer> m, int k) {
if (k == n + 1) {
v.add(m);
return;
} // the unique vector;
f(new Vector<>(m), k + 1); // create a new vector to store the elements;
m.add(k);
f(new Vector<>(m), k + 1); // same logic applied here;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
Vector<Integer> u = new Vector<Integer>();
f(new Vector<>(), 0);
for (i = 0; i < v.size(); i++) {
for (int j : v.get(i)) System.out.print(j + " ");
System.out.print("\n");
}
}
}
Output can be:
3
3
2
2 3
1
1 3
1 2
1 2 3
0
0 3
0 2
0 2 3
0 1
0 1 3
0 1 2
0 1 2 3
For a A * B matrix of all distinct numbers from 1 to A * B, we first sort each column and then concatenate all columns in increasing order of indices to form an array of size A * B. Columns are numbered in increasing order from left to right.
For example, if matrix is
[1 5 6]
[3 2 4]
We first sort all columns to get
[1 2 4]
[3 5 6]
Now, we concatenate columns in increasing order of indices to get an array
[1, 3, 2, 5, 4, 6]
Given this final array, you have to count how many distinct initial matrices are possible. Return the required answer modulo 10^9+7.
Two matrices are distinct if:
- Either their dimensions are different.
- Or if any of the corresponding row in two matrices are different.
Example:
If input array is [1, 3, 2, 4], distinct initial matrices possible are:
[1 3 2 4]
============
[1 2]
[3 4]
=============
[1 4]
[3 2]
===========
[3 2]
[1 4]
===========
[3 4]
[1 2]
===========
that is, a total of 5 matrices.
Here is what is did:
I found the ways we can arrange values in every subarray of size(len/2).
So if an array is [1,2,3,4]
we have two subarrays [1,2]&[3,4].So the answer will be 2!*2!.Thing is we have to get the unique rows as well.That's where my code failed.
Can you enlighten me in the right direction.
Here's my code;
public int cntMatrix(ArrayList<Integer> a) {
if(a.size()==1){
return 1;
}
int n=a.size();
int len=n/2;
int i=0;
long ans=1;
if(n%2!=0){ //n is odd
ans=fact(n); //factorial function
}else{
while(i<n){
int x=i;
int y=i+len;
HashMap<Integer,Integer> map=new HashMap<>(); //frequency of each element in subarray[x..y]
for(int m=i;m<y;m++){
if(map.containsKey(a.get(m))){
map.put(a.get(m),map.get(a.get(m))+1);
}else{
map.put(a.get(m),1);
}
}
long p=fact(len);
long q=1;
for(Map.Entry<Integer,Integer> set:map.entrySet()){
int key=set.getKey();
int value=set.getValue();
q*=fact(value);
}
ans*=p/q; //ncr
map.clear();
i+=len;
}
}
ans%=1000000007;
return ((int)ans+1);
}
How to deal with unique rows
Asked on interviewbit.com
One thing that I noticed is that you check if the length is odd or not.
This is not right, if for example, the length is 9 you can arrange a 3x3 matrix that will suffice the conditions.
I think that you should try to "cut" the array into columns with the sizes 1 - n and for each size check if it can be an initial matrix.
The complexity of my algorithm is O(n^2), though I feel like there is a better one.
This is my python code -
class Solution:
# #param A : list of integers
# #return an integer
def cntMatrix(self, A):
count = 0
n = len(A)
# i = number of rows
for i in range(1, n + 1):
if n % i == 0:
can_cut = True
start = 0
while start < len(A) and can_cut:
prev = 0
for j in range(start, start + i):
if prev > A[j]:
can_cut = False
prev = A[j]
start += i
if can_cut:
count = (count + pow(math.factorial(i), n / i)) % (pow(10, 9) + 7)
return count
I didn't check it on their site because the question page couldn't be found anymore, I saw it only on the ninja test.
After running -
s = Solution()
print(s.cntMatrix([1, 2, 3, 1, 2, 3, 1, 2, 3]))
We get - 217 = 3! * 3! * 3! + 1
class Solution:
# #param A : list of integers
# #return an integer
def cntMatrix(self, A):
self.factCache = {}
bucket = 1
buckets = []
while bucket <= len(A):
if len(A) % bucket == 0:
buckets.append(bucket)
bucket += 1
valid_buckets = []
for bucket in buckets:
counter = 1
invalid = False
for i in range(1, len(A)):
if counter == bucket:
counter = 1
continue
if A[i] > A[i - 1]:
counter += 1
else:
invalid = True
break
if not invalid:
valid_buckets.append(bucket)
combs = 0
for bucket in valid_buckets:
rows = bucket
columns = int(len(A)/rows)
combs += (self.fact(rows) ** columns)
return combs % 1000000007
def fact(self, number):
if number == 0 or number == 1:
return 1
fact = 1
for i in range(1, number + 1):
fact = fact * i
return fact
Here is example of my input data:
5 // Number of 1D arrays, in this case we'll have array[5][3]
1 2 3 // Values of array[i][0..2]
1 1 1
1 0 0
1 1 0
2 1 0
And output is:
12 // Maximum sum ({1 2 3} + {1 1 1} + {2 1 0} = {4 4 4} = 12) - END SUM VALUES MUST BE EQUAL(4 4 4).
3 // Number of arrays used to get this sum
The problem is to find maximum sum using n arrays, and secod condition is to use minimum number of arrays. Also if sum > 300 we stop algorithm. (300 is maximum). Here is my code, it's I get good answers but it's time complexity is O(2^n-1). I'm thinking that it's possible to save results in some way and don't calculate same things many times, but I don't know how yet.
public static int[] fuel(int start, int[] sum, int counter) {
int[] val = { sum[0] + crystal[start][0], sum[1] + crystal[start][1], sum[2] + crystal[start][2] };
int newSum = val[0] + val[1] + val[2];
if(newSum > 300)
return null;
if(val[0] == val[1] && val[1] == val[2]) { // All 3 values have to be equal!
if(newSum > result[0]) {
result[0] = newSum;
result[1] = counter;
} else if(newSum == result[0] && result[1] > counter) {
result[1] = counter;
}
}
if(start + 1 < crystalNumber) {
fuel(start + 1, val, counter + 1);
fuel(start + 1, sum, counter);
}
return result;
}
This may not be the best algorithm to solve this but it should be quicker than O(2^N).
The idea is to record all reachable sums as you loop through the input array. You can use a dictionary whose key is a unique hash of the possible sums, for the sake of simplicity let's just assume the key is a string which concatenates the three sums, for example, the sums [3,5,4] we'll use the key "003005004" , the value of the dictionary will be the minimum numbers of arrays to reach that sum.
So in your case:
1 2 3 => [001002003] =1
1 1 1 => [001001001] =1, [002003004]=2 (itself and use [001002003] from above)
1 0 0 => [001000000] =1, [002002003] =2, [002001001] =2, [003003004] =3
1 1 0 ...
2 1 0 ...
In the end, you will find [004004004] =3 and that's your answer.
This may seems going through all combinations as well so why it's quicker, it's because the maximum sum is 300 for each number, so in the very worst case, we may have 301^3 keys filled and have to update their values for each new input array. This is however still O(n) and despite of the large constant, it should still run much faster than O(2^n). (If you solve 300^3*n = 2^n, n is around 30-ish)
A simple hash function would be a*301*301+b*301+c
I think the problem is given m 1-D arrays and a number n, find the maximum sum using n arrays from m;
The solution looks straight forward. keep sum of each 1-D array in a separate array, say sum[]
1 2 3 = 6
1 1 1 = 3
1 0 0 = 1
1 1 0 = 2
2 1 0 = 3
Sort this array sum
6,3,3,2,1
and return the sum of first n elements of this array.
Let's say I have a list [x1, x2, x3] where x1, x2, and x3 can take on any value between 1 and 5.
I want to iterate over every possible list that can be created (From [1, 1, 1], [1, 1, 2], . To [5, 5, 5]). This is an easy problem with only 3 elements in the list.
You can do something like this:
for x = 1; x <= 5; x++;
for y = 1; y <= 5; y++;
...
for q = 1; q <= 5; q++;
create list [x, y, ..., q];
do something with the list;
However, how do you iterate over every possible list where the number of elements is over like 10?
Edi: I've added Java as a constraint. I just want to see how this would be done without too many fancy library calls.
Edit2: What I am really looking for is some algorithm to do this, not what sort of libraries can be used to do it. But what I'm looking for is really a language-independent algorithm.
Using Guava you can do it easily:
public static void main(String[] args) {
int lowerBound = 1;
int upperBound = 5;
int setSize=3;
ContiguousSet<Integer> integers = ContiguousSet.create(Range.closed(lowerBound, upperBound), DiscreteDomain.integers());
List<Set<Integer>> sets = Lists.newArrayList();
for (int i = 0; i < setSize; i++) {
sets.add(integers);
}
Set<List<Integer>> cartesianProduct = Sets.cartesianProduct(sets);
for (List<Integer> list : cartesianProduct) {
System.out.println(list);
}
}
Which prints:
[1, 1, 1]
[1, 1, 2]
[1, 1, 3]
[1, 1, 4]
[1, 1, 5]
...
[5, 5, 4]
[5, 5, 5]
Logic :
In arr[x1 x2 x3]; all x1, x2, x3 can have values from 1 to 5. Which means every position in array can have value from 1 to 5. For a value at current position all the values are possible at next position.
suppose at 0 position of array value stored is 1.
[1 _ _] _ represent there is no value.
values for the next position : [1 1 _] , [1 2 _] ,[1 3 _] ,[1 3 _] ,[1 4 _],[1 5 _].
So iterate over current position to store the different possible values from 1 to 5 at current position and for each value call the permutate function again with current position value incremented by 1 for iterating all possible values from 1 to 5 at next position .
Code :
public class permutation {
static int limit;
public static void permutate(int arr[],int curPos)
{
int i;
if(curPos==arr.length)
{
for(i=0;i<arr.length;i++)
{
System.out.print(arr[i] + "\t");
}
System.out.println("");
return;
}
for(i=1;i<=limit;i++)
{
arr[curPos]=i;
permutate(arr,curPos+1);
}
}
public static void main(String[] args) {
int arr[] = new int[3];
limit = 5;
permutate(arr,0);
}
}
Output :
1 1 1
1 1 2
1 1 3
1 1 4
1 1 5
1 2 1
1 2 2
1 2 3
1 2 4
1 2 5
1 3 1
1 3 2
1 3 3
1 3 4
1 3 5
1 4 1
1 4 2
1 4 3
1 4 4
1 4 5
1 5 1
1 5 2
1 5 3
1 5 4
1 5 5
2 1 1
2 1 2
2 1 3
2 1 4
2 1 5
2 2 1
2 2 2
2 2 3
2 2 4
2 2 5
2 3 1
2 3 2
2 3 3
2 3 4
2 3 5
2 4 1
2 4 2
2 4 3
2 4 4
2 4 5
2 5 1
2 5 2
2 5 3
2 5 4
2 5 5
3 1 1
3 1 2
3 1 3
3 1 4
3 1 5
3 2 1
3 2 2
3 2 3
3 2 4
3 2 5
3 3 1
3 3 2
3 3 3
3 3 4
3 3 5
3 4 1
3 4 2
3 4 3
3 4 4
3 4 5
3 5 1
3 5 2
3 5 3
3 5 4
3 5 5
4 1 1
4 1 2
4 1 3
4 1 4
4 1 5
4 2 1
4 2 2
4 2 3
4 2 4
4 2 5
4 3 1
4 3 2
4 3 3
4 3 4
4 3 5
4 4 1
4 4 2
4 4 3
4 4 4
4 4 5
4 5 1
4 5 2
4 5 3
4 5 4
4 5 5
5 1 1
5 1 2
5 1 3
5 1 4
5 1 5
5 2 1
5 2 2
5 2 3
5 2 4
5 2 5
5 3 1
5 3 2
5 3 3
5 3 4
5 3 5
5 4 1
5 4 2
5 4 3
5 4 4
5 4 5
5 5 1
5 5 2
5 5 3
5 5 4
5 5 5
At least in python (You should specify language if it's a constraint):
>>> from itertools import permutations as permu
>>> for i in permu(range(5), 3):
... print i
...
(0, 1, 2)
(0, 1, 3)
(0, 1, 4)
(0, 2, 1)
(0, 2, 3)
(0, 2, 4)
(0, 3, 1)
....
In recursive solution you don't have to sort the list every time. Giving sorted list to recursive function must be sifficient.
To do so, I've written this piece of C# code. Length of output result will be determined by len. Just remember that input length must be equal or bigger than len:
// Input must be sorted, Result must be initialized to empty list
void Iterate(List<int> input, int len, List<int> result)
{
if(result.Count == n)
print result
else
foreach (var i in input)
Iterate(input, len, result.Append(num).ToList())
}
Use this algorithm.
Input: X is the minimum number, Y is the maximum number, and Z is the number of independent choices.
Create an array of size Z, with each element equal to X. Call it Permutation.
Loop:
Add a copy of Permutation to the list of permutations.
Set J to Z minus 1.
Loop:
Add 1 to Permutation[J]. If Permutation[J] is now Y or less, break.
Set Permutation[J] to X.
Subtract 1 from J. If J is now less than 0, return the list of permutations.
Must be classic algorithm. But it always fun to write it from scratch. Here is Java class accepting data set and result list size parameters. Core method is generate(). Also lists might be copied on demand (to be more functional style).
import com.google.common.collect.Maps;
import org.apache.commons.lang.ArrayUtils;
import java.util.Map;
public class PermutationGenerator {
private int listValuesSize;
private int resultListSize;
private String[] currentList;
private Map<String, String> nextValue = Maps.newHashMap();
private int permutations = 0;
public PermutationGenerator(String[] dataSet, int resultListSize) {
this.listValuesSize = dataSet.length;
this.resultListSize = resultListSize;
init(dataSet);
}
private void init(String[] dataSet) {
// rolling values
String previous = dataSet[0];
for (int valuesIndex = 1; valuesIndex < dataSet.length; valuesIndex++) {
nextValue.put(previous, dataSet[valuesIndex]);
previous = dataSet[valuesIndex];
}
nextValue.put(dataSet[dataSet.length - 1], dataSet[0]);
// init
currentList = new String[resultListSize];
for (int i = 0; i < resultListSize; i++) {
currentList[i] = dataSet[0];
}
}
public void generate() {
generate(0, resultListSize - 1);
}
private void generate(int from, int to) {
if (from > to) {
return;
}
for (int i = 0; i < listValuesSize; i++) {
if (from == to) {
processList(currentList);
} else {
generate(from + 1, to);
}
roll(from);
}
}
private void roll(int position) {
currentList[position] = nextValue.get(currentList[position]);
}
private void processList(String[] list) {
permutations++;
System.out.println(ArrayUtils.toString(list));
}
public static void main(String... args) {
PermutationGenerator generator = new PermutationGenerator(new String[]{"1", "2", "3", "4", "5"}, 3);
generator.generate();
System.out.println(generator.permutations);
}
}