next_permutation not by reference? - c++

I do not understand why inside the loop, the position of the values are changed. But outside do, while loop, all the values return to the original positions. Thus i need the //here code. I also tried a pointer array, but it showed the same behavior. Why so?
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int a[] = {0, 1, 2};
do
{
for (int i = 0; i < 3; i++)
cout << a[i];
cout << endl;
} while (next_permutation(a, a + 3));
cout << endl;
// here
a[0] = 2;
a[1] = 1;
a[2] = 0;
do
{
for (int i = 0; i < 3; i++)
cout << a[i];
cout << endl;
} while (prev_permutation(a, a + 3));
return 0;
}

Thats how next_permutation is defined. The last permutation (the one that returns false) is the one that puts the elements in sorted order.
I suppose there is another misunderstanding. Here:
do
{
print_permutation();
} while (next_permutation(a, a + 3));
The last permutation you print inside the loop is that one before the one that makes next_permutation return false. Hence in the last iteration you are not printing the same permutation as outside of the loop. It is similar to:
bool increment(int& i) {
++i;
return i<10;
}
int i = 0;
do {
std::cout << i;
} while( increment(i) );
std::cout << i;
The last value printed inside the loop is 9, but the value of i after the loop is 10.

Every time it is called, std::next_permutation generates an permutation P' of the given container a where the current permutation is, say, P. As long as the permutation P' it generates is greater than P, it returns true. However, in the case for P being the greatest (i.e., see below for an explanation of greatness) permutation of the elements in the given container a, for instance P=[2, 1, 0] the next permutation P' it generates is [0, 1, 2], which is not greater than P. In that case, it returns false and the loop terminates. But, due to the side effect of the process, once the function returns, the elements in the container are already placed in that smallest permutation possible. That is why you see those elements in their smallest permutation possible after the loop terminates.
The word greater may be a little confusing. Basically std::next_permutation uses whatever comparison operators are available to compare individual elements and ends up iterating over them in a way that lexicographically increases with each following permutation. So, for a vector of [0, 1, 2], it would iterate the following permutations in that order:
0, 1, 2
0, 2, 1
1, 0, 2
1, 2, 0
2, 0, 1
2, 1, 0
That is why, the function recognizes that [0,1,2] would not be a greater permutation after [2,1,0] and returns false.

Related

Duplicates in Array

