different result between c+ set and unordered_set - c++

I am working on leetcode Frog Jump question and find some wired result when I use unordered_set instead of set for the following test case. unordered_set and set both have size 4, but looks like unordered_set doesn't loop through all elements.
[0,1,2,3,4,5,6,7,8,9,10,11]
output :
set size 4
1
2
3
4
unordered set size: 4
1
Struggleing for hours but can't find out any reason. Any tips would be really appeciated.
bool canCross(vector<int>& stones) {
unordered_map<int, set<int>> dp;
unordered_map<int, unordered_set<int>> dp1;
unordered_set<int> s(stones.begin(), stones.end());
dp[0].insert(0);
dp1[0].insert(0);
for (int i = 0; i < stones.size(); ++i) {
if (i == 10) cout << "set size " << dp[stones[i]].size() << endl;
for (auto a: dp[stones[i]]) {
if (i == 10) cout << a << "\t" << endl;
int b = stones[i];
if (s.count(b + a - 1)) {
dp[b + a - 1].insert(a - 1);
}
if (s.count(b + a)) {
dp[b + a].insert(a);
}
if (s.count(b + a + 1)) {
dp[b + a + 1].insert(a + 1);
}
}
if (i == 10) cout << "unordered set size: " << dp1[stones[i]].size() << endl;
for (auto a: dp1[stones[i]]) {
if (i == 10) cout << a << "\t" << endl;
int b = stones[i];
if (s.count(b + a - 1)) {
dp1[b + a - 1].insert(a - 1);
}
if (s.count(b + a)) {
dp1[b + a].insert(a);
}
if (s.count(b + a + 1)) {
dp1[b + a + 1].insert(a + 1);
}
}
}
return !dp[stones.back()].empty();
}

It happens because some of your insertions modify the same container that you are currently iterating over by a for cycle. Not surprisingly, insertions into setand into unordered_set might end up in different positions in the linear sequence of container elements. In one container the new element ends up in front of the current position and is later iterated over by the cycle. In other container the new element ends up behind the current position and is never seen by the cycle.
It is generally not a good idea to modify container that you are currently iterating over by a range-based for cycle. It might not produce any undefined behavior in your case (if you are using associative containers with stable iterators), but still... in my opinion range-based for should be reserved for iterating over non-changing containers.
In your case insertion of a new element into an std::unordered_set may trigger rehashing and invalidate all iterators of that unordered_set. It means that if that unordered_set is currently being iterated over by a range-based for, you end up with undefined behavior.

Related

How to find median of `std::set` [duplicate]

