vector.insert doesn't resize vector? - c++

i'm trying to create a function that takes in a vector by reference and if it sees a vector entry 2, it would take delete the entry and replace it with 4 copies of 5.
so if the vector is 222 (then it is size n = 3), i want 555555555555 as the new vector
however, it only works properly for the first few, when the index is < n.
so right now, it would change vector a to be 555522
any ideas how to make the vector resize?
void replace2 (vector <int>* a, int n){
for (int i = 0; i < n; ++i){
if ((*a)[i] == 2){
(*a).erase((*a).begin() + i);
for(int j = 0; j < 4; ++j){
(*a).insert((*a).begin() + i, 5);
}
}
}
}

The problem with using
for ( int i = 0; i < n; ++i ) { ... }
has already been pointed out in one of the comments:
After the first iteration of the loop, (*a)[i] no longer equals 2. Remaining iterations do nothing.
Your function will be simplified if you iterate from the end of the vector and go back.
Also, pass a reference to the vector instead of a pointer.
Here's a complete program:
#include <vector>
#include <iostream>
void replace2(std::vector <int>& a, int n){
for (int i = n-1; i >= 0; --i){
if (a[i] == 2){
a.erase(a.begin() + i);
for(int j = 0; j < 4; ++j){
a.insert(a.begin() + i, 5);
}
}
}
}
int main()
{
std::vector<int> a{2, 2, 2};
replace2(a, 3);
for(auto item : a )
{
std::cout << item;
}
std::cout << std::endl;
}
See it working at https://ideone.com/0Lip5j.

Related

Showing the original index of an element in a vector after bubblesort

I'm new to c++ and i'm having a problem with my code. I need to show the original indexes of a vector before it was sorted, after sorted. I tried it like this:
#include <vector>
using namespace std;
void bubblesort(vector<int> &a, int n) {
for (int j = 0; j < n - 1; j++) {
for (int i = n - 1; i > j; i--) {
if (a.at(i) < a.at(i-1)) {
int aux = a.at(i);
a.at(i) = a.at(i-1);
a.at(i-1) = aux;
}
}
}
}
int main()
{
int n;
cout << "Digite o tamanho do vetor: ";
cin >> n;
vector<int> v;
vector<int> vold;
vector<int> pos;
for (int i = 0; i < n; i++) {
int a;
cin >> a;
v.push_back(a);
vold.push_back(a);
}
bubblesort(v, n);
for (int i = 0; i < n; i++) {
if (vold.at(i) == v.at(i)) {
pos.push_back(i);
}
else {
for (int j = i+1; j < n - 1; j++) {
if (vold.at(i) == v.at(j)) {
pos.at(j) = i;
break;
}
}
}
}
for (const int& i : pos) {
cout << i << " ";
}
system("pause>0");
}
But it didn't worked, if someone could help me to see what I'm doing wrong I would be glad, thanks in advance.
If your goal is to show the indices of the sorted vector, then another approach is to not sort the original vector, but instead to sort a vector of index values based on the original vector.
The index vector would be initialized to 0, 1, 2, etc. up until the vector's size, minus 1.
Here is an example:
#include <vector>
#include <numeric>
#include <iostream>
void bubblesort(std::vector<int> &a, std::vector<int>& index)
{
// Make sure the index vector is the same size as
// the original
index.resize(a.size());
if ( a.size() <= 1 )
return;
// This is just a shortcut way of setting the values to 0,1,2,etc.
std::iota(index.begin(), index.end(), 0);
size_t n = a.size();
// Here is your sort, but with one difference...
for (size_t j = 0; j < n - 1; j++)
{
for (size_t i = n - 1; i > j; i--)
{
// Look at the comparison being done here using the index array
if (a.at(index[i]) < a.at(index[i-1]))
{
// We swap the index values, not the values
// in the vector
int aux = index.at(i);
index.at(i) = index.at(i-1);
index.at(i-1) = aux;
}
}
}
}
int main()
{
std::vector<int> v = {3, 1, 65, 23, 4};
std::vector<int> index;
bubblesort(v, index);
// Display the index values of the sorted items
for (const int& i : index)
std::cout << i << " ";
}
Output:
1 0 4 3 2
Note that the bubblesort function takes a vector of indices, and not n. There is no need to pass n, since a vector already knows its own size by utilizing the size() function.
The output shows the original index of each of the sorted items.

