Generate subsets of elements from vector (NO NESTED LOOP) - c++

Let v = {1,2,3,4,5,6}. I want to generate by using v the following sets:
1 2 3 4 5 6
2 1 3 4 5 6
3 1 2 4 5 6
4 1 2 3 5 6
5 1 2 3 4 6
6 1 2 3 4 5
To achieve this goal I am using the following code, with a nested for loop:
#include<vector>
#include<iostream>
using namespace std;
int main()
{
vector<int> v{1,2,3,4,5,6};
for(unsigned int i = 0; i < v.size(); i++)
{
cout << v[i] <<",";
for(unsigned int j = 0; j < v.size(); j++)
{
if(i != j)
cout << v[j] <<",";
}
cout << endl;
}
return 0;
}
Is there a better approach that can be used in order to generate the previous sets. At least not O(n^2).

For an input list of size n, your output will always consist of n*n numbers. You cannot do better than O(n^2).
However, it seems to me that you merely swap the first and the first element, then the first and the second, then the first and the third etc..
You can hide the inner loop which prints a particular subset with an algorithm though, like in
#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v {1, 2, 3, 4, 5, 6};
for ( auto it = v.begin(); it != v.end(); ++it ) {
std::iter_swap( v.begin(), it );
std::copy( v.begin(), v.end(), std::ostream_iterator<int>( std::cout, "," ) );
std::cout << '\n';
}
}

To understand the lower bounds in your algorithm; Lets look at the transformation between the input and the output.
You are starting with a list of N elements and you end up with a list of [N x (N - 1)] elements.
Ignoring the logic to generate the output, the act of outputting itself is O(N * (N - 1)) => O(n2).
In other words, you are outputting NxN items per the intial input on N. This will be O(n2) by definition.

Here the inner loop is only used to print results:
int main()
{
vector<int> v{1,2,3,4,5,6};
for(unsigned int i = 0; i < v.size(); i++)
{
int t = v[0];
v[0] = v[i];
v[i] = t;
cout << v[0];
for(unsigned int j = 1; j < v.size(); j++)
{
cout << "," << v[j];
}
cout << endl;
}
return 0;
}

Related

Trying to make a simple Array sorter with input numbers

