how do I get all combinations of elements in a list? - c++

When getting a list of X elements, how can I get all doubles, triples, ... ( Y ) combinations of these elements ?
Y being the size of the required combinations. Ex : if Y = 2, I need to get all of the possible pairs.
I must not give the same combinations twice ( ex : [a, b] and [b, a] are the same combination )

Take a copy of the list.
If the list is empty, there are no combinations.
To get all combinations of size one, look at each element in turn.
To get all combinations of size n+1, first remove the first element. Then get all combinations of size n of the rest of the list, plus that first element. Then get all combinations of size n+1 of the rest of the list, and don't add the first element.
And then you are done.
You can get fancy and merely pretend to copy/remove elements for optimization sake.

You can iterate t from 2 to Y, and create an array A with the size X fill with X-t 0s in the front and t 1s in the back, then with the code below:
do{
//1s in array A now correspond to a valid combination
}while(std::next_permutation(A,A+X));
The loop will stop when all combination with size t are iterated
next_permutation is in header algorithm, it will reorder the array to the next lexicographically greater permutation or return false if the array is already in the lexicographically greatest permutation. Its complexity is O(n), since you also need to iterate through the array once, so it wouldn't be a problem. Total complexity for the whole process will be bounded by O(2^n*n).
So here is an example pseudo code
D[X] = {1,2,3,4} Y = 3 //the input
For t = 2,3,..,Y
A[X] = {0,...,0,1,...,1} // X - t 0s and t 1s
Do
For j = 0,1,...,X-1
if A[j] == 1
output D[j]
end if
end for
output newline
While next_permutation(A,A+X)
end for
The output will looks like
3 4
2 4
2 3
1 4
1 3
1 2
2 3 4
1 3 4
1 2 4
1 2 3

Related

finding whats wrong with my code,solving a easy competitive problem

QN;Here is the question.i dont know where my algorithm is wrong.help me find pls
Given an array A of N length. We need to calculate the next greater element for each element in given array. If next greater element is not available in given array then we need to fill ‘_’ at that index place.
Input:
The first line contains an integer T, the number of test cases. For each test case, the first line contains an integer n, the size of the array. Next line contains n space separated integers denoting the elements of the array.
Output:
For each test case, the output is an array that displays next greater element to element at that index.
Constraints:
1 <= T <= 100
1 <= N <= 100
-106 <= Ai <= 106
Example:
Input
2
9
6 3 9 8 10 2 1 15 7
4
13 6 7 12
Output:
7 6 10 9 15 3 2 _ 8
_ 7 12 13
Explanation:
Testcase 1: Here every element of the array has next greater element but at index 7, 15 is the greatest element of given array and no other element is greater from 15 so at the index of 15 we fill with ''.
Testcase 2: Here, at index 0, 13 is the greatest value in given array and no other array element is greater from 13 so at index 0 we fill ''.
My solution:
//NOT SOLVED YET
#include<iostream>
using namespace std;
int main()
{
int a[10]={6 ,3 ,9, 8 ,10, 2 ,1, 15, 7};
int b[10],flag=0,big=-1,i,j;
for(i=0;i<10;i++)
{
for(j=0;j<10;j++)
{
if(i==j)continue;
if((a[j]>a[i]) && (flag==0))
{
big=a[j];
flag=1;
}
else if(a[j]<big && big>a[i] && flag==1)
big=a[j];
}
if(big==-1)cout<<'_';
else cout<<big<<' ';
big=-1;
flag=0;
}
}
the output i get is:
2 2 2 2 7 1 0 _ 2 1
The condition should be:
else if(a[j] < big && a[j] > a[i] && flag == 1)
Indeed, if you use big > a[i], then that means you just check if the thus far next greater element was larger than a[i], but this thus makes it possible to select a value later in the process that is smaller than big, but smaller than a[i] as well. Here we thus want to check if a[j] is between a[i] and big.
That being said, the above approach is not very efficient. Indeed, for each element, you calculate the next element in linear time, making this a quadratic time algorithm. You might want to look at solutions where the list is sorted first. You can for example use min-heap here to move over the list in two passes.
To expand on what others have mentioned - that you currently have an O(N^2) algorithm, and this can be done more efficiently.
I don't think you can get O(N) here, but here is a plan for an O(N log N) algorithm:
For each test case:
Load the Ai values into two arrays, let's call them X and Y
Sort the Y array
Iterate over X and for each element of X do a binary search into Y to find the next larger value of Ai: use that as the output, or use _ if you did not find one
I recommend, for practice purposes, implementing this both using the C++ standard library, using https://en.cppreference.com/w/cpp/algorithm/sort and https://en.cppreference.com/w/cpp/algorithm/upper_bound , and implementing the above two functions yourself, see: https://en.wikipedia.org/wiki/Quicksort