Given an integer array nums sorted in non-decreasing order, remove some duplicates in-place such that each unique element appears at most twice. The relative order of the elements should be kept the same.
Since it is impossible to change the length of the array in some languages, you must instead have the result be placed in the first part of the array nums. More formally, if there are k elements after removing the duplicates, then the first k elements of nums should hold the final result. It does not matter what you leave beyond the first k elements.
Return k after placing the final result in the first k slots of nums.
What is wrong with my code ??
map<int,int> m;
for(int i = 0 ; i < nums.size() ; i++){
m[nums[i]]++;
if(m[nums[i]] > 2)nums.erase(nums.begin() + i);
}
return nums.size();
From the given text, we can derive the following requirements
Given an integer array nums
sorted in non-decreasing order,
remove some duplicates in-place such that each unique element appears at most twice.
The relative order of the elements should be kept the same.
Since it is impossible to change the length of the array in some languages, you must instead have the result be placed in the first part of the array nums.
More formally, if there are k elements after removing the duplicates, then the first k elements of nums should hold the final result.
It does not matter what you leave beyond the first k elements
Return k after placing the final result in the first k slots of nums.
So, after elicitating the requirements, we know that we have a fixed size array, presumably (because of the simplicity of the task) a C-Style array or a C++ std::array. Because of the shown source code, we assume a std::array.
It will be sorted in increasing order. Their shall be an in-place removal of elements. So, no additional variables. The rest of the requirements already shows the solution.
--> If we find duplicates (more than 2) we will shift the rest of the values one to the left and overwrite one of the duplicates. Then the logical number of elements in the array will be one less. So, the loop must run one step less.
This ends up in a rather simple program:
#include <iostream>
#include <array>
// Array with some test values
constexpr int ArraySize = 25;
std::array<int, ArraySize> nums{ 1,2,2,2,3,3,3,4,4,4,4,4,6,5,5,5,5,5,6,6,6,6,6,6,9,9 };
int main() {
// Currentlogical end of the data in the array. In the beginning, last value in the array
size_t endIndex = nums.size();
// Check allelments from left to tright
for (size_t index = 0; index < endIndex;) {
// Check, if 3 elements are same
if ((index < (endIndex -2)) and nums[index] == nums[index + 1] and nums[index + 1] == nums[index + 2]) {
// Yes, found 3 same elements. We willdelete one, so the endIndex needs to be decremented
--endIndex;
// Now hsift all array elements one to the left
for (size_t shiftIndex = index + 2; shiftIndex < endIndex; ++shiftIndex)
nums[shiftIndex] = nums[shiftIndex + 1];
}
else ++index;
}
// SHow result
std::cout << endIndex << '\n';
}
I can offer the solution of your problem.
#include <iostream>
#include <vector>
#include <set>
using namespace std;
void showContentSet(set<int>& input)
{
for(auto iterator=input.begin(); iterator!=input.end(); ++iterator)
{
cout<<*iterator<<", ";
}
return;
}
void showContentVector(vector<int>& input)
{
for(int i=0; i<input.size(); ++i)
{
cout<<input[i]<<", ";
}
return;
}
void solve()
{
vector<int> numbers={1, 2, 1, 3, 4, 5, 7, 5, 8, 5, 9, 5};
set<int> indicesToDelete;
for(int i=0; i<numbers.size(); ++i)
{
int count=0;
for(int j=0; j<numbers.size(); ++j)
{
if(numbers[i]==numbers[j])
{
++count;
if(count>2)
{
indicesToDelete.insert(j);
}
}
}
}
cout<<"indicesToDelete <- ";
showContentSet(indicesToDelete);
int newOrder=0;
cout<<endl<<"Before, numbers <- ";
showContentVector(numbers);
for(auto iterator=indicesToDelete.begin(); iterator!=indicesToDelete.end(); ++iterator)
{
numbers.erase(numbers.begin()+(*iterator-newOrder));
++newOrder;
}
cout<<endl<<"After, numbers <- ";
showContentVector(numbers);
cout<<endl;
return;
}
int main()
{
solve();
return 0;
}
Here is the result:
indicesToDelete <- 9, 11,
Before, numbers <- 1, 2, 1, 3, 4, 5, 7, 5, 8, 5, 9, 5,
After, numbers <- 1, 2, 1, 3, 4, 5, 7, 5, 8, 9,
I suggest using a frequency array.
frequency array works, That you count how many duplicates of each number while inputting, It's stored usually in an array called freq, Also can be stored in a map<int, int> or unordered_map<int, int>.
And because of input is in non-decreasing order, outputting this solution will be easy.
Note: this solution won't work if input numbers is bigger than 10^5
Solution:
#include <iostream>
const int N = 1e5 + 1; // Maximum size of input array
int n;
int nums[N], freq[N];
int main()
{
// Input
std::cin >> n;
for (int i = 0; i < n; i++)
{
std::cin >> nums[i];
freq[nums[i]]++;
}
// Outputting numbers, Using frequency array of it
for (int i = 0; i < N; i++)
{
if (freq[i] >= 1)
std::cout << i << ' ';
if (freq[i] >= 2)
std::cout << i << ' ';
}
return 0;
}
This is basically a conditional copy operation. Copy the entire range, but skip elements that have been copied twice already.
The following code makes exactly one pass over the entire range. More importantly it avoids erase operations, which will repeatedly shift all elements to the left.
vector<int> nums; // must be sorted already
if (nums.size()<=1)
return; // already done
// basically you copy all elements inside the vector
// but copy them only if the requirement has been met.
// `in` is the source iterator. It increments every time.
// `out` is the destination iterator. It increments only
// after a copy.
auto in=nums.begin();
auto out=nums.begin();
// current is the current 'int' value
int current=*in;
// `count` counts the repeat count of the current value
int count=0;
while (in!=nums.end()) {
if (*in==current) {
// The current value repeats itself, so increment
// the count value
++count;
} else {
// No, this is a new value.
// initialise current and count
current=*in;
count=1;
}
if (count<=2) {
// only if at most two elements of the same value
// copy the current value to `out`
*out=current;
++out;
}
// try next element
++in;
}
// out points to the last valid element + 1

How to consider only first two elements from *pointer

