Just to provide background, I'm trying to write a function in C++ that takes a vector of ints and a particular int, and removes all of the elements of the vector in place that match the particular int, while returning the number of times it appears.
I'm not asking for help solving the problem. I am stuck trying to figure out why the wrong elements are being erased. Here is the code:
int removeElement(vector<int>& nums, int val) {
int output = 0;
int i = 0;
while (i < nums.size()) {
cout << nums[i] << " " << i << " " << (nums[i] == val) << "\n";
if (nums[i] == val) {
nums.erase(nums.begin() + i);
output+=1;
}
else {
i += 1;
}
}
cout << "---------------\n";
return output;
}
Here is what I'm using to test it:
int main() {
vector<int> firstOne = {3,2,2,3};
cout << removeElement(firstOne,2) << "\n";
firstOne = {3,2,2,3};
cout << removeElement(firstOne,3) << "\n";
}
The output is supposed to be {3,3} and then {2,2} but it's {3,3} twice. Not only that, but the whole thing crashes when I try to test it with a vector with only 2 elements. I suspect there is a gap in my understanding of how vectors work. Can anyone explain to me what I'm doing wrong?
It is better to use erase-remove idiom
int removeElement(vector<int>& nums, int val) {
int output = 0;
int i = 0;
// remove if moves elements "to be removed" in the end
auto newend = std::remove_if(nums.begin(), nums.end(), [&](int element){
cout << element << " " << i << " " << (element == val) << "\n";
i++;
if(element == val) {
output++;
return true; // if true, element will be removed
}
return false; // if false, element will not be removed
});
nums.erase(newend, nums.end());
cout << "---------------\n";
return output;
}
Besides the problems suggested in the comments that you just fixed, your code works fine. You are also not updating output anywhere so the function always returns 0 instead of the number of times the int appears in the passed vector. I edited your function a little and it's good to go:
int removeElement(vector<int>& nums, int val) {
int output = 0;
int i = 0;
while (i < nums.size()) {
cout << nums[i] << " " << i << " " << (nums[i] == val) << "\n";
if (nums[i] == val) {
nums.erase(nums.begin() + i);
output++;
}
else {
i += 1;
}
}
cout << "---------------\n";
return output;
}
Related
The size of unordered map keeps increasing in the last for loop? Why is it so?
class Solution {
public:
bool isAnagram(string s, string t) {
if(s.size() != t.size()){
return false;
}
unordered_map<char,int> sm;
unordered_map<char,int> tm;
for (int i = 0; i<s.size();i++){
sm[s[i]]++;
tm[t[i]]++;
}
for (int j = 0; j<sm.size();j++){
cout << j << endl;
cout << sm.size() <<endl;
if(sm[j] != tm[j]){
cout << sm[j] << endl;
cout << tm[j] << endl;
cout << j << endl;
return false;
}
}
return true;
}
};
I have tried to search online but can't find any relevant answer.
https://en.cppreference.com/w/cpp/container/unordered_map/operator_at
Returns a reference to the value that is mapped to a key equivalent to key, performing an insertion if such key does not already exist.
sm[j] != tm[j]
The [] operator on maps inserts entries if they didn't already exist.
You probably wanted to call .find(j) instead
Could anyone tell me what is wrong with my code:
int Partition(vector<string>& userIDs, int i, int k) {
int pivot = (i + (k - i) / 2);
string temp;
while(i<k) {
cout << "pivot:" << pivot << endl;
while (userIDs.at(i).compare(userIDs.at(pivot))<0) {
cout << "1. i:"<<i<<" UserIDs.at(i):" << userIDs.at(i) << " UserID.at(pivot): " << userIDs.at(pivot) << endl;
i += 1;
}
while (userIDs.at(pivot).compare(userIDs.at(k))<0) {
cout << "2. k:" << k << " UserIDs.at(k):" << userIDs.at(k) << " UserID.at(pivot): " << userIDs.at(pivot) << endl;
k -= 1;
}
if(i<k){
cout << "3. i:" << i << " k:"<<k<<" UserIDs.at(i):" << userIDs.at(i) << " UserID.at(k) : " << userIDs.at(k) << endl;
temp = userIDs.at(i);
userIDs.at(i) = userIDs.at(k);
userIDs.at(k) = temp;
i++;
k--;
}
cout << "4. i:" << i << " k:" << k << endl;
}
cout << " 5. k:" << k << endl;
return k;
}
void Quicksort(vector<string>& userIDs, int i, int k) {
cout << "Quicksort i:" << i << " k:" << k << endl;
if (i >= k) {
return;
}
int lowEndIndex = Partition(userIDs, i, k);
cout << "Quicksort lowEndIndex:" << lowEndIndex << endl;
Quicksort(userIDs, i, lowEndIndex);
Quicksort(userIDs, lowEndIndex+1, k);
}
When I input this list:
BigBen
GardenHeart
GreyMare
TeenPunch
WhiteSand
LifeRacer
Doom
AlienBrain
I get:
AlienBrain
BigBen
GreyMare
GardenHeart
Doom
LifeRacer
TeenPunch
WhiteSand
Why is Doom not in the correct place?
#include <bits/stdc++.h>
using namespace std;
int Partition(vector<string>& userIDs, int i, int k) {
int pivot = i;
string pivotValue = userIDs[pivot];
string temp;
int leftIndex = i;
int rightIndex = k;
while(i<k) {
while (userIDs[i].compare(pivotValue)<=0) {
i++;
if(i >= rightIndex) break;
}
while (pivotValue.compare(userIDs[k])<=0) {;
k--;
if(k <= leftIndex) break;
}
if(i<k){
temp = userIDs[i];
userIDs[i] = userIDs[k];
userIDs[k] = temp;
}
}
// swap
userIDs[pivot] = userIDs[k];
userIDs[k] = pivotValue;
return k;
}
void Quicksort(vector<string>& userIDs, int i, int k) {
if (i >= k) {
return;
}
int lowEndIndex = Partition(userIDs, i, k);
Quicksort(userIDs, i, lowEndIndex - 1);
Quicksort(userIDs, lowEndIndex + 1, k);
}
int main() {
vector<string> userIDs = {"BigBen", "GardenHeart", "GreyMare", "TeenPunch",
"WhiteSand", "LifeRacer", "Doom", "AlienBrain" };
Quicksort(userIDs, 0, userIDs.size() - 1);
for(auto& c: userIDs) cout << c << " ";
cout << endl;
return 0;
}
Fixed the code and tested. Now it works. What were the problems?
As far as I noticed, firstly you didn't put break() statements within the while loops in case i or k exceeds the boundaries of the vector. I've changed the pivot from middle element to first element, but it's just my preference, you can implement the quicksort algorithm with your pivot in the middle, not a big deal. I've called first Quicksort() with lowEndIndex - 1 rather than lowEndIndex. I've used [] operator rather than at(), but again it's my preference. I guess the main problems were that break stuff and calling the quicksort method with lowEndIndex rather than lowEndIndex - 1.
Output:
AlienBrain BigBen Doom GardenHeart GreyMare LifeRacer TeenPunch WhiteSand
template<typename s>
void vecprint2d(const s& vec){
cout<<"{"<<endl;
for(int x = 0; x < vec.size(); x++){
cout<<"{";
for(int y = 0; y < vec[x].size() - 1;y++){
cout << vec[x][y]<<", ";
}
cout<<vec[x][vec[x].size() - 1]<<"}"<<endl;
}
cout<<"}"<<endl;
}
int main(){
vector<vector<int>> vec = {{1,2,3},{},{4,5,6}};
vecprint2d(vec);
return 0;
}
in my attempt at a function for printing a vector of vectors,
why does cout inside the inner loop cause problems, or is the problem elsewhere?
the output right now looks like:
{
{
If the inner vector's size is 0, size() - 1 will overflow and it will loop forever and/or crash. Could that be what is happening on your raspberry pi?
To avoid this, handle 0-sized vectors as well.
For example like this:
template<typename s>
void vecprint2d(const s& vec) {
cout << "{" << endl;
for (auto const& row : vec) {
cout << "{";
int i = 0;
for (auto const& val : row) {
if (i++)
cout << ", ";
cout << val;
}
cout << "}" << endl;
}
cout << "}" << endl;
}
The size() function of an empty vector will return an (unsigned) value of zero and, in your inner loop, you test y against vec[x].size() - 1. This will give a value that has 'underflowed' and thus have the maximum value that a size_t variable can hold, so the y loop will run a very large number of times! However, it will likely fail on the first loop, because trying to access any element of an empty vector is undefined behaviour.
To fix this, enclose your inner loop in an "is it empty" if block (in fact, you should do this for both loops). Here's a possible solution:
template<typename s>
void vecprint2d(const s& vec)
{
cout << "{" << endl;;
if (!vec.empty()) for (size_t x = 0; x < vec.size(); x++) {
cout << "{";
if (!vec[x].empty()) {
for (size_t y = 0; y < vec[x].size() - 1; y++) {
cout << vec[x][y] << ", ";
}
cout << vec[x][vec[x].size() - 1];
}
cout << "}" << endl;
}
cout << "}" << endl;
}
Feel free to ask for further clarification and/or explanation.
So here is my working code for a simple dynamic array. This has to be a sample code for a very entry level data structure implementation:
#include <iostream>
using namespace std;
class AdvancedArray {
public:
AdvancedArray();
~AdvancedArray();
int get_size() const; // get the number of elements stored
double& at(int idx) const; // access the element at idx
void push_back(double d); // adds a new element
void remove(int idx); // remove the element at idx
void clear(); // delete all the data stored
void print() const;
private:
double* elements;
int size;
};
int main()
{
AdvancedArray* arr = new AdvancedArray();
cout << "The Array Size is: " << arr->get_size() << endl;
cout << "Pusing Values: 1.2, 2.1, 3.3, 4.5 in the Array. " << endl;
arr->push_back(1.2);
arr->push_back(2.1);
arr->push_back(3.3);
arr->push_back(4.5);
arr->print();
cout << "The Array Size is: " << arr->get_size() << endl;
cout << "The Element at Index 2 is: " << arr->at(2) << endl;
cout << "Deleting Values: 2.1 from the Array. " << endl;
arr->remove(1);
cout << "The Array Size is: " << arr->get_size() << endl;
arr->print();
cout << "Clearing the Array: " << endl;
arr->clear();
cout << "The Array Size is: " << arr->get_size() << endl;
arr->clear();
return 0;
}
AdvancedArray::AdvancedArray()
{
size = -1;
elements = new double[100]; //Maximum Size of the Array
}
AdvancedArray::~AdvancedArray()
{
delete[] elements;
}
int AdvancedArray::get_size() const
{
if(size < 0)
{
return 0;
}
return size;
}
double & AdvancedArray::at(int idx) const
{
if (idx < 100 && idx >= 0 && size > 0) {
return elements[idx];
}
cout << "Index Out of Bounds." << endl;
}
void AdvancedArray::push_back(double d)
{
if (size >= 100)
{
cout << "Overflow Condition. No More Space!" << endl;
}
else
{
elements[++size] = d;
cout << "Element Pushed In Stack Successfully!" << endl;
}
}
void AdvancedArray::remove(int idx)
{
if (size >= 100 || size < 0)
{
cout << "No Such Element Exists!" << endl;
}
else
{
for(int i = idx; i <size; i++)
{
elements[idx] = elements[idx + 1];
}
size--;
cout << "Element Deleted In Stack Successfully!" << endl;
}
}
void AdvancedArray::clear()
{
delete[] elements;
size = -1;
}
void AdvancedArray::print() const
{
cout << "[ ";
for(int i = 0; i <= size; i++)
{
cout << elements[i] << " ";
}
cout << "]" << endl;
}
So every time I try to run this I have the 2 problems:
What is wrong with my code? Why is the heap getting corrupted (I searched about the error code and that's all has to say)? Is my code doing some major access violations? I am using VS2015.
You do delete [] elements three times without setting elements to nullptr in between. That leads to undefined behavior the second time (and third) time.
When size == 99, the following piece of code attempts to access elements[100]:
if (size >= 100)
{
cout << "Overflow Condition. No More Space!" << endl;
}
else
{
elements[++size] = d;
cout << "Element Pushed In Stack Successfully!" << endl;
}
You need to change ++size to size++.
I am trying to solve the Euler question 419
So far, I think I managed to build an algorithm to find the answer. Or at least it gives the correct result for first 40 step. But I need to compute 1,000,000,000,000th step. Solving first 40 step (with my algorithm) takes about 3-4 seconds. And bigger the iteration number increases, computation time increases as well. I don't think my computer can solve 1,000,000,000,000 iteration in a year.
What I do is simply using temporary vectors for both sequential number counting(form_1 and form_2) and keeping the calculated the result for each iteration(testVec). Here is my code below:
#include <iostream>
#include <stdio.h>
#include <vector>
#include <cmath>
std::vector<int> form_1;
std::vector<int> form_2;
std::vector<int> testVec;
void showVec(std::vector<int>& vec)
{
//
for (unsigned long int i = 0; i < vec.size(); i++)
{
//
std::cout << vec[i] << std::endl;
}
}
void resFin(int start, int stop, std::vector<int>& vec)
{
//
for (unsigned long int i = 0; i < vec.size(); i++)
{
//
if (i == 0)
{
//
form_1.push_back(vec[0]);
//std::cout << "form_1 pushed " << vec[0] << std::endl;
}
else
{
//
if (i != vec.size() - 1)
{
//
if (vec[i] == vec[i - 1])
{
//
form_1.push_back(vec[i]);
//std::cout << "form_1 pushed " << vec[i] << std::endl;
}
else
{
//
form_2.push_back(form_1.size());
form_2.push_back(vec[i - 1]);
form_1.clear();
form_1.push_back(vec[i]);
}
}
else
{
//
if (vec[i] == vec[i - 1])
{
//
form_1.push_back(vec[i]);
//std::cout << "form_1 pushed " << vec[i] << std::endl;
form_2.push_back(form_1.size());
//std::cout << "form_2 pushed " << form_1.size() << std::endl;
form_2.push_back(vec[i - 1]);
//std::cout << "form_2 pushed " << vec[i - 1] << std::endl;
form_1.clear();
}
else
{
//
form_2.push_back(form_1.size());
//std::cout << "form_2 pushed " << form_1.size() << std::endl;
form_2.push_back(vec[i - 1]);
//std::cout << "form_2 pushed " << vec[i - 1] << std::endl;
form_2.push_back(1);
//std::cout << "form_2 pushed " << 1 << std::endl;
form_2.push_back(vec[i]);
//std::cout << "form_2 pushed " << vec[i] << std::endl;
form_1.clear();
}
}
}
}
vec.clear();
for (unsigned long int k = 0; k < form_2.size(); k++)
{
//
vec.push_back(form_2[k]);
//std::cout << "vec pushed " << form_2[k] << std::endl;
}
//showVec(vec);
if (start + 1 != stop)
{
//
form_1.clear();
form_2.clear();
std::cout << "recursed to " << start + 1 << std::endl;
resFin(start + 1, stop, vec);
}
}
void stepFind(int stop, std::vector<int>& vec)
{
//
resFin(1, stop, vec);
}
void trimmVec(std::vector<int>& vec)
{
//
int a = 0;
int b = 0;
int c = 0;
for (unsigned long int i = 0; i < vec.size(); i ++)
{
//
switch (vec[i])
{
case 1:
a++;
a = a % 1073741824;
break;
case 2:
b++;
b = b % 1073741824;
break;
case 3:
c++;
c = c % 1073741824;
break;
default:
break;
}
}
std::cout << "a is " << a << "; b is " << b << "; c is " << c << std::endl;
}
int main()
{
//
testVec.push_back(1);
testVec.push_back(1);
stepFind(39, testVec);
//showVec(testVec);
trimmVec(testVec);
getchar();
return 0;
}
I think no one ought to wait more than a few hours to solve euler problems right? So I am doing something wrong here. So, are there such methods existed to minimize computing time, especially in vectors inside searching(I think this consumes the time most)?