find frequency in array using vector

How can I change my code to get a count for every element?
With my code everything is okay. And it works, but how can I change only that part?
#include <iostream>
#include <vector>
void countFreq(int arr[], int n)
{
// Mark all array elements as not visited
std::vector<bool> visited(n, false);
// Traverse through array elements and
// count frequencies
for (int i = 0; i < n; i++) {
// Skip this element if already processed
if (visited[i] == true)
continue;
// Count frequency
int count = 1;
for (int j = i + 1; j < n; j++) {
if (arr[i] == arr[j]) {
visited[j] = true;
count++;
}
}
std::cout<<count<<" ";
}
}
int main()
{
int n;
std::cin>>n;
int arr[n];
for(int i = 0; i < n; i++){
std::cin>>arr[i];
}
countFreq(arr, n);
return 0;
}
And about the result`
input 10
1 1 2 2 3 3 4 4 5 5
output 2 2 2 2 2
but I want to get
output 2 2 2 2 2 2 2 2 2 2
(for every element)
Your function contains extra code that ends up confusing you. The visited variable is essentially unnecessary. Start the count at 0 and make no special case for the "current" cell and you'll find that some very simple code will do what you need:
void countFreq(int arr[], int n)
{
// Traverse through array elements and
// count frequencies
for (int i = 0; i < n; i++) {
// Count frequency
int count = 0;
for (int j = 0; j < n; j++) {
if (arr[i] == arr[j]) {
count++;
}
}
std::cout << count << " ";
}
}
You need to save the result to an array for each number. Then when you find any processed number then print counter from the saved array.
#include <iostream>
#include <vector>
#include <unordered_map>
void countFreq(int arr[], int n)
{
// Mark all array elements as not visited
std::vector<bool> visited(n, false);
std::unordered_map<int, int> counter;
// Traverse through array elements and
// count frequencies
for (int i = 0; i < n; i++)
{
// Skip this element if already processed
if (visited[i] == true)
{
std::cout << counter[arr[i]] << " ";
continue;
}
// Count frequency
int count = 1;
for (int j = i + 1; j < n; j++)
{
if (arr[i] == arr[j])
{
visited[j] = true;
count++;
}
}
counter[arr[i]] = count;
std::cout<<count<<" ";
}
}
int main()
{
int n;
std::cin>>n;
int arr[n];
for(int i = 0; i < n; i++)
{
std::cin>>arr[i];
}
countFreq(arr, n);
return 0;
}
The issue is that you discard the values already visited.
One possibility is instead to memorize the count when the value is visited the first time,
and to memorize the index value of the first value appearance, when a value is visited the 2nd, 3rd ... time.
#include <iostream>
#include <vector>
void countFreq(const std::vector<int>& arr) {
int n = arr.size();
// Mark all array elements as not visited
std::vector<int> mem_count(n, n);
// Traverse through array elements and
// count frequencies
for (int i = 0; i < n; i++) {
// Skip this element if already processed
if (mem_count[i] != n) {
std::cout << mem_count[mem_count[i]] << " ";
continue;
}
// Count frequency
int count = 1;
for (int j = i + 1; j < n; j++) {
if (arr[i] == arr[j]) {
mem_count[j] = i;
count++;
}
}
mem_count[i] = count;
std::cout << count << " ";
}
}
int main() {
int n;
std::cin>>n;
std::vector<int> arr(n);
for(int i = 0; i < n; i++){
std::cin >> arr[i];
}
countFreq(arr);
return 0;
}
You can find the frequencies of numbers this way if you know the what is your maximum element in the input array. lets say m is maximum number in your array.
so you have to create a new array of size m. you can simply co-relate them as m buckets. from 0 to m. And each bucket will hold the count of each element in the input array. The index of each bucket will refer to element in the input array. This has time complexity O(1) if we know what is the max element the array.
You can do this way:
std::vector<int> frequencey(std::vector<int>& nums){
auto max = *(std::max_element(nums.begin(), nums.end()));
std::vector<int> frequencies(max + 1, 0);
for(int i = 0; i < nums.size(); ++i){
frequencies[nums[i]] +=1;
}
return frequencies;
}
This is very simple
#include <vector>
#include <map>
#include <iostream>
void main()
{
std::vector<int> v { 1,1,2,2,3,3,4,4,5,5 }; // Your input vector
// Count "frequencies"
std::map<int, int> m;
for (auto i : v)
m[i]++;
// Print output
for (auto i : v)
std::cout << m[i] << " ";
}

Delete duplicates from array C++

I am trying to create a simple program which calls on 2 functions. The first function takes a partially filled array, loops through it and deletes any duplicate values. When a value is deleted from the array, the remaining numbers are moved backwards to fill the gap i.e. when the function is finished, all null values of the array will be together at the end.
The second function prints the updated array.
My current code is below. At present when I run my code, the console shows:
2 6 0 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460. It should be showing: 1 2 5 6 if it worked correctly.
Also, I am not sure how to move the remaining elements of the array backwards so that the null values will be together at the end.
#include "pch.h"
#include <iostream>
using namespace std;
void deleteRepeats(int *arr, int arraySize, int& posUsed);
void printArray(int *arr, int arraySize);
int main()
{
int arr[10] = { 1, 2, 2, 5, 6, 1};
int posUsed = 6;
int arraySize = 10;
deleteRepeats(arr, arraySize, posUsed);
printArray(arr, arraySize);
return 0;
}
void deleteRepeats(int *arr, int arraySize, int& posUsed)
{
{
for (int i = 0; i < arraySize; i++)
{
for (int j = i; j < arraySize; j++)
{
if (arr[i] == arr[j])
{
for (int k = j; k < arraySize; k++)
{
arr[k] = arr[k + 1];
}
posUsed--;
}
else
j++;
}
}
}
}
void printArray(int *arr, int arraySize)
{
for (int i = 0; i < arraySize; i++)
{
cout << arr[i] << " ";
}
}
I would let the std containers to what you like to do.
Sort the vector
Use erase and unique to delete duplicates.
Here is the code
#include <vector>
#include <iostream>
#include <algorithm>
void print(const std::vector<int> &arr){
for (const auto & i : arr){
std::cout << i <<" ";
}
std::cout <<"\n";
}
int main() {
std::vector<int> arr{1, 2, 2, 5, 6, 1};
print(arr);
std::sort( arr.begin(), arr.end() );
arr.erase( std::unique( arr.begin(), arr.end() ), arr.end() );
print(arr);
}
Ps. Using int *arr, int arraySize is not very C++ like. Please always try to use a proper container (which almost always will be std::vector).
EDIT:
I changed my answer a bit, because I found this speed comparison (and actuallty the whole question answered).
What's the most efficient way to erase duplicates and sort a vector?
Given your assignment constraints (more C-like, than idiomatic C++), you can rewrite your function like this, to make it work:
void deleteRepeats(int *arr, int arraySize, int& posUsed)
{
for (int i = 0; i < posUsed; ++i)
{
int duplicates = 0;
int j = i + 1;
// find the first duplicate, if exists
for ( ; j < posUsed; ++j)
{
if ( arr[i] == arr[j] ) {
++duplicates;
break;
}
}
// overwrite the duplicated values moving the rest of the elements...
for (int k = j + 1; k < posUsed; ++k)
{
if (arr[i] != arr[k])
{
arr[j] = arr[k];
++j;
}
// ...but skip other duplicates
else
{
++duplicates;
}
}
posUsed -= duplicates;
}
// clean up (could be limited to the duplicates only)
for (int i = posUsed; i < arraySize; ++i)
arr[i] = 0;
}
It might be easier to imagine the algorithm having separate input and output arrays. Then, in pseudo-code:
for i = 0 to input_array_size-1
Is input[i] equal to input[j] for any j between 0 and i-1?
Yes - do nothing
No - copy input[i] to output
To implement this with shared input and output, you need to have two array sizes, input_array_size and output_array_size. Then, the pseudo-code becomes
output_array_size = 0
for i = 0 to input_array_size-1
Is array[i] equal to array[j] for any j between 0 and output_array_size-1?
Yes - do nothing
No:
copy array[i] to array[output_array_size]
Increase output_array_size
Note: it writes output where the input once was, so the check for duplicates should look at all elements that were output. For example, if your array is 1, 2, 1, 3, 5, 6, 3, then for the last 3 the accumulated output is 1, 2, 3, 5, 6, and the code should compare all these with the current element.
To simplify debugging, where it says "do nothing", you can set current element to -1. This way, if you print your array during execution (for debugging), it will be clearer which elements were removed.
there are only two changes made as you can see
1: you were traversing the whole array as you have declared a posUsed=6 variable which is because there are only 6 elements so in in loops you need to traverse in array upto posUsed index like i<posUsed j<posUsed k<posUsed
2: the second changes is in j loop j=i+1 because you don't need to compare the element of any index with element of the same index you have to compare it with elements after that index. if you compare it with same element it will be same and the program will delete that same element which results in ERROR.
onw more thing is that we don't traverse after posUsed index because after that the array is already empty/zero or null whatever you call it
and if you want to display just the non duplicated elements and not the zero's at the end of the array just add if(arr[i]==0) return; in the printArray function loop before cout statement
void deleteRepeats(int *arr, int arraySize, int& posUsed)
{
{
for (int i = 0; i < posUsed; i++)
{
for (int j = i+1; j < posUsed; j++)
{
if (arr[i] == arr[j])
{
for (int k = j; k < posUsed; k++)
{
arr[k] = arr[k + 1];
}
}
}
}
}
}
using two pointers
and if the array sorted
int removeDuplicates(vector<int>& nums) {
if(nums.size() == 0) return 0;
int i = 0;
for(int j = 1; j < nums.size(); j++)
if(nums[j] != nums[i]) nums[++i] = nums[j];
// return new array length
return i + 1;
}
//input: [1, 1, 2, 1] (arr1)
//output: 2 (returned length)
// print unique element
for(int i = 0; i < output; i++) cout << arr1[i] << '\n';
// [1, 2]
time complexity: O(N/2) -> O(N)
space complexity: O(1)
Removing duplicate elements from an unsorted array by O(n^2) complexity.
for (i = 1; i < vec.size(); i++)
{
for (j = 0; j < i; j++)
{
if (vec[i] == vec[j])
{
vec[i] = -1; //Every duplicate element will replace by -1
}
}
}
for (i = 0; i < vec.size(); i++)
{
if (vec[i] != -1)
{
copy.push_back(vec[i]);
/*if you are using an array then store this value into a new array.
first, declare a new array. The new array size will be equal to the
previous array. Like this :
int newArr[sizeOfPreviousArrary];
int j = 0;
newArr[j] = arr[i];
j++;
*/
}
}
Removing duplicate elements from an sorted array by O(n) complexity.
for (i = 0; i < n; i++)
{
if (arr[i] != arr[i+1]){
vec.push_back(arr[i]);
/*if you are using an array then store this value into a new array.
first, declare a new array. The new array size will be equal to the
previous array. Like this :
int newArr[sizeOfPreviousArrary];
int j = 0;
newArr[j] = arr[i];
j++;
*/
}
}
Use map or set for deleting duplicates
void removeDuplicates(int arr[], int n)
{
int i;
// Initialise a set
// to store the array values
set<int> s;
// Insert the array elements
// into the set
for (i = 0; i < n; i++) {
// insert into set
s.insert(arr[i]);
}
set<int>::iterator it;
// Print the array with duplicates removed
cout << "\nAfter removing duplicates:\n";
for (it = s.begin(); it != s.end(); ++it)
cout << *it << ", ";
cout << '\n';
}

Getting segmentation fault (vector declaration)

Find out the maximum sub-array of non negative numbers from an array.
The sub-array should be continuous. That is, a sub-array created by choosing the second and fourth element and skipping the third element is invalid.
Maximum sub-array is defined in terms of the sum of the elements in the sub-array. Sub-array A is greater than sub-array B if sum(A) > sum(B).
This is my solution:
vector<int> Solution::maxset(vector<int> &A) {
// Do not write main() function.
// Do not read input, instead use the arguments to the function.
// Do not print the output, instead return values as specified
// Still have a doubt. Checkout www.interviewbit.com/pages/sample_codes/ for more details
vector <int> bla;
int sum[100]={0};
int k = 0;
int j = 1;
for (int i =0; i < A.size(); i++){
if (A[i] > -1){
sum[k] = A[i] + sum[k];
}
else {
k++;
}
}
cout<<sum[0]<<" ";
cout<<sum[1]<<" ";
cout << sum[2] << " ";
int s = 0;
for (int i =0; i< 100; i++){
if (s < sum[i]){
s = sum[i];
k = i;
}
}
cout << s;
int count = 0;
for (int i =0; i < A.size(); i++){
if (A[i] < 0) {
count ++;
}
if (count == k) {
int j = i+1;
int x = 0;
while (A[j] > 0 && j< (A.size()-1)) {
// bla[x] = A[j];
x++;
j++;
}
}
}
return bla;
}
If I uncomment the line bla[x] = A[j], I get segmentation error. Can someone explain how to undetstand this error? I read it somewhere that there is not enough space in stack. I do not understand how.
Thank you
You can pass the size to a vector object or you can call it's default constructor which creates a vector object with 0 size.
std::vector<int> vecInt(10);
for(int i(0); i < vecInt.size(); i++)
vecInt[i] = i;
Or you can declare a vector with size 0:
std::vector<int> vecInt;
vecInt[0] = 10; // segfault
Because you try to store values in an un-allocated space.
To solve such problem use push_back to store and pop to clear:
So your example can be like this:
while (A[j] > 0 || j< (A.size()-1)) {
// bla[x] = A[j];
bla.push_back(A[j]);
x++;
j++;
}

C++ Selection Sort (vectors)

int temp;
for (int j = 0; j < vecsize - 1; ++j) {
int min = sort.at(j);
for (int i = j+1; i < vecsize; ++i) {
if (min > sort.at(i)) {
min = sort.at(i);
temp = i;
}
}
swap(sort.at(j), sort.at(temp));
}
I am trying to sort (in ascending order) the vector of: 23 42 4 16 8 15
However, my attempt at using selection sort outputs: 4 8 15 23 16 42
What am I doing wrong?
When you define min, you seem to be assigning it the value of the array sort at jth index. Yet, you are using an extra variable tmp to swap the elements, and you seem to fail to initialize it before the inner for loop, similar to how you initialize min. And if all the other elements in the array are smaller than the element at sort[j], tmp will be uninitialized for that iteration of the outer loop, possibly causing it to have an incorrect value in it.
int temp;
for (int j = 0; j < vecsize - 1; ++j) {
int min = sort.at(j);
temp = j; # HERE'S WHAT'S NEW
for (int i = j+1; i < vecsize; ++i) {
if (min > sort.at(i)) {
min = sort.at(i);
temp = i;
}
}
swap(sort.at(j), sort.at(temp));
}
You may see this code at work here. It seems to produce the desired output.
Try this : corrected-code
#include <iostream>
#include <vector>
using namespace std;
void print (vector<int> & vec) {
for (int i =0 ; i < vec.size(); ++i) {
cout << vec[i] << " ";
}
cout << endl;
}
int main() {
int temp;
vector<int> sort;
sort.push_back(23);
sort.push_back(42);
sort.push_back( 4);
sort.push_back( 16);
sort.push_back( 8);
sort.push_back(15);
print(sort);
int vecsize = sort.size();
for (int j = 0; j < vecsize - 1; ++j) {
int min = j;
for (int i = j+1; i < vecsize; ++i) {
if (sort.at(min) > sort.at(i)) {
min = i;
}
}
if (min != j)
swap(sort.at(j), sort.at(min));
}
print(sort);
return 0;
}
If you can use C++11, you can also solve sorting (as in your example) with lambdas. It's a more powerful and optimized way. You should try it maybe in the future.
[EDITED]:
A short example:
// Example program
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> myVector;
myVector.emplace_back(23);
myVector.emplace_back(42);
myVector.emplace_back(4);
myVector.emplace_back(16);
myVector.emplace_back(8);
myVector.emplace_back(15);
std::sort(myVector.begin(), myVector.end(),
[](int a, int b) -> bool
{
return a < b;
});
}