Every sum possibilities of elements

From a given array (call it numbers[]), i want another array (results[]) which contains all sum possibilities between elements of the first array.
For example, if I have numbers[] = {1,3,5}, results[] will be {1,3,5,4,8,6,9,0}.
there are 2^n possibilities.
It doesn't matter if a number appears two times because results[] will be a set
I did it for sum of pairs or triplet, and it's very easy. But I don't understand how it works when we sum 0, 1, 2 or n numbers.
This is what I did for pairs :
std::unordered_set<int> pairPossibilities(std::vector<int> &numbers) {
std::unordered_set<int> results;
for(int i=0;i<numbers.size()-1;i++) {
for(int j=i+1;j<numbers.size();j++) {
results.insert(numbers.at(i)+numbers.at(j));
}
}
return results;
}
Also, assuming that the numbers[] is sorted, is there any possibility to sort results[] while we fill it ?
Thanks!
This can be done with Dynamic Programming (DP) in O(n*W) where W = sum{numbers}.
This is basically the same solution of Subset Sum Problem, exploiting the fact that the problem has optimal substructure.
DP[i, 0] = true
DP[-1, w] = false w != 0
DP[i, w] = DP[i-1, w] OR DP[i-1, w - numbers[i]]
Start by following the above solution to find DP[n, sum{numbers}].
As a result, you will get:
DP[n , w] = true if and only if w can be constructed from numbers
Following on from the Dynamic Programming answer, You could go with a recursive solution, and then use memoization to cache the results, top-down approach in contrast to Amit's bottom-up.
vector<int> subsetSum(vector<int>& nums)
{
vector<int> ans;
generateSubsetSum(ans,0,nums,0);
return ans;
}
void generateSubsetSum(vector<int>& ans, int sum, vector<int>& nums, int i)
{
if(i == nums.size() )
{
ans.push_back(sum);
return;
}
generateSubsetSum(ans,sum + nums[i],nums,i + 1);
generateSubsetSum(ans,sum,nums,i + 1);
}
Result is : {9 4 6 1 8 3 5 0} for the set {1,3,5}
This simply picks the first number at the first index i adds it to the sum and recurses. Once it returns, the second branch follows, sum, without the nums[i] added. To memoize this you would have a cache to store sum at i.
I would do something like this (seems easier) [I wanted to put this in comment but can't write the shifting and removing an elem at a time - you might need a linked list]
1 3 5
3 5
-----
4 8
1 3 5
5
-----
6
1 3 5
3 5
5
------
9
Add 0 to the list in the end.
Another way to solve this is create a subset arrays of vector of elements then sum up each array's vector's data.
e.g
1 3 5 = {1, 3} + {1,5} + {3,5} + {1,3,5} after removing sets of single element.
Keep in mind that it is always easier said than done. A single tiny mistake along the implemented algorithm would take a lot of time in debug to find it out. =]]
There has to be a binary chop version, as well. This one is a bit heavy-handed and relies on that set of answers you mention to filter repeated results:
Split the list into 2,
and generate the list of sums for each half
by recursion:
the minimum state is either
2 entries, with 1 result,
or 3 entries with 3 results
alternatively, take it down to 1 entry with 0 results, if you insist
Then combine the 2 halves:
All the returned entries from both halves are legitimate results
There are 4 additional result sets to add to the output result by combining:
The first half inputs vs the second half inputs
The first half outputs vs the second half inputs
The first half inputs vs the second half outputs
The first half outputs vs the second half outputs
Note that the outputs of the two halves may have some elements in common, but they should be treated separately for these combines.
The inputs can be scrubbed from the returned outputs of each recursion if the inputs are legitimate final results. If they are they can either be added back in at the top-level stage or returned by the bottom level stage and not considered again in the combining.
You could use a bitfield instead of a set to filter out the duplicates. There are reasonably efficient ways of stepping through a bitfield to find all the set bits. The max size of the bitfield is the sum of all the inputs.
There is no intelligence here, but lots of opportunity for parallel processing within the recursion and combine steps.