From the below code you can see that the vector array has the same number twice or more than. What I want to do is to find the first two same number's position from the pointer *ptr
#include<iostream>
#include<iterator> // for iterators
#include<vector> // for vectors
using namespace std;
int main()
{
vector<int> ar = { 1,8,2, 2, 2, 5,7,7,7,7,8 };
// Declaring iterator to a vector
vector<int>::iterator ptr;
// Displaying vector elements using begin() and end()
cout << "The vector elements are : ";
for (ptr = ar.begin(); ptr < ar.end(); ptr++)
cout << *ptr << " ";
return 0;
}
Let's assume I want to print out the first two position and elements of 7 by dereferencing the pointer *ptr. Should I use an if a condition like
int *array = ptr.data();
for( int i =0; i < ar.size(); i++) {
if( array[i] - array[i+1]+ ==0)
cout<<array[i]<<endl;
}
But how would I guarantee that it is not looking for the only first two same elements from *ptr?
UPDATE
Clearing the question:
The reason I always want to know the first and second position of the same element from the dereferencing the pointer is that later I will do some study, and in that study, I will be given some time associated with the first and second position of the same number. The problem, I wanted to ignore the same elements which are still repetitive after the second time is because I want to ignore these element positions in my calculations.
For example, if you print out the code you would find the element: **The vector elements are 1 8 2 2 2 5 7 7 7 7 8 **. In this case, the first two positions of the element 2, is [2], and [3], therefore I would like to ignore the position [4]. Another thing to mention, that I don't care if the value or consequent or not[I mean for example 828, or 888, I would consider both]. For example, the number 8 is in location array[1], and in the [10]. I would also consider this.
Create a map where each value is stored as key, mapped to a list of indices:
std::unordered_map<int, std::vector<size_t>> indexMap;
Loop over your initial values and fill the map:
for (size_t index = 0; index < ar.size(); index++)
{
indexMap[ar[index]].push_back(index);
}
Now you can loop over your map and work with every value that has 2 or more indices and only use the first 2 indices for whatever you want to do:
for (auto const& [value, indices] : indexMap)
{
if (indices.size() < 2)
continue;
size_t firstIndex = indices[0];
size_t secondIndex = indices[1];
// do whatever
}
(If you don't use C++17 or up, use for (auto const& pair : indexMap), where pair.first is value and pair.second is indices.)
You could use map or unordered_map to register indexes of each value.
Here's a simple demo of the concept:
#include<iostream>
#include<vector>
#include<map>
using namespace std;
int main() {
vector<int> ar{ 1, 8, 2, 2, 2, 5, 7, 7, 7, 7, 8 };
map<int, vector<size_t> > occurrences{ };
for (size_t i = 0; i < ar.size(); ++i) {
occurrences[ar[i]].push_back(i);
}
for (const auto& occurrence:occurrences) {
cout << occurrence.first << ": ";
for (auto index: occurrence.second) {
cout << index << " ";
}
cout << endl;
}
return 0;
}
Output:
1: 0
2: 2 3 4
5: 5
7: 6 7 8 9
8: 1 10

Keeping only N smallest elements with STL (with duplicates)

The MVCE below attempts to output only the 5 smallest elements in ascending order from a large incoming input stream of random elements (which contains duplicates).
int main(int argc, char *argv[])
{
std::set<int> s; //EDIT: std::multiset is an answer to Q1
for (int i : {6, 6, 5, 8, 3, 4, 0, 2, 8, 9, 7, 2}) //Billions of elements in reality
{
if ( (s.size() < 5) || (i <= *(--s.end())) ) //Insert only if not full or when the element to be inserted is smaller than the greatest one already in the set
{
if (s.size() >= 5) //Limit the number of smallest elements that are kept. In reality ~8000
s.erase(*(--s.end())); //Erase the largest element
s.insert(i);
}
}
for (int d: s)
std::cout << d << " "; //print the 5 smallest elements in ascending order
std::cout << '\n';
return 0;
}
The output is:
0 2 3 4
The output should be:
0 2 2 3 4
Q1: What must be changed to allow duplicates ?
Q2: How can this code be made faster while not wasting GBs of memory for storing all of the input elements? (the code is way too slow now, as it is).
This sounds like the classical interview question "how to store the smallest N items, without knowledge of the size of the data that will be processed?".
One answer is to use a max-heap of N items, and then adjust the heap (remove the top element, add the new element, heapify) if the subsequent item is less than or equal to the top most item in the heap.
This can be easily done using the C++ library functions std::make_heap, std::pop_heap, and std::push_heap.
Here is an example:
#include <vector>
#include <algorithm>
#include <iostream>
int main(int argc, char *argv[])
{
std::vector<int> s;
for (int i : {6, 6, 5, 8, 3, 4, 0, 2, 8, 9, 7, 2})
{
// add the first 5 elements to the vector
if (s.size() < 5)
{
s.push_back(i);
if ( s.size() == 5 )
// make the max-heap of the 5 elements
std::make_heap(s.begin(), s.end());
continue;
}
// now check if the next element is smaller than the top of the heap
if (s.front() >= i)
{
// remove the front of the heap by placing it at the end of the vector
std::pop_heap(s.begin(), s.end());
// get rid of that item now
s.pop_back();
// add the new item
s.push_back(i);
// heapify
std::push_heap(s.begin(), s.end());
}
}
// sort the heap
std::sort_heap(s.begin(), s.end());
for (int d : s)
std::cout << d << " "; //print the 5 smallest elements in ascending order
std::cout << '\n';
return 0;
}
Output:
0 2 2 3 4
Of course you can make this a function and replace the hard-coded 5 with N.
If there are billions of elements, i.e. many more elements than N, the only thing that will be kept in the heap are N elements.
The max-heap is only manipulated if it is detected that the new item satisfies being one of the smallest N elements, and that is easily done by inspecting the top item in the heap and comparing it with the new item that is being processed.
try this, no need to sort everything. this only sorts until the first 5 elements are on the front of the vector, does not need any additional memory (sort is in-place), vector is fast regarding inserts
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> vec{ 6, 6, 5, 8, 3, 4, 0, 2, 8, 9, 7, 2 };
int numElements = 5;
std::partial_sort(vec.begin(), vec.begin() + numElements, vec.end());
for (int i = 0; i < numElements; ++i)
{
std::cout << vec[i] << "\n";
}
return 0;
}
if you do not want to store all inputs, it depends a bit on how you read the input, but the solution will be a bit different. For example read chunks, take smallest 5 of each chunck and in the end just execute once more on the combined "smallest 5" of each chunk.
Q2 ans: Go trought first N elements of the multiset(i am not sure if it is sorted highest to lowest or lowest to highest, so adjust that), and push_back() them to a std::vector.

