I am having a difficult time with the merging portion for merge sort. Every time I merge the two halves of the vector, it ends up losing at least one of the values in the vector.
void merge(vector <double> &v, vector <double> &temp, int start, int size) {
int i, j, k;
i = start;
j = start + size - size/2;
k = start;
temp.resize(v.size());
while(i < start+size/2 && j < start+size) {
if(v[i] <= v[j]) {
temp[k] = v[i];
i++;
k++;
// cout << "i <= j " << temp[k] << endl;
} else {
temp[k] = v[j];
j++;
k++;
// cout << "i > j "<< temp[k] << endl;
}
}
for(i = start; i < start+size; i++) {
v[i] = temp[i];
}
}
Since I don't know the caller implementation and I may be wrong, but I think there are two bugs.
First, i is terminated at start+size/2 in the first while-loop.
This value must be equal to the first value of j which is start+size-size/2.
But, for instance, if size==5, then start+5/2=start+2 and start+5-5/2=start+3.
In this case v[start+2] is never entered to the final result.
Secondly, after breaking out of the first while-loop, remaining values of v also must be assigned to temp.
In summary, my quick answer is as follows. Demo is here.
void merge(std::vector<double> &v, std::vector<double> &temp, int start, int size)
{
int i = start; // left array begin
int j = i + size - size/2; // right array begin (which should be guaranteed by caller.)
int i_max = j; // left array end
int j_max = start+size; // right array end
int k = i;
temp.resize(v.size());
while(i < i_max && j < j_max)
{
if(v[i] <= v[j]){
temp[k] = v[i];
i++;
k++;
//std::cout << "i <= j: " << temp[k-1] << std::endl;
}
else {
temp[k] = v[j];
j++;
k++;
//std::cout << "i > j: "<< temp[k-1] << std::endl;
}
}
while (i < i_max) {
temp[k] = v[i];
i++;
k++;
}
while (j < j_max) {
temp[k] = v[j];
j++;
k++;
}
for(i = start; i < j_max; i++) {
v[i] = temp[i];
}
}
Related
I have just tried some of the data structures questions along with my friends. I encountered this problem from one of my friends who is also not able to solve it.
Question: Reverse an array without changing position of zeroes. example : if array has has 0 5 7 8 0 9 then the result should be 0 9 8 7 0 5.
I tried it but it does not do it correctly in all cases, I am sorry if code looks ugly I am a novice right now.
#include<iostream>
using namespace std;
int main()
{
int arr[100], tot, i, j, temp;
cout<<"Enter the Size for Array: ";
cin>>tot;
cout<<"Enter "<<tot<<" Array Elements: ";
for(i=0; i<tot; i++)
cin>>arr[i];
cout<<"\nThe Original Array is:\n";
for(i=0; i<tot; i++)
cout<<arr[i]<<" ";
j = tot-1;
for(i=0; i<j; i++, j--)
{
if(arr[i] == 0) {
i++;
continue;
}else if(arr[j] == 0) {
j--;
continue;
}
else {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
cout<<"\n\nThe Reverse of Given Array is:\n";
for(i=0; i<tot; i++)
cout<<arr[i]<<" ";
cout<<endl;
return 0;
}
I have tried the above code but it does not give the correct results.
The issue here is the fact that you're modifying the loop variables i and j in every iteration of the loop; you need to update it only in the case of elements being swapped:
for(i=0; i<j;)
{
if(arr[i] == 0) {
i++;
}else if(arr[j] == 0) {
j--;
}
else {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
++i;
--j;
}
}
Demo on godbolt.org
Seems you need the next logic inside the loop:
i = 0;
j = tot-1;
while(i<j) {
while (arr[i]==0 && i<j)
i++;
while (arr[j]==0 && j>i)
j--;
if (i < j) {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
i++;
j--;
}
You can use two pointers to switch, simply skipping any 0's.
#include<iostream>
using namespace std;
int main()
{
int arr[100], tot, i, j, temp;
cout<<"Enter the Size for Array: ";
cin>>tot;
cout<<"Enter "<<tot<<" Array Elements: ";
for(i=0; i<tot; i++)
cin>>arr[i];
cout<<"\nThe Original Array is:\n";
for(i=0; i<tot; i++)
cout<<arr[i]<<" ";
i = 0, j = tot-1;
while (i < j) {
if (arr[i]!=0 && arr[j]!=0) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
j--;
} else if (arr[i] == 0) {
i++;
} else {
j--;
}
}
cout << "\n Reverse all elements of the array: " << endl;
// use for loop to print the reverse array
for ( i = 0; i < tot; i++)
{
cout << arr[i] << " ";
}
cout<<endl;
return 0;
}
You can see this in action here: https://godbolt.org/z/84q3McccW
In your code in the loop:
if(arr[i] == 0) {
i++;
continue;
}else if(arr[j] == 0) {
j--;
continue;
You increment i when arr[i] is a 0. But then you continue and for the next iteration i is incremented again as part of i++, j--. This makes your code skip elements.
I suggest to use std::vector and iterators:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> x{1,2,0,3,4,0,0,0};
auto begin = x.begin();
auto end = std::prev(x.end());
while (begin != end) {
while(begin != end && *begin == 0) ++begin;
while(begin != end && *end == 0) --end;
if (begin != end) {
std::swap(*begin,*end);
++begin;
if (begin != end) --end;
}
}
for (const auto& e : x) std::cout << e << " ";
}
output:
4 3 0 2 1 0 0 0
The code starts with iterators to first and last element. In the loop they are advanced while they refer to a 0 and the two didn't cross each other yet. Then the elements are swapped.
If additional memory is acceptable, a much simpler solution is to copy all non zero elements to a second std::vector, std::reverse that vector, then copy back. Alternatively use the ranges library with a filter.
If there were no zeroes to be skipped, the code could be
for (i= 0, j= n-1; i < j; i++, j--)
{
Swap(a[i], a[j]);
}
Now it "suffices" to skip the zeroes. This gives the modified code
for (i= 0, j= n-1; i < j; i++, j--)
{
while (i < j && a[i] == 0) i++;
while (i < j && a[j] == 0) j--;
Swap(a[i], a[j]);
}
Notice that the Swap can be performed with i==j, which is useless but harmless, as 0 ≤ i ≤ j < n.
Update: as done by #fabian, you can compress the three loops in one.
for (i= 0, j= n-1; i < j; )
{
if (a[i] == 0)
i++;
else if (a[j] == 0)
j--;
else
{
Swap(a[i], a[j]);
i++; j--;
}
}
you need to change the logic of reverse.
#include<iostream>
using namespace std;
int main()
{
int arr[100], tot, i, j, temp;
cout<<"Enter the Size for Array: ";
cin>>tot;
cout<<"Enter "<<tot<<" Array Elements: ";
for(i=0; i<tot; i++)
cin>>arr[i];
cout<<"\nThe Original Array is:\n";
for(i=0; i<tot; i++)
cout<<arr[i]<<" ";
j = tot-1;
for ( i = 0, j = tot - 1; i < tot/2; i++, j--)
{
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
cout << "\n Reverse all elements of the array: " << endl;
// use for loop to print the reverse array
for ( i = 0; i < tot; i++)
{
cout << arr[i] << " ";
}
cout<<endl;
return 0;
}
I hope this will help
If I enter an array , at first the code finds the minimums then I want to put zeroes after all the minimums . For example
given an array = 1,1,3,1,1
As we see 1s are the minimum so the result should be = 1,0,1,0,3,1,0,1,0
CODE
#include <pch.h>
#include <iostream>
int main()
{
int min = 10000;
int n;
std::cout << "Enter the number of elements (n): "; //no of elements in the
std::cin >> n; //array
int *array = new int[2 * n];
std::cout << "Enter the elements" << std::endl;
for (int i = 0; i < n; i++) {
std::cin >> array[i];
if (array[i] > min)
min = array[i];
}
for (int i = 0; i < n; i++) {
if (array[i] == min) { // Not very clear about this
for (int k = n; k > i; k--) // part of the code, my teacher
array[k] = array[k - 1]; //explained it to me , but i
array[i + 1] = 0; // didn't understand (from the
i++; // `for loop k` to be precise)
n++;
}
std::cout << array[i] << ", 0";
}
return 0;
}
But my answer doen't put zeroes exactly after minimums
There are few issues in your code, first of all your min is wrong. I have fixed your code with comments on fixes I have made. Please take a look :
#include "stdafx.h"
#include <iostream>
int main()
{
int min = 10000;
bool found = 0;
int n;
std::cout << "Enter the number of elements (n): "; //no of elements in the
std::cin >> n; //array
int *array = new int[2 * n];
std::cout << "Enter the elements" << std::endl;
for (int i = 0; i < n; i++) {
std::cin >> array[i];
if (array[i] < min) //< instead of >
min = array[i];
}
for (int i = 0; i < n; i++) {
if (array[i] == min)
{
for (int k = n; k > i; k--)
{
array[k] = array[k - 1];
}
array[i + 1] = 0;
i++; //increment i here because you don't want to consider 0 that you have just added above.
n++; //since total number of elements in the array has increased by one (because of 0 that we added), we need to increment n
}
}
//print the array separately
for (int i = 0; i < n; i++)
{
std::cout << array[i];
if (i != n - 1)
{
std::cout << ",";
}
}
return 0;
}
The first issue was in the calculation of min: < instead of >.
Another problem if that you are modifyng the paramers iand ninside the loop. This is rather dangerous and implies to be very cautious.
Another issue was that it should be i++; n++; instead of i--,n--;
Here is the code:
// #include <pch.h>
#include <iostream>
int main()
{
int min = 1000000;
int n;
std::cout << "Enter the number of elements (n): "; //no of elements in the
std::cin >> n; //array
int *array = new int[2 * n];
std::cout << "Enter the elements" << std::endl;
for (int i = 0; i < n; i++) {
std::cin >> array[i];
if (array[i] < min)
min = array[i];
}
for (int i = 0; i < n; i++) {
if (array[i] == min) { // Not very clear about this
for (int k = n; k > i; k--) // part of the code, my teacher
array[k] = array[k - 1]; //explained it to me , but i
array[i + 1] = 0; // didn't understand (from the)
i++;
n++;
}
}
for (int i = 0; i < n; i++) {
std::cout << array[i] << " ";
}
std::cout << "\n";
return 0;
}
I'm basically using this code to get my head around the movement of values with arrays. I'm fine up to where it says ++mode[i][0] near the bottom. What does this actually increment? This is not my code by the way.
int main()
{
int arr[10];
int mode[10][2];
cout << "Enter 10 integer values\n";
for (int l = 0; l < 10; l++)
{
cout << "value " << l << ":";
cin >> arr[l];
}
int i, j, temp;
for (i = 0; i < 10; i++)
{
for (j = 9; j > i; j--)
{
if (arr[j] < arr[j - 1])
{
int temp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = temp;
for (int x = 0; x < 10; x++)
{
cout << arr[x] << " ";
}
cout << "\n";
}
}
}
cout << "Highest number = " << arr[9] << "\nLowest number = " << arr[0];
for (i = 0; i < 2; i++)
{
for (j = 0; j < 10; j++)
{
mode[j][i] = 0;
}
}
mode[0][0] = 1;
for (i = 0; i < 10; i++)
{
for (j = 0; j < 10; j++)
{
if (arr[i] == arr[j + 1])
{
++mode[i][0];
mode[i][1] = arr[i];
}
}
}
You can see it that way :
++(mode[i][0]);
So it will increment the value stored in mode[i][0]
since mode[i][0] = some_int, specifically the first element in the array at index [i] it’s incrementing the value stored there
operator[] has a higher precedence than operator++, so ++mode[i][0] is actually treated as ++(mode[i][0]), not (++mode)[i][0] like you are thinking.
The code is incrementing a specific int in the array, it is not incrementing the array itself.
at the moment I have the following code:
for(int i = 0; i < 4; i++){
cout << rowNo[i] << endl;
}
for(int i = 0; i < 4; i++){
for(int j = 0; j < 4; j++){
cout << rowNo[i] << '.';
cout << rowNo[j] << endl;
}
}
for(int i = 0; i < 4; i++){
for(int j = 0; j < 4; j++){
for(int k = 0; k < 4; k++){
cout << rowNo[i] << '.';
cout << rowNo[j] << '.';
cout << rowNo[k] << endl;
}
}
}
for(int i = 0; i < 4; i++){
for(int j = 0; j < 4; j++){
for(int k = 0; k < 4; k++){
for(int l = 0; l < 4; l++){
cout << rowNo[i] << '.';
cout << rowNo[j] << '.';
cout << rowNo[k] << '.';
cout << rowNo[l] << endl;
}
}
}
}
Where rowNo[] is an array {1,2,3,4}
And I was wondering two things:
Can this be simplified, so maybe put into some sort of recursive loop?
Following that, can this then be made for an array of size N?
Your looking for Cartesian_product
With
bool increment(std::vector<std::size_t>& v, std::size_t maxSize)
{
for (auto it = v.rbegin(); it != v.rend(); ++it) {
++*it;
if (*it != maxSize) {
return true;
}
*it = 0;
}
return false;
}
then you can do:
void print_cartesian_product(const std::vector<int>&v, int n)
{
std::vector<std::size_t> indexes(n);
do {
print(v, indexes);
} while (increment(indexes, v.size()));
}
Demo
You are actually trying to print a number encoded in base4 with digit {1, 2, 3, 4}. To achieve it, You only need to define a function to increment by one. I propose a generic solution in the term of amount of number to print and base.
Like others, I use a number to mean "empty digit", and I use zero which is quite convenient.
Complete source code :
#include <iostream>
#include <vector>
bool increment_basep(std::vector<int>& number, int p)
{
int i = 0;
while(i < number.size() && number[i] == p)
{
number[i] = 1;
++i;
}
if(i >= number.size())
return false;
++number[i];
return true;
}
void print_vect(std::vector<int>& number)
{
for(int i = number.size() -1 ; i >= 0; --i)
{
if(number[i] != 0)
std::cout << number[i];
}
std::cout << std::endl;
}
int main() {
int n = 4;
int p = 4;
std::vector<int> num4(n);
std::fill(num4.begin(), num4.end(), 0);
while(increment_basep(num4, p))
{
print_vect(num4);
}
return 0;
}
The increment return whether or not the computation has overflown. When we overflow we know we need to stop.
First solution it comes my mind is that on every loop to put in a buffer and finally to print all the buffers.
I think there are some other ingenious methods
for(int i = 0; i < 4; i++){
put in buffer1 rowNo[i]
for(int j = 0; j < 4; j++){
put in buffer2 rowNo[i],rowNo[j]
for(int k = 0; k < 4; k++){
put in buffer3 rowNo[i],rowNo[j],rowNo[k]
for(int l = 0; l < 4; l++){
put in buffer4 rowNo[i],rowNo[j],rowNo[k],rowNo[l],endl.
}
}
}
}
print(buffer1);
print(buffer2);
print(buffer3);
print(buffer4);
The following is the simplest code I came up with. There has to be a more direct way of doing this though...
It basically introduces a "ghost" index -1, corresponding to an empty place in a number. The ternary operators in the loops conditions are there to avoid duplicates.
int main()
{
int N = 4;
int rowNo[4] = {1, 2, 3, 4};
for (int i = -1; i < N; i++)
for (int j = (i > -1 ? 0 : -1); j < N; j++)
for (int k = (j > -1 ? 0 : -1); k < N; k++)
for (int l = (k > -1 ? 0 : -1); l < N; l++)
{
if (i > -1) std::cout << rowNo[i] << '.';
if (j > -1) std::cout << rowNo[j] << '.';
if (k > -1) std::cout << rowNo[k] << '.';
if (l > -1) std::cout << rowNo[l];
std::cout << std::endl;
}
}
It can of course be generalized to an array of arbitraty size, possibly with some code generation script.
So i've for a school project i've been assigned to implement a merge sort from a pseudo code given by the professor. This is what i came up with, in my use case,
instead of ordering:
0 1 4 5 9
it orders it:
5 4 1 0 9
My use case:
5 9 1 0 5 4
here is the merge part of the merge sort and the global variables
long long intercambio;
int aux[5555], arr[555];
void merge(int begin, int middle, int end) {
int i = begin, j = middle+1, k = begin, temp;
while (i <= middle && j <= end) {
if (arr[i] < arr[j]) {
aux[k] = arr[i];
i++;
}
else {
aux[k] = arr[j];
j++;
}
k++;
noSwaps++;
}
if (i > middle) {
while (j <= end) {
if (aux[k -1] > arr[j]) {
temp = aux[k - 1];
aux[k - 1] = arr[j];
aux[k] = temp;
noSwaps++;
}
else {
aux[k] = arr[j];
}
k++;
j++;
}
}
else {
while (i <= middle) {
if (aux[k -1] > arr[i]) {
temp = aux[k - 1];
aux[k - 1] = arr[i];
aux[k] = temp;
noSwaps++;
}
else {
aux[k] = arr[i];
}
k++;
i++;
}
}
}
Here i call recursively the merge sort
void mergeSort(int begin, int end) {
if (begin < end) {
int middle = (begin + end) / 2;
mergeSort(begin, middle);
mergeSort(middle + 1, end);
merge(begin, middle, end);
}
}
This is the main class
int main(int argc, const char * argv[])
{
int len;
cin >> len;
while (len != 0) {
for (int x = 0; x < len; x++)
cin >> arr[x];
noSwaps = 0;
mergeSort(0, len - 1);
for (int x = 0; x < len; x++)
cout << aux[x] << " ";
cout << endl;
cout << noSwaps << endl;
cin >> len;
}
return 0;
}
I don't see why your code inside the if (i > middle) block and its else block are so complicated. All you have to do is copy the remaining elements into aux, and then from aux back to arr:
void merge(int begin, int middle, int end) {
int i = begin, j = middle+1, k = begin, temp;
while (i <= middle && j <= end) {
// ... same as before ...
}
while (i <= middle)
{
aux[k++] = arr[i++];
}
while (j <= end)
{
aux[k++] = arr[j++];
}
for (i = begin; i <= end; ++i)
{
arr[i] = aux[i];
}
}
This may or may not be less (or more) efficient than your solution, but at least it works :)
By the way, there is a cute trick to implementing merge sort where you don't have to worry about exhausting one range before the other. You copy the left range to aux in ascending order, and the right range in descending order. Then you start merging from both ends, and when the indexes meet, both ranges are exhausted:
void merge(int begin, int middle, int end)
{
int i, j, k;
for (i = begin; i <= middle; ++i)
{
aux[i] = arr[i];
}
for (j = end; j > middle; --j, ++i)
{
aux[i] = arr[j];
}
i = begin;
j = end;
k = begin;
while (i <= j)
{
arr[k++] = aux[(aux[i] < aux[j]) ? i++ : j--];
}
}
This solution appears to produce the wrong output, but only because there is a bug inside main:
for (int x = 0; x < len; x++)
cout << aux[x] << " ";
You are printing aux, when in fact you should be printing arr:
for (int x = 0; x < len; x++)
cout << arr[x] << " ";