Finding the permutation that satisfy given condition

I want to find out the number of all permutation of nnumber.Number will be from 1 to n.The given condition is that each ithposition can have number up to Si,where Si is given for each position of number.
1<=n<=10^6
1<=si<=n
For example:
n=5
then its all five element will be
1,2,3,4,5
and given Si for each position is as:
2,3,4,5,5
It shows that at:
1st position can have 1 to 2that is 1,2 but can not be number among 3 to 5.
Similarly,
At 2nd position can have number 1 to 3 only.
At 3rd position can have number 1 to 4 only.
At 4th position can have number 1 to 5 only.
At 5th position can have number 1 to 5 only.
Some of its permutation are:
1,2,3,4,5
2,3,1,4,5
2,3,4,1,5 etc.
But these can not be:
3,1,4,2,5 As 3 is present at 1st position.
1,2,5,3,4 As 5 is present at 3rd position.
I am not getting any idea to count all possible number of permutations with given condition.
Okay, if we have a guarantee that numbers si are given in not descending order then looks like it is possible to calculate the number of permutations in O(n).
The idea of straightforward algorithm is as follows:
At step i multiply the result by current value of si[i];
We chose some number for position i. As long as we need permutation, that number cannot be repeated, so decrement all the rest si[k] where k from i+1 to the end (e.g. n) by 1;
Increase i by 1, go back to (1).
To illustrate on example for si: 2 3 3 4:
result = 1;
current si is "2 3 3 4", result *= si[0] (= 1*2 == 2), decrease 3, 3 and 4 by 1;
current si is "..2 2 3", result *= si[1] (= 2*2 == 4), decrease last 2 and 3 by 1;
current si is "....1 2", result *= si[2] (= 4*1 == 4), decrease last number by 1;
current si is "..... 1", result *= si[3] (= 4*1 == 4), done.
Hovewer this straightforward approach would require O(n^2) due to decreasing steps. To optimize it we can easily observe that at the moment of result *= si[i] our si[i] was already decreased exactly i times (assuming we start from 0 of course).
Thus O(n) way:
unsigned int result = 1;
for (unsigned int i = 0; i < n; ++i)
{
result *= (si[i] - i);
}
for each si count the number of element in your array such that a[i] <= si using binary search, and store the value to an array count[i], now the answer is the product of all count[i], however we have decrease the number of redundancy from the answer ( as same number could be count twice ), for that you can sort si and check how many number is <= s[i], then decrease that number from each count,the complexity is O(nlog(n)), hope at least I give you an idea.
To complete Yuriy Ivaskevych answer, if you don't know if the sis are in increasing order, you can sort the sis and it will also works.
And the result will be null or negative if the permutations are impossible (ex: 1 1 1 1 1)
You can try backtracking, it's a little hardcore approach but will work.
try:
http://www.thegeekstuff.com/2014/12/backtracking-example/
or google backtracking tutorial C++

find a single element in an array of consecutive duplicate elements