Count pairs with given sum

Given an array of integers, and a number ‘sum’, find the number of pairs of integers in the array whose sum is equal to ‘sum’. This is the solution by Geeks for Geeks:
// C++ implementation of simple method to find count of
// pairs with given sum.
#include <bits/stdc++.h>
using namespace std;
// Returns number of pairs in arr[0..n-1] with sum equal
// to 'sum'
int getPairsCount(int arr[], int n, int sum)
{
unordered_map<int, int> m;
// Store counts of all elements in map m
for (int i=0; i<n; i++)
m[arr[i]]++;
int twice_count = 0;
// iterate through each element and increment the
// count (Notice that every pair is counted twice)
for (int i=0; i<n; i++)
{
twice_count += m[sum-arr[i]];
// if (arr[i], arr[i]) pair satisfies the condition,
// then we need to ensure that the count is
// decreased by one such that the (arr[i], arr[i])
// pair is not considered
if (sum-arr[i] == arr[i])
twice_count--;
}
// return the half of twice_count
return twice_count/2;
}
// Driver function to test the above function
int main()
{
int arr[] = {1, 5, 7, -1, 5} ;
int n = sizeof(arr)/sizeof(arr[0]);
int sum = 6;
cout << "Count of pairs is "
<< getPairsCount(arr, n, sum);
return 0;
}
My big question is, what is sum-arr? It is not declared, so it must be built in C++. However, I can't find any documentation of it and I am unsure on how it works.
I am trying to follow the code, and it doesn't make sense the sum-arr values.
arr [1,5,8,-1,5]
m [0,1,0,0,0]
sum-arr [5,1,-2,7,1]
Expression, sum - arr[n] which yields the value stored in the nth position of the array.
Here, the value of arr at n (here at the position where i points, since it is arr[i]) is subtracted with the value of sum.
Given, you say,
int arr[] = { 1, 5 , 8, -1, 5 }
and
int sum = 6
Then, for example, take i as 0...
arr[i] is represented as arr[0] which means pointing to the first element (0) in the array arr. Here, the value is 1.
And subtracting 1 from 6, we get 5.
On the other hand, sum - arr is the subtraction of an integer(int) with a pointer(int arr[] will become int * arr inside the program), which, in fact, is not possible, since a super-pointer is bigger than a sub-pointer...
However, you can do, sum - *arr (which is called dereferencing).
Last words,
Just to reduce all this confusion with using pointers and everything, just use std::vector<type>(Example: std::vector<int> arr;), which is a common practice in C++ and whats more, works just like them too! (You are stuck to using pointers in C though!).
Good luck!
My big question is, what is sum-arr?
sum is an id-expression. It names a variable of type int.
arr is an id-expression. It names a different variable, which is of type int*. It is also a sub-expression of the expression arr[i]. That expression is the subscript operator, which in this case increments the pointer arr to its i'th successive sibling in the array and indirects the pointer.
- is the subtraction operator. sum expression is the left hand operand, and arr[i] is the right hand operand.