I'm very new to C++ or even coding. I was trying to make a simple array sorter, where the I first input the number of elements that will be in the array and then input the elements. My outcome should be the array sorted in ascending order. I have not thought about the case if elements inserted are same. So I would love to get some help from you folks.
The main error that I'm facing is that only the first unsorted element is sorted while the rest are either interchanged or left the same.
int main(){
int x;
cout<<"Enter no. of elements"<<endl;
cin>>x;
int A[x];
for (int i = 0;i<x;i++){
cin>>A[i];
}
for(int i=0;i<x;i++)
cout<<A[i]<<",";
int count=0;
if(count <= (x-1)){
for (int i=0;i<(x-1);i++){
if(A[i]>A[i+1]){
int a;
a = A[i];
A[i] = A[(i+1)];
A[i+1] = a;
}
else if(A[i]<A[i+1])
count++;
}
}
cout<<"Sorted array:";
for(int i=0;i<x;i++)
cout<<A[i]<<",";
return 0;
}
You declared a variable length array
int x;
cout<<"Enter no. of elements"<<endl;
cin>>x;
int A[x];
because its size is not a compile-time constant.
However variable length arrays are not a standard C++ feature though some compilers have their own language extensions that support variable length arrays,
It is better to use the class template std::vector.
Another problem is that it seems you are trying to use the bubble sort method to sort the array. But this method requires two loops.
Here is a demonstration program that shows how the bubble sort algorithm can be implemented.
#include <iostream>
int main()
{
int a[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
const size_t N = sizeof( a ) / sizeof( *a );
for (const auto &item : a)
{
std::cout << item << ' ';
}
std::cout << '\n';
for (size_t last = N, sorted = N; not ( last < 2 ); last = sorted)
{
for (size_t i = sorted = 1; i < last; i++)
{
if (a[i] < a[i - 1])
{
// std::swap( a[i-1], a[i] );
int tmp = a[i - 1];
a[i - 1] = a[i];
a[i] = tmp;
sorted = i;
}
}
}
for (const auto &item : a)
{
std::cout << item << ' ';
}
std::cout << '\n';
}
The program output is
9 8 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 8 9
Let us try the following method:
find the largest element in the array and move it to the end, by swapping with the last element;
repeat with the array but the last element, and so on.
To find the largest element in A[0..m-1], scan the array and keep an index to the largest so far, let l. This index can be initialized to 0.
// Move the largest to the end
int l= 0;
for (int i= 1; i < m; i++)
{
if (A[i] > A[l]) l= i;
}
// A[l] is the largest in A[0..m-1]
Swap(A[l], A[m-1]);
// A[m-1] is the largest in A[0..m-1]
To sort, repeat with decreasing m. You can stop when the subarray just holds one element:
// Sort
for (int m= n-1; m > 1; m--)
{
// Move the largest to the end
....
}
Writing the Swap operation and assembling the whole code is your task. Also check
correctness of the Move for the limit cases m= 0, 1, 2.
correctness of the Sort for the limit cases n= 1, 2, 3.
how you could instrument the code to verify that the Move does its job.
how you could instrument the code to verify that the Sort does its job.
what happens in case of equal keys.
Your code can be fixed a bit to make it working.
Just replace if (count <= (x - 1)) with while (count < (x - 1)) and also set count = 0; at start of loop, plus replace else if (A[i] < A[i + 1]) with just else. And your code becomes working!
Necessary fixes I did in code below. Also I did formatting (indents and spaces) to make code looks nicer. Rest remains same.
As I see you have a kind of Bubble Sort.
Try it online!
#include <iostream>
using namespace std;
int main() {
int x;
cout << "Enter no. of elements" << endl;
cin >> x;
int A[x];
for (int i = 0; i < x; i++) {
cin >> A[i];
}
for (int i = 0; i < x; i++)
cout << A[i] << ",";
int count = 0;
while (count < (x - 1)) {
count = 0;
for (int i = 0; i < (x - 1); i++) {
if (A[i] > A[i + 1]) {
int a;
a = A[i];
A[i] = A[(i + 1)];
A[i + 1] = a;
} else
count++;
}
}
cout << "Sorted array:";
for (int i = 0; i < x; i++)
cout << A[i] << ",";
return 0;
}
Input:
10
7 3 5 9 1 8 6 0 2 4
Output:
7,3,5,9,1,8,6,0,2,4,Sorted array:0,1,2,3,4,5,6,7,8,9,
If you are taking the size of array as input from user you have to create your array dynamically in c++ like
int *array=new int(x)
and after taking the inputs of the elements just run a nested loop from 0 to size and
the inner loop from 0 to size-1 and check if(A[i]>A[i+1]) if true then swap the values else continue

Permutations of a specific set of numbers from n to m

#include <iostream>
using namespace std;
int n, m, x[20], p[20];
void display(){
for(int i = 1 ; i <= n; ++i)
cout << x[i] << ' ';
cout << "\n";
}
void bkt(int k){
for(int i = n; i <= m; ++i)
if(!p[i]){
x[k] = i;
p[i] = 1;
if(k<n)
bkt(k+1);
else
display();
p[i] = 0;
}
}
int main()
{ cin >> n >> m;
bkt(1);
return 0;
}
This code should do the permutations from n to m, but it doesn't work and I don't know what I did wrong. I tried a set of examples like 4 and 6, and it should show
4 5 6
4 6 5
5 4 6
5 6 4
6 4 5
6 5 4
but it doesn't show anything in the console, just returns 0.
There's a number of issues with the code, but you can solve the problem in the following way:
cin >> n >> m; // get range
Then create a vector of the appropriate size
std::vector<int> v(m - n + 1);
and then fill it with the needed values
std::iota(std::begin(v), std::end(v), n);
and then generate all permutations in a loop
do {
// ...
} while(std::next_permuation(std::begin(v), std::end(v));

Binary Search with Duplicates

I am doing this particular exercise where I have to implement the Binary Search algorithm which returns the index of the first occurence of an element in a sorted array, if it contains duplicates. Since I am primarily working on my algorithmic skills in C++, I am only trying to do it in C++. Here is my code:
#include <iostream>
#include <cassert>
#include <vector>
using std::vector;
int binary_search(const vector<int> &a, int x, int n) {
int left = 0, right = n-1;
while(left<= right){
int mid = left + (right-left)/2;
if(x== a[mid]){
return mid;
}else if(a[mid]>x){
right = mid-1;
}else{
left = mid+1;
}
}
return -1;
}
int first_occurence(const vector<int>&a, int x, int n) {
int out = binary_search(a, x, n);
if(out !=-1){
for(int i = out;i>0&& a[i]==x;--i ){
out = i;
}
}
return out;
}
int main() {
int n;
std::cin >> n;
vector<int> a(n);
for (size_t i = 0; i < a.size(); i++) {
std::cin >> a[i];
}
int m;
std::cin >> m;
vector<int> b(m);
for (int i = 0; i < m; ++i) {
std::cin >> b[i];
}
for (int i = 0; i < m; ++i) {
std::cout << first_occurence(a, b[i], n) << ' ';
}
}
The first input to the program tells how many items the array should contain, the second is the enumeration of these elements, third line tells how many keys to search for and the final line are the individual keys. The output is the indices for the key or -1 when no such key is found.
My strategy is to use a function to find the index of a key. If it is found, then in case of duplicates, the first occurrence has to have a lower index. That is what the first_occurence() method does; keep looping back till the first occurence is found.
For the following input:
10
1 5 4 4 7 7 7 3 2 2
5
4 7 2 0 6
The output is:
-1 4 -1 -1 -1
Which is only correct for the key 7. I have been trying to debug this for quite some time but I can not figure out the problem.
returns the index of the first occurence of an element in a sorted array,
Your binary search algorithm requires that the data is sorted before you call it.
Example:
#include <algorithm>
#include <sstream>
int main() {
std::istringstream in(R"aw(10
1 5 4 4 7 7 7 3 2 2
5
4 7 2 0 6
)aw");
int n;
in >> n;
vector<int> a(n);
for (auto& v : a) {
in >> v;
}
std::sort(a.begin(), a.end()); // <- add this
// display the sorted result:
for (auto v : a) std::cout << v << ' ';
std::cout << '\n';
int m;
in >> m;
vector<int> b(m);
for (auto& v : b) {
in >> v;
}
for (auto v : b) {
std::cout << v << ' ' << first_occurence(a, v, n) << '\n';
}
}

Filter out duplicate values in array in C++

I have a row of ten numbers for example:
5 5 6 7 5 9 4 2 2 7
Now I want a program that finds all duplicates and gives them out in the console like 3 times 5, 2 times 2, 2 times 7.
While I did code an algorithm that finds duplicates in a row of numbers I can't give them out in the console as described. My program will output:
3 times 5
2 times 5
2 times 7
2 times 2
How can I solve this problem?
#include <iostream>
using namespace std;
int main()
{
int arr[10];
int i,j;
int z = 1;
for(i = 0; i < 10; i++) {
cin >> arr[i];
}
for(i = 0; i < 10; i++){
for(j = i+1; j < 10; j++){
if(arr[i] == arr[j]){
z++;
}
}
if(z >= 2){
cout << z << " times " << arr[i] << endl;
z = 1;
}
}
return 0;
}
You can use the STL here (C++11):
int arr[10];
std::map<int, int> counters;
for (auto item : arr)
{
cin >> item;
++counters[item];
}
std::for_each(counters.begin(), counters.end(), [](const std::pair<int,int>& item)
{
if(item.second > 1) std::cout << item.second << " times " << item.first << std::endl;
});
You need to check that arr[i] is not already found before, like this for example:
if(z >= 2) {
int found_before = 0;
for(j = 0; j < i; ++j)
if(arr[i] == arr[j])
found_before = 1;
if(!found_before)
cout << z << " times " << arr[i] << endl;
z = 1;
}
which will print:
3 times 5
2 times 7
2 times 2
That way you don't print 5 again.
With your code it would print that it found 5 three times (for the first 5 in your array), and then when it would move to he second 5 in your array, it would forgot about the first 5 in your array, and report that it found 5 twice (itself and the 5th number of the array).
Why not use STL?
std::map<int, int> counter;
for (i = 0; i < 10; i++)
counter[arr[i]] ++;
for (i = 0; i < 10; i++) {
if (counter.count(arr[i]) > 0){
std::cout << counter[arr[i]] << " times "<< arr[i] << std::endl;
counter.erase(arr[i]);
}
}
std::map is a convenient tool for this job. You can easily count up occurrences of a specific number. After counting, you can print the count of each array element. With counter.erase, it's guaranteed that you won't print the same element for multiple times.
Why keeping your algorithm idea, I suggest to create sub method:
std::size_t count(const int* arr, std::size_t start, std::size_t end, int value)
{
std::size_t res = 0;
for (std::size_t i = start; i != end; ++i) {
if (arr[i] == value) {
++res;
}
}
return res;
}
then your fixed algorithm would be:
for (std::size_t i = 0; i != 10; ++i) {
if (count(arr, 0, i, arr[i]) != 0) {
continue; // Already visited
}
auto total = count(arr, i, 10, arr[i]);
if(total >= 2){
std::cout << z << " times " << arr[i] << std::endl;
}
}
An easy way is to make another array for it, especially if the numbers are not that big.
Lets say you have initialized your array like so: int nums[10] = { 5, 5, 6, 7, 5, 9, 4, 2, 2, 7 }
int result[max(nums)]; //Fill with zeroes, max(nums) is the highest number in the array
for(int i = 0; i < 10; i++) {
result[nums[i]]++;
}
for(int i = 0; i < max(nums); i++) {
if (result[i] > 1) cout << result[i];
}
Mind you this isn't optimized for memory. For larger number contents you might want to consider hashmaps.
If you don't need performance but rather compact code, then std::multiset with std::upper_bound is an alternative:
#include<set>
#include<iostream>
#include<algorithm>
int main(int a, char** b)
{
int array[] = {5, 5, 6, 7, 5, 9, 4, 2, 2, 7};
std::multiset<int> a(std::begin(array), std::end(array));
for(auto it = a.begin(); it != a.end(); it = std::upper_bound(a.begin(), a.end(), *it))
{
if(a.count(*it) > 1)
std::cout << *it << " times " << a.count(*it) << std::endl;
}
return 0;
}

Recurssion issue in generating permutation in c++

i have two n in c++ and i want to generate permutation of the numbers in those vectors in such a way for each permutation of the first vector i have all the permutations of all the other vectors.
Say i have two vectors with number 2 9 and the other vector will be 5 6. then my result should be...
2 9 5 6
2 9 6 5
9 2 5 6
9 2 6 5
means that the total number of permutations i have got will be
total perms = (# of permutations of the 1st vector times number of permutations of the second vector times number of permutations of the third vector and so on).
I have written the below code and i am struck in to recursion stack... It is actually printing 6 times for the case of 2 vectors each have the size of 2 each.
mySwap(int *x, int *y){
int temp;
temp = *x;
*x = *y;
*y = temp;
}
swaps the two int elements
void myPerm(vector<vector<int>> myItems, int start, int end,int vectorIndex){
int j;
if(start == end){
for(int k = vectorIndex +1; k < items.size(); ++k){
myPerm(myItems, 0, myItems[k].size()-1,k);
}
for(int z = 0; z < myItems.size(); ++z){
for(int l = 0; l < myItems[z].size(); ++z){
std::cout << myItems[z][l];
}
}
}
else{
for(int j = start; j <= end; j++){
mySwap(&myItems[vectorIndex][start],&myItems[vectorIndex][j]);
myPerm(myItems,start + 1, end,vectorIndex);
mySwap(&myItems[vectorIndex][start],&myItems[vectorIndex][j]);
}
}
}
above code that generates permutations recursively...
int main(){
vector<vector<int>> myItems;
int k = 0;
for(int i =0; i < 2; ++i){
myItems.push_back(vector<int>);
}
for(int j =0; j < 2; ++j){
myItems[i].push_back(k++);
}
myPerm(items,0,items[0].size()-1,0);
return;
}
my main function.
Please give me some hint or solve this this for the generic case as the above code prints the permutations for the six which originally should be 4 times.
Thanks
Considering this is not a homework you can simply use stl algorithm next_permutation instead of what you have.
This is the code for your sample input.
int main()
{
std::vector<int> v1 , v2 , v3;
v1.push_back( 2 );
v1.push_back( 9 );
v2.push_back( 5 );
v2.push_back( 6 );
std::sort( v1.begin() , v1.end() );
std::sort( v2.begin() , v2.end() );
do
{
v3 = v2;
do
{
std::for_each( v1.begin() , v1.end() , [](int x) { std::cout << x << " ";} );
std::for_each( v3.begin() , v3.end() , [](int x) { std::cout << x << " ";} );
std::cout << std::endl;
}
while ( std::next_permutation(v3.begin() , v3.end() ) );
}
while ( std::next_permutation(v1.begin() , v1.end() ) );
return 0;
}
This does it for two vectors... I am sure you can generalize it further.
Thanks for all the ideas specially for the STL function next_permutation. I don't know it earlier.
I was able to write the code i want it correctly...
Here is my code
void perm(std::vector<std::vector <int>> &items, int level){
if(level == 0){
for (int i = 0; i < items.size(); i++)
for (int j = 0; j < items[i].size(); j++)
std::cout << items[i][j];
std::cout<<std::endl;
while(next_permutation(items[level].begin(), items[level].end())){
for (int i = 0; i < items.size(); i++)
for (int j = 0; j < items[i].size(); j++)
std::cout << items[i][j];
std::cout<<std::endl;
}
}
else{
if(level > 0)
perm(items,level-1);
while(next_permutation(items[level].begin(), items[level].end())){
if(level > 0)
perm(items,level-1);
}
}
}
For this problem recursion could be omitted entirely by using next_permutation. Here's some untested code that is arguably more elegant:
void myPerm(std::vector<std::vector<int>>& myItems)
{
for (int i = 0; i < myItems.size(); i++)
std::sort(myItems[i].begin(), myItems[i].end());
int level;
do
{
printAll(myItems);
level = myItems.size() - 1;
while (!next_permutation(myItems[level].begin(), myItems[level].end()))
level--;
}
while (level >= 0);
}
Nice thing about next_permutation is that it returns false as it "wraps around" given set, and so the set is sorted and ready for the next round of permutations.