This question already has answers here:
Efficient way to get middle (median) of an std::set?
(6 answers)
Closed 2 years ago.
I'm trying to find the median of a std::set. Since std::set already sorts everything, I just have to pick the middle element. My idea is to advance to the half: std::advance(e, rtspUrls.size() / 2);, but I'm not sure how it'll behave. What about numbers like 1.5? Will it advance to something?
I'm using a try catch to try to not advance into something undefined. Is this safe?
According to http://www.cplusplus.com/reference/algorithm/min_element/?kw=min_element, std::advance throws if the iterator throws. I'm not sure if the iterator for std::set throws when we try to ++ it (https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator does not say anything).
std::set<RTSPUrl, decltype(compare_rtsp_url)*> rtspUrls(compare_rtsp_url);
std::set<RTSPUrl, decltype(compare_rtsp_url)*>::iterator e = rtspUrls.begin();
for (const RTSPUrl &rtspUrl : stream.rtsp_urls())
{
if (rtspUrl.has_resolution())
{
rtspUrls.push_back(rtspUrl);
}
}
try
{
std::advance(e, rtspUrls.size() / 2);
return *e;
}
catch (std::exception &e)
{
return std::nullopt;
}
I just have to pick the middle element. My idea is to advance to the half: std::advance(e, rtspUrls.size() / 2);, but I'm not sure how it'll behave. What about numbers like 1.5? Will it advance to something?
std::set indices use unsigned integer values (size_t) so the double 1.5 will be converted to size_t 1.
I'm not sure if the iterator for std::set throws when we try to ++
No it will not, but advancing beyond end() is undefined.
A true median for a set with an even amount of elements would take the average of the two middle elements - but that requires that the type you store in your std::set both supports + and /. Example:
std::set<double> foo{1., 2., 3., 10.};
if(foo.empty()) throw std::runtime_error("no elements in set");
double median;
if(foo.size() % 2 == 0) { // even number of elements
auto lo = std::next(foo.begin(), foo.size() / 2 - 1);
auto hi = std::next(lo);
median = (*lo + *hi) / 2.;
} else { // odd number of elements
median = *std::next(foo.begin(), foo.size() / 2);
}
std::cout << median << '\n'; // prints 2.5
In your case, the type in the set does not look like it's supporting + and / to create an average of two RTSPUrls in case you have an even number of elements, so you should probably just go for one of the two middle elements in case you have an even amount. Either by returning an iterator (so the user can then check if it's rtspUrls.end()):
return std::next(rtspUrls.begin(), rtspUrls.size() / 2);
Or by returning a reference to, or copy of, the element:
if(rtspUrls.empty()) throw std::runtime_error("no elements in set");
return *std::next(rtspUrls.begin(), rtspUrls.size() / 2);
With std::set you are limited to using iterators to iterate to the middle element (in case of an odd number of entries in your set) or iterating to middle-1 and middle and taking the average (int the case of a even number of entries) to determine the median.
A simple loop and a counter is about as straight-forward as it gets. A short example would be:
#include <iostream>
#include <set>
int main (void) {
#ifdef ODD
std::set<std::pair<char,int>> s {{'a',1}, {'b',2}, {'c',3}, {'d',4}, {'e',5}};
#else
std::set<std::pair<char,int>> s {{'a',1}, {'b',2}, {'c',3}, {'d',4}, {'e',5}, {'f',6}};
#endif
double median = 0.;
size_t n = 0;
for (auto iter = s.begin(); iter != s.end(); iter++, n++) {
if (n == s.size() / 2 - 1 && s.size() % 2 == 0) {
median += iter->second;
std::cout << iter->first << " " << iter->second << '\n';
}
if (n == s.size() / 2) {
median += iter->second;
if (s.size() % 2 == 0)
median /= 2.;
std::cout << iter->first << " " << iter->second
<< "\n\nmedian " << median << '\n';
break;
}
}
}
(of course you will have to adjust the types to meet your data)
Example Use/Output
Compiled with ODD defined:
$ ./bin/set_median
c 3
median 3
Compiled without additional definition for the EVEN case:
$ ./bin/set_median
c 3
d 4
median 3.5
std::next
You can use std::next to advance to the nth iterator after the current. You must assign the result:
median = 0.;
auto iter = s.begin();
if (s.size() % 2 == 0) {
iter = std::next(iter, s.size() / 2 - 1);
median += iter->second;
iter = std::next(iter);
median += iter->second;
median /= 2.;
}
else {
iter = std::next(iter, s.size() / 2);
median += iter->second;
}
std::cout << "\nmedian " << median << '\n';
std::advance
std::advance advances the iterator provided as a parameter to the nth iterator after the current:
median = 0.;
iter = s.begin();
if (s.size() % 2 == 0) {
std::advance(iter, s.size() / 2 - 1);
median += iter->second;
std::advance(iter, 1);
median += iter->second;
median /= 2.;
}
else {
std::advance(iter, s.size() / 2);
median += iter->second;
}
std::cout << "\nmedian " << median << '\n';
(the output for median is the same as with the loop above)
Look things over and let me know if you have further questions.
I just have to pick the middle element
Only when the set contains an odd number of elements. Otherwise, when the size is even, the median is defined as the mean of the two middle values, sometimes called upper and lower median.
What about numbers like 1.5?
You will never get that since rtspUrls.size() / 2 is an integer division that truncates any decimal places.
I think, passing an float or double as second parameter, like std::advance(e, 1.5) shouldn't compile.
As far as I can see the reference does not specify the type of the second paramter. However the "possible implementations"-section uses always the difference type specific to the first parameter, which is usually an integral type and seems reasonable.
I'm using a try catch to try to not advance into something undefined. Is this safe?
No, dereferencing or incrementing an invalid iterator is undefined behaviour and is not required to throw any exceptions. Allthough many implementations provide extensive error checking in debug builds and be so nice to throw an exception UB occurs. But advancing until half the sets size won't become a problem.

For-loop-condition (vector of ints). How to get the previous value?

