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
Related
In the function insertionSort, I have defined a variable temp which is equivalent to arr[i]. For the following while loop I have written some conditions one of them is temp < arr[j]), this code works perfectly fine. BUT if I replace this temp with arr[i] in the condition [ i.e while(j >= 0 && arr[i] < arr[j]) ] this code does work as intended. Why is this happening aren't the values of the variable temp and arr[i] the same, as is defined 2 lines above it ?
With while(j >= 0 && arr[i] < arr[j]), it does not work.With while(j >= 0 && temp < arr[j]), it works.
#include<iostream>
void printSortedArray(int arr[], int size){
std::cout<<"{ ";
for(int m=0; m<size-1; ++m){
std::cout<<arr[m]<<", ";
}
std::cout<<arr[size-1]<<" ";
std::cout<<"}";
}
void insertionSort(int arr[], int size){
for(int i=1; i<size; ++i){
int temp = arr[i]; // <---- Variable *temp* ----
int j = i - 1;
while(j >= 0 && temp < arr[j]){ // <---- *while loop*----
arr[j+1] = arr[j];
--j;
}
arr[j+1] = temp;
}
printSortedArray(arr, size);
}
int main(){
int n; std::cout<<"Enter the size of array : ";
std::cin>>n;
int arr[n];
for(int i=0; i<n; ++i){
std::cout<<"Enter the element at index ~ "<<i<<" : ";
std::cin>>arr[i];
}
insertionSort(arr, n);
}
The loop condition should be while (j > 0 && temp < arr[j])
and
the end arr[j] = temp; instead of arr[j+1] = temp;
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];
}
}
I am trying to solve the problem at: Cut the Sticks.
My code works fine when the array size <=3 but goes bonkers then the size increases to >=6
#include<iostream>
using namespace std;
int minElement(int a[]){
int min = a[0];
int k;
for (k=1; k < 6; k++){
if (a[k] < min and a[k] > 0)
min = a[k];
}
return min;
}
int main(){
int a[6];
for (int i=0; i<6; i++){
cin >> a[i];
}
int minElem, flag;
while (true){
flag = 0;
minElem = minElement(a);
for (int i = 0; i < 6; i++){
a[i] = a[i] - minElem;
}
for (int j = 0; j < 6; j++){
if (a[j] > 0){
cout<<a[j]<<endl;
flag++;
}
}
if (flag == 0)
break;
};
return 0;
}
The problem is arising in the minElement function, it seems. On print min after assignment, it shows min as empty. Similarly, inside the loop in the function, I am getting blanks for all mins. What could be the issue?
EDIT
Please try the code here: http://cpp.sh/2ti6 with the input as [5,4,4,2,2,8]. It doesn't reach zero, the code starts failing before the first iteration, when the minimum element is called as Nothing is returned from the minElement functionn
Problem is there because of this line in the code
int min = a[0];
you need to check that array element is non-zero
int minElement(int a[]){
int min = 0;
int i=0;
while(i<6) // check the array element is non -zero
{
if(a[i]>0){
min = a[i];
break;
}
i++;
}
//int min = a[0];
int k;
for (k=1; k < 6; k++){
if (a[k] < min && a[k] > 0)
min = a[k];
}
return min;
}
The problem lies in your minElement function.
In the case that a[0] happens to be zero, you'll never assign another value to min and will return zero. Out of the function you will subtract zero to the values and enter the infinite loop.
In the case that a[0] is a negative number, you'll end up subtracting a negative value (and so increase the values instead). Then a[0] will become zero and your program loops.
Initializing min with a[0] is not enough, you have to look for a valid minimum value. You could, for example, initialize it with a very large value (not a very good solution) or search the array for the first valid min value.
EDIT:
I added some prints to your code:
...
while (true){
flag = 0;
minElem = minElement(a);
std::cout << "Min: " << minElem << std::endl;
for (int i = 0; i < 6; i++){
a[i] = a[i] - minElem;
}
std::cout << "Values:";
for (int j = 0; j < 6; j++){
std::cout << " " << a[j];
if (a[j] > 0){
//cout << " " << a[j];
flag++;
}
}
std::cout << std::endl;
if (flag == 0)
break;
getchar();
}
...
Here's the output:
5 4 4 2 2 8
Min: 2
Values: 3 2 2 0 0 6
Min: 2
Values: 1 0 0 -2 -2 4
Min: 1
Values: 0 -1 -1 -3 -3 3
Min: 0
Values: 0 -1 -1 -3 -3 3
(...) Loop forever
I hope that helps you understand now what the problem is.
int minElement(int a[]); change this to int minElement(int a[], int size)
2.
int a[6];
for (int i=0; i<6; i++){
cin >> a[i];
}
change this to
int arr_size=0;
cout << "Enter the array size ";
cin >> arr_size;
int a[arr_size];
for (int i=0; i<arr_size; i++){
cin >> a[i];
}
for (int i = 0; i < 6; i++){
a[i] = a[i] - minElem;
}
You are subtracting the min of the array from each element, so at this point there is only one 0 in the array and rest are positive numbers.
for (int j = 0; j < 6; j++){
if (a[j] > 0){
cout<<a[j]<<endl;
flag++;
}
So at this point flag has to be some positive number, and in this case 5.
if (flag == 0)
break;
This condition will never hit and hence the infinite loop.
it has nothing to do with the dimension.
What happens is that if a[0] is the smallest value => it will run in an infinte loop. Why because a[0] eventually becomes 0.
Why does a[0]=0 run in an infinte loop?
What value does minElement return when a[0] is 0?
try replace int min = a[0]; qith min = (a[0]>0) ? a[0]: 1;
or adding `minElem= (minElem>0) ? minElem: 1;' after 'minElem = minElement(a);'
PS:
Looking at all the answers this seems the simplest minElement that does what you want:
int minElement(int a[]){
int min = a[0];
int k;
for (k=1; k < 6; k++){
if(min==0 && a[k]>0 )
min=a[k];
else
if (a[k] < min and a[k] > 0)
min = a[k];
}
return min;
}
the min will only be zero at iteration N if a[j]==0 for all j+1
I solve this base on the link you provide. I use vector for me to easy remove those minimum length stick.
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
int noOfInput;
int input;
vector<int> myVec;
cin>>noOfInput;
for (int i=0; i<noOfInput; i++){
cin >> input;
myVec.push_back(input);
}
sort(myVec.begin(),myVec.end(),greater<int>());
while(myVec.size()>0){
int minimum = myVec[myVec.size()-1];
int lengthOfVector = myVec.size();
cout<<myVec.size()<<" ";
for(int i = lengthOfVector-1 ; i >=0 ; i--){
myVec[i]=myVec[i]-minimum;
if(myVec[i]==0){
myVec.pop_back();
}
}
}
return 0;
}
This code is supposed to check the input array for five consecutive '1's if found, it is supposed to add a '0' at the end as a parity bit for a simple parity bit checker.
This is the code.
#include <conio.h>
#include <stdio.h>
#include <iostream>
using namespace std;
int main() {
int n, a[30], b[5] = {1, 1, 1, 1, 1}, temp = 0, count = 0;
cout << "Enter the size of input bits :";
cin >> n;
cout << endl;
cout << "Enter the input bits :";
for (int i = 0; i < n; i++) {
cin >> a[i];
}
for (int i = n; i >= 0; i--) {
if (i >= 4) {
temp = i;
for (int j = 0; j < 5; j++) {
if (a[temp] == b[j]) {
temp++;
count++;
}
}
}
}
if (count == 4) {
n = n + 1;
a[n] = 0;
}
cout << endl << endl;
for (int i = 0; i < n; i++) {
cout << a[i];
}
getch();
return 0;
}
Here is a simple logic of what you want to achieve.. let's say input array is a, it's length is n:
int counter = 0;
for(int i=0; i<n; i++) {
if(a[i] == 1)
counter++;
else
counter = 0; //need to start looking for 1's again because consecutive stream is broken
if(counter == 5) {
a[i+1] = 0; //found 5 consecutive 1's so next bit will be 0
i++; //don't need to check the next bit which is already 0
counter = 0; //resetting counter
}
}
The above code will change the array [2,3,1,1,1,1,1,3,4,5] to -> [2,3,1,1,1,1,1,0,4,5]
If you want to insert 0 at the end of the array then simply change a[i+1] = 0 to a[n+1] = 0 and remove i++;
You also need to make sure that n is not greater than the size of array.
I'll go line by line from the beginning:
change for(int i=n; i>=0; i--) to for (int i = n-1; i >= 0; i--) (n-sized array in C++ has cells in the range of [0, n-1])
change if(i>=4) to if (n >= 5)
place temp++ after if(a[temp]==b[j]){}, not inside of it.
add
if (count == 5) break;
else count = 0;
just after for(int j = 0; j < 5; j++) loop
change
if(count==4)
{
n=n+1;
a[n]=0;
}
to
if(count == 5){
a[n] = 0;
n = n+1;
}
Once again! n-sized array holds n elements on positions 0 to n-1
Of course sequence makes a difference above!
You can also write it as if (count == 5) a[n++] = 0;
And that would be all.
I am working through the "Introduction to Algorithms" book by Cormen, and I have created the following from pseudocode. However, the first two elements of the Array do not seem to be sorted. I cannot spot the error (possibly because its late). So I was wondering if anybody could see from first glance.
#include <iostream>
#include <stdlib.h>
using namespace std;
int main(){
int input;
cout << "Enter length of desired array." << "\n";
cin >> input;
cout << "\n";
int A [input];
//Populate and print the Array.
for(int i=0; i<input; i++){
A[i] = rand()%99-1;
cout << A[i] << " ";
}
cout << "\n";
//Insertion sort.
for(int j=2; j<input; j++){ //Iterate through the Array.
int key = A[j]; //Store the current element into key.
int i = j-1; //Iterator for while loop.
while(i>0 && A[i]>key){ //Loop to insert A[j] into the sorted sequence.
A[i+1] = A[i]; //Move the element.
i=i-1; //New value of i.
A[i+1] = key; //Update the key
}
}
for(int i=0; i<input; i++){
cout << A[i] << " ";
}
return 0;
}
I haven't looked too carefully, but I think the book's pseudocode uses one-based indexing, and for coding in C (or most modern languages) you need to adjust it to zero-based indexing.
The principal suspect is
for(int j=2; j<input; j++)
Where you might want to start at 1 instead of 2.
The termination condition
while(i>0 && A[i]>key)
might also need to be changed to ensure you're above -1 rather than 0.
EDIT:
After a bit closer look, I'm pretty sure you do also have to adjust that while.
You should also of course review all upper limits for similar off-by-one issues.
change to for (int j = 1; ...)
Actually your code is correct but the problem in there in your for loop initialization. the pseudocode for insertion sort is :
for j ←1 to length(A)-1
key ← A[ j ]
> A[ j ] is added in the sorted sequence A[0, .. j-1]
i ← j - 1
while i >= 0 and A [ i ] > key
A[ i +1 ] ← A[ i ]
i ← i -1
A [i +1] ← key
Actually your code is not considering the first element of the array. It is just staring sorting from second element of the array that's you getting that type of result.
Just change the initialization of j to 1 and it would run correctly.
You can use this code , I have corrected your error
#include<iostream>
#include<stdlib.h>
#include<cstdlib>
using namespace std;
int main(){
int input;
cout<< "Enter length of desired array";
cin>>input;
cout<<"\n";
int A[input];
for(int i = 0 ;i <input ; i++)
{
A[i] = rand() % 100;
cout<<A[i] << "\t";
}
cout<<"\n";
for(int j =1; j<input ; j++)
{ int i;
int key = A[j];
i = j-1;
while( i >=0 && A[i] > key)
{
A[i+1] = A[i];
i = i-1;
A[i+1] = key;
}
}
for(int i = 0 ;i <input ; i++)
{
cout<<A[i] << "\t";
}
}
Take a look at the CLRS insertion sort algorithm translated in java.
int a[] = {5,2,4,3,1};
int key;
int i;
for(int j = 0; j < 5; j++)
{
key = a[j];
i = j - 1;
while(i>=0 && a[i]>key)
{
a[i+1]= a[i];
i--;
}
a[i+1] = key;
System.out.println("i in for loop "+i);
for(int k=0; k<a.length;k++)
{
System.out.print(a[k]+" ");
}
}
Book's pseudocode uses one-based indexing, and for coding in C (or most modern languages) you need to adjust it to zero-based indexing.
Make the following changes and it will work:
for(int i=1; i<input+1; i++){
A[i] = rand()%99-1;
cout << A[i] << " ";
}
for(int j=2; j<input+1; j++){ //Iterate through the Array.
int key = A[j]; //Store the current element into key.
int i = j-1; //Iterator for while loop.
while(i>0 && A[i]>key){ //Loop to insert A[j] into the sorted sequence.
A[i+1] = A[i]; //Move the element.
i=i-1; //New value of i.
A[i+1] = key; //Update the key
}
}
for(int i=1; i<input+1; i++){
cout << A[i] << " ";
}
here's the answer, read the explanation by Don Roby first.
start j = 1 and while loop should have i >= 0