Finding the kth smallest element in an array using recursion?

#include <iostream>
using namespace std;
void moveToKthSmallest(int a[], int size, int k);
int main() {
int theArray[17] = {42, 5, 412, 56, 14, 98, 488, 4882, 24, 4, 9, 67, 9424, 2, 1, 3, 5};
int num;
cout << "Move to the kth smallest number in the array (size of 17): " << endl;
cin >> num;
moveToKthSmallest(theArray, 17, num);
return 0;
}
void moveToKthSmallest(int a[], int size, int k) {
int pivot = size / 2;
int pivotValue = a[pivot];
int index1 = 0, index2 = 0;
int s1[size], s2[size]; //not sure about this
for (int i = 0; i < size; i++) {
if (a[i] < pivotValue) {
s1[index1] = a[i];
index1++;
}
else {
s2[index2] = a[i];
index2++;
}
}
int s1Size = index1; //problem?
int s2Size = index2; //problem?
if (s1Size == k - 1) {
cout << pivotValue;
}
else if (s1Size > (k - 1)) {
moveToKthSmallest(s1, s1Size, k);
}
else if (s1Size < (k - 1)) {
moveToKthSmallest(s2, s2Size, k - (s1Size - 1));
}
}
I ask the user to input a number (greater than or equal to 0 or less than or equal to 17) and the program should output the kth smallest number in the already generated array.
The above is my attempt but it crashes whenever I run it. I think it has something to do with the declaration of the arrays s1 and s2 in the function and possibly the size values generated from index1 and index2. I've tried using vectors and dynamic arrays but I keep getting error messages in my compiler such as "error: cannot convert 'std::vector**' to 'int*' for argument '1' to 'void moveToKthSmallest" ... to be quite honest, I'm not quite sure what that means.
Am I missing something obvious here?
The first point of order is that this is tagged C++ and not C. Therefore, instead of an int a[] and an int size, you should be using a straightforward std::vector<int>.
Now, with that out of the way, in your example, you're iterating over the entire array each time you recurse.
The second point of order, I don't understand why recursion is even needed here. The answer can be found with a single iteration over your array.
The most simplest way of doing that is to use a second array, let's say std::vector<int> smallest, then iterate over your std::vector<int> a just once.
When iterating over each element:
if smallest.size() is already k, and the current value is larger than the last value in smallest, then proceed to the next value in a, otherwise remove the last value in smallest.
at this point, smallest.size() is always less than k, therefore add the current value in a to the smallest in a manner that keeps the smallest array in sorted order.
At the end of the iteration, the last value in the smallest vector is the kth smallest value in your original vector.
If you would like to know the position of the kth smallest value, this is just a minor modification to the above algorithm, by tracking the position in the smallest vector, rather than the value.
This seems to be a much simpler, straightforward solution, then a complicated recursion-based approach with a confusing pivoting operation. Also, your pivoting example requires the original array to be modified, while my approach does not, and can be used with a const std::vector<int>, even.
P.S. It's not really necessary to keep smallest in sorted order. With a slight modification to the algorithm, smallest can remain unsorted. The homework assignment here is to adjust this algorithm to not require smallest to remain in sorted order.