I have vector of integers which is filled only by 1 or 0 values. What I am trying to make is that when the current value is 1 and previous/old is 0 or opposite if Current=0 and Previous=1, then to assign another variable(AvgCan) to 0.
I am trying to get from FOR condition previous value. However, if I try it the usual way I still get the same value all the time until the loop end. The issue is in the first if-statement.
int AvgCan = 0;
int OldAvgCan = 0;
int iteration = 0;
int iterationDecrease = 0;
for (int i = 0; i < resultINT.size(); i++)
{
//myFileO << to_string(resultINT.at(i)) + "\n";
cout << to_string((resultINT.at(i))) + " Current" + "\n";
cout << to_string((resultINT.at(i - iteration))) + " Old" + "\n" << endl;
cout << to_string(AvgCan) + "\n" << endl;
iteration = i;
iterationDecrease = i - 1;
if ((resultINT.at(i)) != (resultINT.at(iteration - iterationDecrease)))
{
AvgCan = 0;
}
if ((resultINT.at(i)) == 1)
{
/*if ((resultINT.at(i- iteration)) != 1)
{
AvgCan = 0;
}*/
AvgCan++;
}
if ((resultINT.at(i)) == 0)
{
/*if ((resultINT.at(i- iteration))!=0 )
{
AvgCan = 0;
}*/
AvgCan--;
}
myFileO << to_string(AvgCan) + "\n";
}
As you can see I assigned iterator i to iteration variable and i - 1 to iterationDecrease. (I also tried i-- and similar possible ways.)
I simulated the data so the results are 1,1,1,1,0,0,0,0. When it is changing from 1 to 0 and it gets to the if condition, but each next iteration it still returns 1 like old values, even when it's 0.
I am adding also screenshot for better understanding. On the right side is output in the console.
Here
iteration = i;
iterationDecrease = i - 1;
if ((resultINT.at(i)) != (resultINT.at(iteration - iterationDecrease)))
the iteration - iterationDecrease is equal to i - (i - 1) which is always 1. Meaning in effect that if the statement is equivalent to
if ((resultINT.at(i)) != (resultINT.at(1)))
You probably meant
if (resultINT.at(iteration) != resultINT.at(iterationDecrease))
which is still not correct, as when i==0, the iterationDecrease = -1 which will throw an exception, for the call .at(-1)
You need to start from i=1 in the loop therefore,
for (int i = 1; i < resultINT.size(); i++)
{
// ...code
if (resultINT[i] != resultINT[i-1])
{
// ...code
}
}
Think about the expression iteration - iterationDecrease. It has a constant value 1.
You wished probably resultINT.at(iterationDecrease), but it will cause an exception on the first iteration, since it will try to access -1 element.
Avoid indexing when it is possible. It is not final solution but it may show you right direction. Use adjacent_find to find pairs. I made this example for you here.
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> vec{ 0,0,1,1,0,0,0,1,0,1,0,0,0,0,1,1 };
auto it = std::begin(vec);
while (1) {
it = std::adjacent_find(it, std::end(vec), [](int v1, int v2) {
return std::min(v1, v2) == 0 && std::max(v1, v2) == 1;
});
if (it != std::end(vec)) {
std::cout << "Pairs " << *it << " and " << *(it + 1) << " with indexes "
<< std::distance(std::begin(vec), it) << " and "
<< std::distance(std::begin(vec), it + 1) << std::endl;
++it;
}
else {
break;
}
}
return 0;
}
Output
Pairs 0 and 1 with indexes 1 and 2
Pairs 1 and 0 with indexes 3 and 4
Pairs 0 and 1 with indexes 6 and 7
Pairs 1 and 0 with indexes 7 and 8
Pairs 0 and 1 with indexes 8 and 9
Pairs 1 and 0 with indexes 9 and 10
Pairs 0 and 1 with indexes 13 and 14

How to use std::multimap to map integer key to two integer values that serve as multidimensional array coordinates (for Tic Tac Toe)?