Given an array of elements where every element is repeated except a single element. Moreover all the repeated elements are consecutive to each other.
We need to find out the index of that single element.
Note:
array may not be sorted
expected time O(logn)
range of elements can
be anything.
O(n) is trivial. but how can I figure out logn?
Gave a thought to bitwise operators also but nothing worked out.
Also, I am unable to make use of this statement in this question all the repeated elements are consecutive to each other.
Ex: 2 2 3 3 9 9 1 1 5 6 6
output 5
It can be done in O(logn) by checking if arr[2k] == arr[2k+1], k>=0 - if it is, then the distinct elementt is AFTER 2k+1, if it's not - than it is before before 2k+1.
This allows you to effectively trim half of the array at each step by checking the middle value, and recursing only on a problem half as big, getting it O(logn) overall.
Python code:
def findUnique(arr,l,r):
if r-l < 2:
return (arr[l],l)
mid = (r-l)/2 + l
if mid % 2 != 0:
flag = -1
else:
flag = 0
if (mid == 0 or arr[mid-1] != arr[mid] ) and (mid == len(arr)-1 or arr[mid] != arr[mid+1] ):
return (arr[mid],mid)
if arr[mid+flag] == arr[mid+1+flag]:
return findUnique(arr,mid,r)
return findUnique(arr,l,mid)
Assuming each element is repeated exactly twice, except one, then it is easy.
The first answer is correct, just feel like I could elaborate a bit on it.
So, lets take your example array.
a = [2 2 3 3 9 9 1 1 5 6 6];
If all elements were paired, then you can take an even index and know for sure that the next element will be the same.
a[0] = 2;
a[1] = 2; //as well
a[2] = 3;
a[3] = 3; //as well
General case:
a[k] = a[k+1] = x;
where k is even, and x is some value.
BUT, in your case, we know that there is one index that doesn't follow this rule.
in order to find it, we can use Binary Search (just for reference), with a bit of extra computation in the middle.
We go somewhere in the middle, and grab an element with an even index.
If that elements' value equals to the next elements' value, then your lonely value is in the second part of the array, because the pairing wasn't broken yet.
If those values are not equal, then either your lonely value is in the first half OR you are at it (it is in the middle).
You will need to check couple elements before and after to make sure.
By cutting your array in half with each iteration, you will achieve O(logn) time.

Position of elements in vector

I have several elements in a vector type that are read from cin and then i perfrom some calculations on the vector and it's order of elements gets changed. The problem is that I need to print the positions of the vector elements after the calculations. I don't know how to explain this well that's why i'll give an example:
10 1 100 1000
and 10 is 1st element, 1 is 2nd, 100 is 3rd etc. After the calculations the vector changes in :
100 10 1 1000
so I should print
3 1 2 4
because 100 is the 3rd element of the input, 10 is the 1st etc. etc.
I tried with an array[1000] (because there aren't numbers larger than 1000 in the input), but it won't work because there can be multiple numbers with the same value, like:
10 10 10 100
and the output can be 1 2 3 4 or 2 3 1 4 or 3 1 2 4 etc. but here i need to output 1 2 3 4 because it's the 'smallest'.
I tried with array f[1001] and f[10] = 1, f[100] = 2, f[1] = 3 - if the numbers from the input are 10 100 1. But in case there are multiple numbers with the same value like 10 10 100, then my idea's not working. Please help me in any possible way.
Sounds like you need to store both the value and the initial position. You should be able to do this with an array of structs:
struct UserInput
{
unsigned int initialPosition;
int userInputValue;
};
int main()
{
userInput theUserInput[100];
// increment a counter, starting at 1, and place it in
// "initialPosition" in the struct as user input is read
}
I'll leave the rest up to you... as it is after all homework :) good luck.
Use an associative array if you know what it is.
Use linear search to determine the index if the number of input is limited.
Consider using log10 (or strlen) to transform the 1, 10, 100, 1000, etc. into 0, 1, 2, 3, etc.
From your description of such example:
10(3) 10(2) 10(1) 100(4)
What we have to output is 1 2 3 4, instead of 3 2 1 4.
So I don't think your requirement is just print the initial position directly. You've to make the position sequences as small as possible.
Following is my solution:
Use a direct-mapping hash table to store all the initial positions for specified element. All the initial positions for the same element is sorted. So if you want output the smallest position sequence, you only need to read the initial positions for this specified element from first to last.
The detailed implementation is left to you, since it's a homework.