Note:After reading templatetypedef's post, it seems like I'm trying to compute the cartesian product of a set with itself a certain amount of times.
I am not completely sure what the problem I'm trying to solve is called, but it seems pretty close to permutation with replacement to me.
So basically, my problem is this.
Given an array, for example:
{1, 2, 3}
and a size, say 2.
I need to output:
{1,1},{1,2},{1,3},{2,1},{2,2},...
If size was 3, then it would be
{1,1,1},{1,1,2},{1,1,3},{1,2,1},{1,2,2},{1,2,3},{1,3,1}...
How would I do this?
For the purposes of my problem, I have an input size of 15 numbers, so I guess I could create 15 for loops, but that seems like a hack to me.
Thanks.
Edit: I edited my problem after becoming not sure what I was asking and what I actually needed were essentially the same problem.
After reading templatetypedef's post, it seems like i'm trying to compute the cartesian product of a set with itself size amount of times.
You are trying to compute the Cartesian product of the set {1, 2, 3} with itself fifteen times. You can do this very elegantly with a simple recursive algorithm:
To compute the Cartesian product of a set with itself just once, return a set containing singleton lists of each of the elements of the original set.
To compute the Cartesian product of a set with itself n > 1 times:
Recursively compute the Cartesian product of the set with itself n - 1 times.
For each element x of the input list:
For each sequence S produced so far:
Add the sequence S + x to the output set.
Return the output set.
In (somewhat inefficient) C++ code:
vector<vector<int>> CartesianPower(const vector<int>& input, unsigned k) {
if (k == 1) {
vector<vector<int>> result;
for (int value: input) {
result.push_back( {value} );
}
return result;
} else {
vector<vector<int>> result;
vector<vector<int>> smallerPower = CartesianProduct(input, k - 1);
for (int elem: input) {
for (vector<int> sublist: smallerPower) {
sublist.push_back(elem);
result.push_back(sublist);
}
}
return result;
}
}
Hope this helps!
Related
I've had a long break from coding, so I've been doing some coding problems.
In this one, I've passed the tests but the issue lies in my inefficient code. Here's the task:
Given a vector 'arr' and a number n, create a new vector that contains each number of arr at most n times without reordering. For example if n = 2, and the input is [1,2,3,1,2,1,2,3], you take [1,2,3,1,2], drop the next [1,2] since this would lead to 1 and 2 being in the result 3 times, and then take 3, which leads to [1,2,3,1,2,3].
e.g.
deleteNth ([1,1,1,1],2) // return [1,1]
deleteNth ([20,37,20,21],1) // return [20,37,21]
and here's my code:
std::vector<int> deleteNth(std::vector<int> arr, int n)
{
std::vector<int>::iterator it=(arr.begin());
for(;it!=arr.end();it++){
int temp=*it;
int counter=0;
std::vector<int>::iterator it2=it;
for(;it!=arr.end();it++){
if(*it==temp){
counter++;
if(counter>n){
arr.erase(it);
}
}
it=it2;
}
}
return arr;
}
Sorry for the cringe caused, and any help will be most appreciated!
Is vector a list?
You should do it in one pass, using an unordered_map<int,int> to count occurrences of different values; if it's below the threshold - copy it to a new list, if at the threshold - ignore and move to the next element.
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.
I have a vector< vector <int> > matrix of size n and I want to get the minimum value for each i and it indexs [i][j] and put it on a vector but I don't want to get any indexs repeated.
I've found a theoretical way but I cannot write it in code.
Make 2 vectors U←{1,...,n}, L←{1,...,n}
Repeat n times
Be (u,l)∈U×L from matrix[u,l] ≤ matrix[i,j], ∀i∈U, ∀j∈L
S[u] ← l
Do U←U-{u} y L←L-{l}
You can code this algorithm directly
typedef vector<vector<int>> Matrix;
typedef pair<size_t, size_t> Index;
typedef vector<Index> IndexList;
IndexList MinimalSequence(const Matrix& matrix) {
IndexList result;
set<size_t> U, L;
for (size_t i = 0; i < matrix.size(); ++i) { // consider square
U.insert(i);
L.insert(i);
}
while (U.size()) { // same as L.size()
int min = numeric_limits<int>::max();
Index minIndex;
for (auto u: U)
for (auto l: L)
if (matrix[u][l] < min) {
minIndex = make_pair(u, l);
min = matrix[u][l];
}
U.erase(minIndex.first);
L.erase(minIndex.second);
result.push_back(minIndex);
}
return result;
}
also your question is not clear in this way: do you want to start from the overall smallest element of the matrix (as your formula said) and then move to the next smallest?
or do you want to move through the columns from left to right? I implemented it according to formulas.
Note that set of non-negative integers in your formula is set<size_t> on which insert() and erase() are available. For all is while-loop
I would also suggest to try alternative algorithm - sort a list of matrix indices by there corresponding values and then iterate over it removing indices you dont want anymore.
edit: code actually differs from algorithm in few ways to be precise. That seemed more practical.
process is repeated until set of indices is exhausted - that is equal to n
return structure is list of 2d indices and encodes more information than array
You already have accepted an answer, but aren't you facing the Assignment problem that can be solved using the Hugarian algorithm, and maybe even more efficient algorithms that exists and are already implemented?
I have a very large n*m matrix S. I want to efficiently determine whether there exists a submatrix F inside of S. The large matrix S can have a size as big as 500*500.
To clarify, consider the following:
S = 1 2 3
4 5 6
7 8 9
F1 = 2 3
5 6
F2 = 1 2
4 6
In such a case:
F1 is inside S
F2 is not inside S
Each element in the matrix is a 32-bit integer. I can only think of using a brute-force approach to find whether F is a submatrix of S. I googled to find an effective algorithm, but I can't find anything.
Is there some algorithm or principle to do it faster? (Or possibly some method to optimize the brute force approach?)
PS the statistics data
A total of 8 S
On average, each S will be matched against about 44 F.
The probability of success match (i.e. F appears in a S) is
19%.
It involves preprocessing the matrix. This will be heavy on memory, but it should be better in terms of computation time.
Check if the size of the sub-matrix is less than that of the matrix before you do the check.
While constructing the matrix, build a construct that maps a value in the matrix to an array of (x,y) positions in the matrix. This will allow you to check for the existence of a sub-matrix where candidates could exist. You would use the value at (0,0) in the sub-matrix and get the possible positions of this value in the larger matrix. If the list of positions is empty, you have no candidates, and so, the sub-matrix does not exist. There's a start (More experienced people might consider this a naive approach however).
Modified Code of deepu-benson
int Ma[][5]= {
{0, 0, 1, 0, 0},
{0, 0, 1, 0, 0},
{0, 1, 0, 0, 0},
{0, 1, 0, 0, 0},
{1, 1, 1, 1, 0}
};
int Su[][3]= {
{1, 0, 0},
{1, 0, 0},
};
int S = 5;// Size of main matrix row
int T = 5;//Size of main matrix column
int M = 2; // size of desire matrix row
int N = 3; // Size of desire matrix column
int flag, i,j,p,q;
for(i=0; i<=(S-M); i++)
{
for(j=0; j<=(T-N); j++)
{
flag=0;
for(p=0; p<M; p++)
{
for(int q=0; q<N; q++)
{
if(Ma[i+p][j+q] != Su[p][q])
{
flag=1;
break;
}
}
}
if(flag==0)
{
printf("Match Found in the Main Matrix at starting location %d, %d",(i+1) ,(j+1));
break;
}
}
if(flag==0)
{
printf("Match Found in the Main Matrix at starting location %d, %d",(i+1) ,(j+1));
break;
}
}
If you want to query multiple times for a same big matrix and same size submatrices. There are many solutions to preprocess the big matrix.
A similar ( or even same ) problem is here.
Fastest way to Find a m x n submatrix in M X N matrix
Since you only want to know whether a given matrix is inside another big matrix. If you know how to use Matlab code from C++, you may directly use ismember from Matlab. Another way may be try to figure out how ismember works in Matlab, then implement the same thing in C++.
See Find location of submatrix
Since you have tagged the question as C++ also, I am providing this code. This is a brute force technique and definitely not the ideal solution for this problem. For an S X T Main Matrix and a M X N Sub Matrix, the time complexity of the algorithm is O(STMN).
cout<<"\nEnter the order of the Main Matrix";
cin>>S>>T;
cout<<"\nEnter the order of the Sub Matrix";
cin>>M>>N;
// Read the Main Matrix into MAT[S][T]
// Read the Sub Matrix into SUB[M][N]
for(i=0; i<(S-M); i++)
{
for(j=0; j<(T-N); j++)
{
flag=0;
for(p=0; p<M; p++)
{
for(q=0; q<N; q++)
{
if(MAT[i+p][j+q] != SUB[p][q])
{
flag=1;
break;
}
}
if(flag==0)
{
cout<<"Match Found in the Main Matrix at starting location "<<(i+1) <<"X"<<(j+1);
break;
}
}
if(flag==0)
{
break;
}
}
if(flag==0)
{
break;
}
}
Much of the answer depends on what you're doing repetitively. Are you testing a bunch of huge matrices for the same submatrix? Are you testing one huge matrix looking for a bunch of different submatrices?
Do any of the matrices have repetitive patterns, or are they nice and random, or can you make no assumptions about the data?
Also, does the submatrix have to be contiguous? Does S contain
F3 = 1 3
7 9
If the data in matrix isn't randomly distributed, it would be helpful to run some statistical analysis on it. Then you could find the sub matrix by comparing its element ranged by their inverse probability. It could be faster, then a plain bruteforce.
Say, you have the matrix of some normally distributed integers with the Gaussian center in 0. And you want to find submatrix say:
1 3 -12
-3 43 -1
198 2 2
You have to start searching for 198, then checking upper right element to be 43 then its upper right for -12, then any 3 or -3 will do; and so on. This would greatly reduce the number of comparisons comparing to the most brutal solution.
My original answer is below the break, thinking about it there are several optimisations, these optimisations refer to the steps of the original answer.
For Step B) do not search the entirety of S: you can discount all columns and rows which would not allow F to fit. (in the below example, only search the upper left 2x2 matrix). In cases where F is a significant proportion of S this would save considerable time.
If the range of values within S is quite low then creating a lookup table would greatly reduce the time required for step B).
Working with these 2 matrices
find inside
A) Select one value from the smaller matrix:
B) locate it within the larger
C) Check the adjacent cells to see if they match
-
It's possible to do in O(N*M*(logN+logM)).
Equality can be expressed as sum of squared differences is 0:
sum[i,j](square(S(n+i,m+j)-F(i,j)))=0
sum[i,j]square(S(n+i,m+j))+sum[i,j](square(F(i,j))-2*sum[i,j](S(n+i,m+j)*F(i,j))=0
First part can be calculated for all (n,m) in O(N*M) similarly to running average.
Second part is calculated as usual in O(sizeof(F)) which is less than O(N*M).
Third part is the most interesting. It's convolution which can be calculated in O(N*M*(logN+logM)) using Fast Fourier Transform: http://en.wikipedia.org/wiki/Convolution#Fast_convolution_algorithms
For example:
array[] = {3, 9, 10, **12**,1,4,**7**,2,**6**,***5***}
First, I need maximum value=12 then I need maximum value among the rest of array (1,4,7,2,6,5), so value=7, then maxiumum value of the rest of array 6, then 5, After that, i will need series of this values. This gives back (12,7,6,5).
How to get these numbers?
I have tried the following code, but it seems to infinite
I think I'll need a recursive function but how can I do this?
max=0; max2=0;...
for(i=0; i<array_length; i++){
if (matrix[i] >= max)
max=matrix[i];
else {
for (j=i; j<array_length; j++){
if (matrix[j] >= max2)
max2=matrix[j];
else{
...
...for if else for if else
...??
}
}
}
}
This is how you would do that in C++11 by using the std::max_element() standard algorithm:
#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
int arr[] = {3,5,4,12,1,4,7,2,6,5};
auto m = std::begin(arr);
while (m != std::end(arr))
{
m = std::max_element(m, std::end(arr));
std::cout << *(m++) << std::endl;
}
}
Here is a live example.
This is an excellent spot to use the Cartesian tree data structure. A Cartesian tree is a data structure built out of a sequence of elements with these properties:
The Cartesian tree is a binary tree.
The Cartesian tree obeys the heap property: every node in the Cartesian tree is greater than or equal to all its descendants.
An inorder traversal of a Cartesian tree gives back the original sequence.
For example, given the sequence
4 1 0 3 2
The Cartesian tree would be
4
\
3
/ \
1 2
\
0
Notice that this obeys the heap property, and an inorder walk gives back the sequence 4 1 0 3 2, which was the original sequence.
But here's the key observation: notice that if you start at the root of this Cartesian tree and start walking down to the right, you get back the number 4 (the biggest element in the sequence), then 3 (the biggest element in what comes after that 4), and the number 2 (the biggest element in what comes after the 3). More generally, if you create a Cartesian tree for the sequence, then start at the root and keep walking to the right, you'll get back the sequence of elements that you're looking for!
The beauty of this is that a Cartesian tree can be constructed in time Θ(n), which is very fast, and walking down the spine takes time only O(n). Therefore, the total amount of time required to find the sequence you're looking for is Θ(n). Note that the approach of "find the largest element, then find the largest element in the subarray that appears after that, etc." would run in time Θ(n2) in the worst case if the input was sorted in descending order, so this solution is much faster.
Hope this helps!
If you can modify the array, your code will become simpler. Whenever you find a max, output that and change its value inside the original array to some small number, for example -MAXINT. Once you have output the number of elements in the array, you can stop your iterations.
std::vector<int> output;
for (auto i : array)
{
auto pos = std::find_if(output.rbegin(), output.rend(), [i](int n) { return n > i; }).base();
output.erase(pos,output.end());
output.push_back(i);
}
Hopefully you can understand that code. I'm much better at writing algorithms in C++ than describing them in English, but here's an attempt.
Before we start scanning, output is empty. This is the correct state for an empty input.
We start by looking at the first unlooked at element I of the input array. We scan backwards through the output until we find an element G which is greater than I. Then we erase starting at the position after G. If we find none, that means that I is the greatest element so far of the elements we've searched, so we erase the entire output. Otherwise, we erase every element after G, because I is the greatest starting from G through what we've searched so far. Then we append I to output. Repeat until the input array is exhausted.