As an exercise, I am trying to create a TicTacToe game in Visual Studio as a console application. First, I created the 3x3 grid with a multidimensional array. I thought an intuitive way to "write" an 'X' or an 'O' in a particular square of the grid would be by having the player input a number 1-9 and that number would map to a particular square. Below is how the numbers would be correspond to the spots in the grid:
1 2 3
4 5 6
7 8 9
Thus, I used std::multimap to map the player input to a square in the grid to practice using maps and multimaps. Since I am new to std::multimap I guess I messed up somewhere: there is no error, the game compiles, but the input does not seem to be mapping correctly to the right square.
I do not know how to fix the bug because I am unfamiliar with maps and multimaps.
*If someone could tell me how to fix the problem using the mapping method I have chosen that would be great!
*I'm also welcoming other and better ideas as to how to approach mapping player input to specific squares!
Sorry for the long code; I don't think I could cut anything more. Thanks for taking the time!
#include <iostream>
#include <map>
using namespace std;
class TTTClass
{
private:
static const int GRID_LENGTH = 3;
char Grid[GRID_LENGTH][GRID_LENGTH] = {' '};
int POInput;
int PXInput;
bool IsInputValid = false;
public:
TTTClass()
{
POInput = 1;
PXInput = 1;
}
void EmptyGrid()
{
for (int RowCounter = 0; RowCounter < GRID_LENGTH; RowCounter++)
{
for (int ColumnCounter = 0; ColumnCounter < GRID_LENGTH; ColumnCounter++)
{
Grid[RowCounter][ColumnCounter] = ' ';
}
}
}
void DisplayGrid()
{
for (int RowCounter = 0; RowCounter < GRID_LENGTH; RowCounter++)
{
std::cout << " ";
for (int ColumnCounter = 0; ColumnCounter < GRID_LENGTH; ColumnCounter++)
{
std::cout << Grid[RowCounter][ColumnCounter];
if (ColumnCounter != GRID_LENGTH - 1) {std::cout << " | ";}
}
if (RowCounter != GRID_LENGTH - 1)
{
std::cout << "\n __|___|__ \n | |\n";
}
}
std::cout << "\n\n";
}
void POTurn()
{
std::multimap<int, int> Gridmm;
Gridmm.insert(std::make_pair(1, 0)); Gridmm.insert(std::make_pair(1, 0));
Gridmm.insert(std::make_pair(2, 0)); Gridmm.insert(std::make_pair(2, 1));
Gridmm.insert(std::make_pair(3, 0)); Gridmm.insert(std::make_pair(3, 2));
Gridmm.insert(std::make_pair(4, 1)); Gridmm.insert(std::make_pair(4, 0));
Gridmm.insert(std::make_pair(5, 1)); Gridmm.insert(std::make_pair(5, 1));
Gridmm.insert(std::make_pair(6, 1)); Gridmm.insert(std::make_pair(6, 2));
Gridmm.insert(std::make_pair(7, 2)); Gridmm.insert(std::make_pair(7, 0));
Gridmm.insert(std::make_pair(8, 2)); Gridmm.insert(std::make_pair(8, 1));
Gridmm.insert(std::make_pair(9, 2)); Gridmm.insert(std::make_pair(9, 2));
do
{
std::cout << "PlayerO, select a square: ";
std::cin >> POInput;
if (POInput < 1 || POInput > 9)
IsInputValid = false;
else
{
std::pair<std::multimap<int, int>::iterator, std::multimap<int, int>::iterator> RepeaterIterator;
RepeaterIterator = Gridmm.equal_range(POInput);
std::multimap<int, int>::iterator itr1 = RepeaterIterator.first;
std::multimap<int, int>::iterator itr2 = RepeaterIterator.second;
Grid[itr1->second][itr2->second] = 'O';
std::cout << "Value at square " << POInput << "/ Coord. " << itr1->second << ", " << itr2->second;
std::cout << " is: " << Grid[itr1->second][itr2->second] << "\n";
IsInputValid = true;
}
} while (IsInputValid == false);
}
void PXTurn()
{
std::multimap<int, int> Gridmm;
Gridmm.insert(std::make_pair(1, 0)); Gridmm.insert(std::make_pair(1, 0));
Gridmm.insert(std::make_pair(2, 0)); Gridmm.insert(std::make_pair(2, 1));
Gridmm.insert(std::make_pair(3, 0)); Gridmm.insert(std::make_pair(3, 2));
Gridmm.insert(std::make_pair(4, 1)); Gridmm.insert(std::make_pair(4, 0));
Gridmm.insert(std::make_pair(5, 1)); Gridmm.insert(std::make_pair(5, 1));
Gridmm.insert(std::make_pair(6, 1)); Gridmm.insert(std::make_pair(6, 2));
Gridmm.insert(std::make_pair(7, 2)); Gridmm.insert(std::make_pair(7, 0));
Gridmm.insert(std::make_pair(8, 2)); Gridmm.insert(std::make_pair(8, 1));
Gridmm.insert(std::make_pair(9, 2)); Gridmm.insert(std::make_pair(9, 2));
do
{
std::cout << "PlayerX, select a square: ";
std::cin >> PXInput;
if (PXInput < 1 || PXInput > 9)
IsInputValid = false;
else
{
std::pair<std::multimap<int, int>::iterator, std::multimap<int, int>::iterator> RepeaterIterator;
RepeaterIterator = Gridmm.equal_range(PXInput);
std::multimap<int, int>::iterator itr1 = RepeaterIterator.first;
std::multimap<int, int>::iterator itr2 = RepeaterIterator.second;
Grid[itr1->second][itr2->second] = 'X';
std::cout << "Value at square " << POInput << "/ Coord. " << itr1->second << ", " << itr2->second;
std::cout << " is: " << Grid[itr1->second][itr2->second] << "\n";
IsInputValid = true;
}
} while (IsInputValid == false);
}
};
int main()
{
TTTClass MyGame;
MyGame.EmptyGrid();
MyGame.DisplayGrid();
MyGame.PXTurn();
MyGame.DisplayGrid();
MyGame.POTurn();
MyGame.DisplayGrid();
return 0;
}
BTW, I know the game only runs through two turns, but problem shows up regardless.
(Too long for a comment and, may be, actually an answer.)
I believe, OP missed the point that the required mapping is int → int × int.
Either the value type has to be e.g. std::pair<int, int> or there are two mappings needed – one to map input to rows and one to map input to columns.
However, there is a very simple linear relation between input index and grid coordinates:
1 -> 0, 0 | 2 -> 0, 1 | 3 -> 0, 2
----------+-----------+----------
4 -> 1, 0 | 5 -> 1, 1 | 6 -> 1, 2
----------+-----------+----------
7 -> 2, 0 | 8 -> 2, 1 | 9 -> 2, 2
I.e. for input int i: int col = (i - 1) % 3, row = (i - 1) / 3;.
This aside: If OP really wants to use a map, then std::map<int, std::pair<int, int> > makes more sense than multimap.
A std::map is a sorted associative container that contains key-value pairs with unique keys. (which you have). Each input index maps to exactly one grid cell and there are no duplicated keys.
It is irrelevant that the value is a pair of ints. It can be rather any object with a minimal requirement of properties:
CopyInsertable
EqualityComparable
Destructible
A std::multimap is an associative container that contains a sorted list of key-value pairs, while permitting multiple entries with the same key. (which you don't need as your keys are unique).
in OPs code:
std::cin >> i;
if (i >= 1 && i <= 9) {
Grid[/* row: */(i - 1) / 3, /* col: */(i - 1) % 3] = mark;
} else {
// harass user
}
Thereby, char mark could have 'X' or 'O' to consider the hint of PaulMcKenzie about code duplication.

Using vector from other class as reverse iterator

I'm on thin ice here, Sorry. I have not used reverse iterators before, and like you can see in my code is that I also want to use a vector from another class as THE iterator object:
double indicators::sRSItemp(input* Close1, int StartDay) {
int n = 14;
double rs;
double rsi;
double tmpavl;
double tmpavg;
if (!RSI.empty()) {
for ( vector<double>::reverse_iterator i = Close1->Close.rbegin(); i != Close1->Close.rend(); ++i ) {
if (Close1->Close[i] < Close1->Close[(i + 1)]){
tmpavl = ((AVL[0] * 13 ) + (Close1->Close[(i +1)] - Close1->Close[i] ) / n);
cout << "AVLtmp " << AVL[0] << endl;
cout << "tmpavl " << tmpavl << endl;
AVL.insert(AVL.begin(), tmpavl);
cout << "AVL is " << AVL[0] << endl;
tmpavg = ((AVG[0] * 13 ) / n );
AVG.insert(AVG.begin(), tmpavg);
// cout << "AVG is " << AVG[i] << endl;
}
else if (Close1->Close[i] > Close1->Close[(i + 1)]) {
tmpavg = ((AVG[0] * 13 ) + (Close1->Close[i] - Close1->Close[(i +1)]) / n );
AVG.insert(AVG.begin(), tmpavg);
// cout << "AVG is " << AVG[i] << endl;
tmpavl = ((AVL[0] * 13 ) / n );
AVL.insert(AVL.begin(), tmpavl);
// cout << "AVL is " << AVL[i] << endl;
}
rs = AVG[0] / AVL[0];
rsi = (100.0 - (100.0 / (1.0 + rs)));
RSI.insert(RSI.begin(), rsi);
}
}
return 0;
}
But when I compile this code I get several errors like this :
error: no match for ‘operator[]’ (operand types are ‘std::vector’ and ‘std::vector::reverse_iterator {aka std::reverse_iterator<__gnu_cxx::__normal_iterator > >}’),
pointing to my vector indexing ??
if (Close1->Close[i] < Close1->Close[(i + 1)]){
Like I said this is new territory for me, and the fault I guess lies with the declaration of the iterator ?
When I iterate through the same vector (front-to-back) in other code there are no problems.
Help much appreciated!
The square brackets operator of std::vector accepts indexes, not iterators.
Here you're trying to use iterators as indexes:
if (Close1->Close[i] < Close1->Close[(i + 1)]) {
Instead of passing iterators to operator [], you should just use asterisks to dereference them, in order to get to vector elements they are pointing to:
if (*i < *(i + 1)) {
Also, be careful with dereferencing i + 1: on the last iteration of your loop i + 1 will be equal to rend() (the reverse past-the-last element iterator). Attempting to access anything via such an iterator will result in undefined behavior.
To see what you're doing wrong, notice that these two are equivalent
int main(){
vector<int> myVec {{1,2,3,4}};
//read then print each value in vector
for(vector<int>::iterator i=myVec.begin();i!=myVec.end(); ++i){
//here i is an iterator not an index
int val = *i; //get value in current position within vector
cout<<val<<endl;
}
for(int i=0; i!=myVec.size(); ++i){
// here i is an index
int val = myVec[i];//get value in current position within vector
cout<<val<<endl;
}
}
in your case use "*i" instead of "Close1->Close[i]" to read the value

Reversing sequence of integers

I'm learning C++ and recently got into this problem:
reverse sequence of positive integers that are coming from std::cin, sequence ends when -1 is approached. This '-1' should not be a part of sequence. Print out reversed sequence, it also must end with -1.
So, I've written pretty straightforward code that does exactly that, it might be not the best in terms of performance, as if I counted right, overall O(N^2 / 2).
int n = 0;
vector<int> numbers; //placeholder vector for input
while (n != -1) {
cin >> n;
numbers.push_back(n);
}
numbers.erase(numbers.end() - 1); // -1 should not be the part of the vector, so I erase it
n = numbers.size() - 1;
for (int i = 0; i < n / 2; ++i) { //swapping
int tmp = numbers[i];
numbers[i] = numbers[n - i];
numbers[n - i] = tmp;
}
for (auto a : numbers) //printing out
cout << a << " "; //each integer in input and output is separated by spacebar
cout << -1; //last element should be '-1'
Unfortunately, this code passes 4/10 test cases which was quite shocking for me.
I would be very grateful if anyone could give me a hint of what is wrong with my code or any generic advices about performance.
Your algorithm is linear, there is no performance issues with it. It looks like you've got a problem with computing indexes while swapping array elements.
You would be better off not adding -1 to the vector in the first place. Moreover, reversing should be done using std::reverse. You also should pay attention to premature end of the input to ensure that your program does not hang if -1 is never entered:
std::vector<int> numbers;
int n;
while (std::cin >> n) {
if (n == -1) break;
numbers.push_back(n);
}
std::reverse(numbers.begin(), numbers.end());
Your output section looks good, although you should add std::endl or '\n' to the end of your output:
std::cout << -1 << std::endl;
You can also write the entire vector to std::cout using std::copy:
std::copy(numbers.begin(), numbers.end(), std::ostream_iterator<int>(std::cout, " "));
Edit: It's for studying purpose, so I can't use std::reverse
Then you should rewrite your loop with iterators and std::iter_swap:
auto first = vector.begin();
auto last = vector.end();
while ((first != last) && (first != --last)) {
std::iter_swap(first++, last);
}
In general, you want to avoid indexes in favor of iterators in order for your code to be idiomatic C++, and avoid potential off-by-one problems.
your problem is when the length of the vector is even
for example if you have 4 elements your n = 4-1 = 3
your loop will go one step only as n/2 = 3/2 = 1
so to fix this just change your loop to this for (int i = 0; i <= n / 2; ++i)