I was trying to make a program that swaps all the biggest and smallest numbers in an array or a vector. I came up with a program but for some reason I'm not able to debug it to get the problem. Its not printing the vector, neither do I know what the issue is. Can anyone please help me.
Desired Input and Output
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
int n;
cin>>n; //size input
vector<int> arr;
for(int i=0;i<n;i++) //filling up the vector
{
int input;
cin>>input;
arr.push_back(input);
}
vector<int> arr1=arr; //copying the vector
sort(arr1.begin(), arr1.end()); //sorting the new vector
int i=0,j=n-1,i1=0,j1=n-1; //i and j are for the vector arr & i1 and j1 are for vector arr1
while(i1<j1)
{
if(arr1[i1]==arr[i] && arr1[j1]==arr[j]) //if the first and last number of the sorted vector is found in arr the swap
{
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
i1++;
j1--;
i=0; // i and j are set to initial value so that it is checked from the start
j=n-1;;
}
else if(arr1[i1]<arr[i] && arr1[j1]==arr[j]) //if only the biggest place element is found the increase i
{
i++;
}
else if(arr1[i1]==arr[i] && arr1[j1]>arr[j]) //if only the smallest place element is found the decrease j
{
j--;
}
else if(arr1[i1]!=arr[i] && arr1[j1]!=arr[j]) //if none of them are found then increase i and decrease j
{
i++;
j--;
}
}
for(int f=0;f<n;f++) //print the vector
cout<<arr[f]<<" ";
return 0;
}
/*
Sample input 1
6
12 34 87 56 38 98
Sample output 1
98 87 34 38 56 12
Sample input 2
6
8 7 9 2 4 6
Sample output 2
4 6 2 9 8 7
*/
Some help would be really appreciated.
A simpler method would be to make a vector of indexes rather than sorting the vector and trying to find the values in the original vector. For example:
#include <iostream>
#include <algorithm>
#include <vector>
int main()
{
int n;
std::cin >> n;
std::vector<int> arr;
std::vector<int> indexes;
for (int i = 0; i < n; i++)
{
int input;
std::cin >> input;
arr.push_back(input);
indexes.push_back(i);
}
std::sort(indexes.begin(), indexes.end(), [&](int a, int b) {return arr[a] < arr[b]; });
for (int i = 0, j = n - 1; i < n / 2; i++, j--)
{
std::swap(arr[indexes[i]], arr[indexes[j]]);
}
for (int f = 0; f < n; f++)
{
std::cout << arr[f] << " ";
}
return 0;
}
Related
#include <stdio.h>
#include <iostream>
using namespace std;
#define MAX 10
int main()
{
//code
int n,i=0,arr[MAX];
cin>>n;
for(int i =0;i<n;i++)
{
cin>>arr[i];
}
int j=1;
while(i<n&&j<=n)
{
if(arr[i]>0)
{
i++;
j++;
}
else if(arr[i]<0 && arr[j]>0)
{
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
i++;
}
else if(arr[i]<0 && arr[j]<0)
{
j++;
}
else
{
i++;
}
}
for(i=0;i<n;i++)
{
cout<<arr[i]<<" ";
}
return 0;
}
INPUT
4
-8
-6
7
8
OUTPUT
7 8 4196864 -6
How can I resolve this?
I have to move negative elements at end of array and in some cases like provided below I'm getting a garbage value instead of negative element. Some cases are working but many are not specially the ones with two consecutive negative elements with following positive element.
This answer is posted for anyone looking for a C++ solution using algorithm functions. The function that gets the job done is std::partition:
#include <iostream>
#include <algorithm>
#define MAX 10
int main()
{
int n = 4;
int arr[MAX] = {-8, -6, 7, 8};
std::partition(arr, arr + n, [&](int val) { return val >= 0;});
for (int i = 0; i < n; ++i)
std::cout << arr[i] << " ";
}
Output:
8 7 -6 -8
If you want to keep the original, relative order of the elements, you can use std::stable_partition:
#include <iostream>
#include <algorithm>
#define MAX 10
int main()
{
int n = 4;
int arr[MAX] = {-8, -6, 7, 8};
std::stable_partition(arr, arr + n, [&](int val) { return val >= 0;});
for (int i = 0; i < n; ++i)
std::cout << arr[i] << " ";
}
Output:
7 8 -8 -6
From the code you've posted, it looks like you are using C, but with cout and cin borrowed from C++.
As PaulMcKenzie already posted a one-line C++ solution, here is how you would write it your way (the C way):
#include <stdio.h>
void swap(int *a, int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
void move_neg_to_end(int *arr, int n)
{
int start, end = n-1;
for (start = 0; start <= end; start++) {
if (arr[start] >= 0)
continue;
while (start < end && arr[end] < 0)
end--;
if (start >= end)
break;
swap(&arr[start], &arr[end]);
end--;
}
}
Use it like:
int main()
{
int arr[] = {4, -8, -6, 7, 8, -3, 2};
int n = sizeof(arr) / sizeof(*arr);
move_neg_to_end(arr, n);
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
}
EDIT: Here is what's wrong with your code:
1- Don't mix <stdio> and <iostream>. You are using either C or C++, not both. So just choose one of them. If you are using C++ (your case), then go for <iostream>.
2- Avoid using namespace std because it pollutes the global namespace. Use std:: prefix instead, or if you want "shortcuts" using std::cin.
3- Avoid macros like #define MAX 10 and use const int max = 10 instead. Macros make debugging a pain.
4- In C++ use std::array or std::vector. Avoid raw arrays.
5- cin >> n... what if n exceeds MAX?
6- j <= n causes your array to overflow.
7- The logic of your code is wrong. j should start from n-1, not from 0. Here is how you can do it:
If arr[i] >= 0 go to the next element.
If arr[i] < 0 and arr[j] < 0 then keep decrementing j until it finds a positive element or is lesser than or equal to i.
If arr[i] < 0 and arr[j] >= 0 then swap arr[i] and arr[j].
Goto step 1 if i <= j.
to resolve a codeforces problem
I have written this c++ code and i have a big problem while displaying the result: in fact,if i add this code :
cout<<"t2simplifier"<<endl;
aff(t2simplifier);
cout<<endl;
aff(t2primsimplifier);
cout<<endl;
the result will be correct
Otherwise it will be wrong
The code:
#include <bits/stdc++.h>
using namespace std;
void aff (vector<int> v)
{
for (int i=0;i<v.size();i++)
cout<<v[i]<<"|";
}
int main()
{
int n;
cin>>n;
int t1[2][n];
vector <int> t2 ;
vector <int> t2prim ;//flous
vector <int> t2simplifier ;
vector <int> t2primsimplifier ;//flous
vector <int> t3prim ;//flous
for(int i=0;i<n;i++)
cin>>t1[0][i];
for(int i=0;i<n;i++)
cin>>t1[1][i];
for (int i = 0;i<n;i++)
for (int j = i+1 ;j<n ;j++)
{
if(t1[0][i]<t1[0][j])
{
t2.push_back(j);
t2prim.push_back(t1[1][i]+t1[1][j]);
}
}
// cout<<"t2"<<endl;
// aff(t2);
// cout<<endl;
// aff(t2prim);
// cout<<endl;
//pour simplifier t2 et t2prim
int minn;
for (int i = 1;i<n;i++)
{
minn==1000000000;
for (int j = 0 ;j<n ;j++)
{
if((t2[j]==i)&&(t2prim[j]<minn))
{
minn=t2prim[j];
}
}
t2simplifier.push_back(i);
t2primsimplifier.push_back(minn);
}
cout<<"t2simplifier"<<endl;
aff(t2simplifier);
cout<<endl;
aff(t2primsimplifier);
cout<<endl;
for (int i = 0;i<t2simplifier.size();i++)
for (int j = t2simplifier[i] ;j<n ;j++)
{
if(t1[0][t2simplifier[i]]<t1[0][j])
{
t3prim.push_back(t2primsimplifier[i]+t1[1][j]);
}
}
// cout<<"t3prim";
// aff(t3prim);
if (t3prim.size()==0)
cout<<-1;
else
{
//talla3 min
int k = t3prim[0];
for (int i = 1;i<t3prim.size();i++)
{
if(k>t3prim[i])
k=t3prim[i];
}
// k is the result
cout << k ;
}
return 0;
}
input :
5
2 4 5 4 10
40 30 20 10 40
the result with the part of code is :
t2simplifier
1|2|3|4|
70|50|50|50|
90
but when we delete this piece of code(of vector display)
the result will be wrong :
24
Thanks to Mr "François Andrieux"
in the code there is a typing error
The line minn == 1000000000;is performing a comparison and it should be minn = 1000000000;
this error leads to an undefined behavior from reading from an uninitialized variable.
I am trying to solve the Non-Divisible Subset problem from Hackerrank (https://www.hackerrank.com/challenges/non-divisible-subset). I am trying to use the idea that if the sum of a and b is divisible by k, then a%k+b%k = k, however, it's not working very well.
Here is what I've written so far:
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int n;
int k;
cin >> n;
cin >> k;
int j;
vector<int>numbers;
vector<int>remainders;
for(int i = 0; i < n; i++) {
int z;
cin >> z;
numbers.push_back(z);
}
for (vector<int>::iterator it = numbers.begin(); it != numbers.end(); it++) {
j = *it % k;
remainders.push_back(j);
}
for(vector<int>::iterator it2 = remainders.begin(); it2 != remainders.end(); it2++) {
int remainderCount = 0;
int otherRemainderCount = 0;
otherRemainderCount = std::count(remainders.begin(), remainders.end(), k-*it2);
remainderCount = std::count(remainders.begin(), remainders.end(), *it2);
if (remainderCount > otherRemainderCount) {
theChosenOne = *it2;
} else if (otherRemainderCount > remainderCount) {
theChosenOne = k-*it2;
}
cout << theChosenOne << endl;
}
return 0;
}
I created a vector for the remainders and I am using the std::cout function to find out which remainder appears more in the vector. If K would be 5, *it2 = 4, and k-*it2 = 1. If *it2 appears more times, then I would choose *it2. Otherwise, I would choose k-*it2.
Your solution looks to be on the right track, but there is some change that is needed.
You basically need to hash the numbers in the array to proper location.
Have an array rem[k] initialised to 0.
Iterate over the n numbers in the array, and do the following:
rem[array[i]%k]++;
Now you have to deal with only the rem[] array, to find the maximum subset. The rem array has size of maximum k<=100. Make use of the small size of rem[] array to find the solution efficiently.
Edit: Adding the code for you.
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int n,i,k;
cin>>n>>k;
int arr[n];
int rem[k]={0};
for(i=0;i<n;i++)
{
cin>>arr[i];
}
for(i=0;i<n;i++)
{
rem[arr[i]%k]++;
}
int count = 0;
for(i=1;i<=k/2;i++)
{
count = count + max(rem[i],rem[k-i]);
}
count = count + (rem[0]>0?1:0);
if(k%2==0)
{
count = count - rem[k/2];
if(rem[k/2]>0)
count = count + 1;
}
cout<<count;
return 0;
}
After you have found out the contents of the rem[] array, its time to find the maximum subset. If you select rem[1] then you cannot select rem[k-1] as any two numbers, one from rem[1] and another from rem[k-1] can be summed together which will be divisible by k that we don't want. So we find whichever is maximum out of rem[i] and rem[k-i] and add it to the count
My code uses the above logic..
Hope it helps!!!
int main() {
int n,k;
cin>>n>>k;
vector <int> a(n);
vector <int> r(k,0);
for(int i=0;i<n;i++)
{
cin>>a[i];
r[a[i]%k]++;
}
int ctr=min(1,r[0]);
for(int a=1;a<(k/2+1);a++)
{
if(a!=k-a)
ctr+=max(r[a],r[k-a]);
}
if(k%2==0&&r[k/2]!=0)
ctr++;
cout<<ctr;
return 0;
}
This seemed to work
#include <stdio.h>
int min(int a, int b) { return a < b ? a : b; }
int max(int a, int b) { return a > b ? a : b; }
int main() {
int n, k, a, total = 0;
scanf("%d %d", &n, &k);
int mods[k];
for (int i = 0; i < k; i++)
mods[i] = 0;
while (n--) {
scanf("%d", &a);
mods[a % k]++;
}
// can only have 1 value congruent to 0 mod k
total += min(1, mods[0]);
// if even, can only have 1 value congruent to k/2 mod k
if (k % 2 == 0)
total += min(1, mods[k / 2]);
// for all others, pick max of those k and n-k mod k
for (int d = 1; d < (k + 1) / 2; d++) { // for all others,
total += max(mods[d], mods[k - d]);
}
printf("%d", total);
return 0;
}
I was not really sure what this order of printing is called hence called it strange.
Consider the following sample example:
1 3 5
2 6 7
Expected output:
1,2
1,6
1,7
3,2
3,6
3,7
5,2
5,6
5,7
Or this example:
1 2 3
4 5 6
7 8 9
output:
1,4,7
1,4,8
1,4,9
1,5,7
1,5,8
1,5,9
... and so on.
I have analyzed that the number of possible combinations will be rows^columns for any given matrix.Here is my solution:
#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstdio>
using namespace std;
void printAllPossibleCombinations(int** a, int h, int n, string prefix)
{
if (h == 0)
{
for (int i = 0; i < n; i++)
{
cout << prefix << a[0][i] << endl;
}
}
else
{
for (int i = 0; i < n; i++)
{
string recursiveString = prefix;
recursiveString.append(to_string(a[h][i]));
recursiveString.append(1, ',');
printAllPossibleCombinations(a, h-1, n, recursiveString);
}
}
}
int main()
{
int **a;
int m,n,k;
cout<<"Enter number of rows: ";
cin>>m;
a = new int*[m];
cout<<endl<<"Enter number of columns: ";
cin>>n;
for(int i=0;i<m;i++)
{
a[i] = new int [n];
}
for(int i=0;i<m;i++)
{
for(int j = 0; j < n;j++)
{
cout<<"Enter a[" << i << "][" << j<< "] = ";
cin>>a[i][j];
cout<<endl;
}
}
printAllPossibleCombinations(a, m-1, n, "");
return 0;
}
Is there an easy and more optimized way of doing it? Please suggest.
Thank You
As you said, there are rows^columns things to physically print out in the algorithm so you can't do better than an O(rows^columns) algorithm and your algorithm is as optimal as you'll get.
i have an array in data.txt file like 9 3 9 4 5 4 3 7 1 9 6
i need to find duplicate numbers and remove them from the array.
After that i need to collect them at the end of the array.
i wrote a code and the output is 9 3 4 5 7 1 6 9 3 4 9, but i need to put the duplicated numbers in array, in the sequence they appear in the original array.
So i need to get { 9, 3, 4, 5, 7, 1, 6, 9, 4, 3, 9 } as output.
What can i do with the code to reach my goal ?
#include <iostream>
#include <fstream>
using namespace std;
#define SZ 11
int main(){
ifstream fs("data.txt");
if (!fs)
return 0;
int a[SZ];
for (int i = 0; i < SZ; ++i)
fs >> a[i];
for (int k=0; k<SZ; k++) {
for (int j=k+1; j< SZ ; j++) {
if (a[j]==a[k]) {
for (int l=j; l<SZ-1; l++) {
a[l]=a[l+1];
}
a[10]=a[k];
}
}
}
for (int i = 0; i < SZ; ++i)
cout << a[i];
return 1;}
Here's one strategy.
Keep the notion of whether an entry is duplicate or not in a parallel array.
Print the numbers that are not duplicates first.
Then print the numbers that are duplicates.
#include <iostream>
#include <fstream>
using namespace std;
#define SZ 11
int main()
{
ifstream fs("data.txt");
if (!fs)
return 0;
int a[SZ];
int isDuplicate[SZ];
for (int i = 0; i < SZ; ++i)
{
fs >> a[i];
isDuplicate[i] = false;
}
for (int k=0; k<SZ; k++) {
for (int j=k+1; j< SZ ; j++) {
if (a[j]==a[k])
{
isDuplicate[j] = true;
}
}
}
// Print the non-duplicates
for (int i = 0; i < SZ; ++i)
{
if ( !isDuplicate[i] )
cout << a[i] << " ";
}
// Print the duplicates
for (int i = 0; i < SZ; ++i)
{
if ( isDuplicate[i] )
cout << a[i] << " ";
}
cout << endl;
// Not sure why you have 1 as the return value.
// It should be 0 for successful completion.
return 0;
}
If you want to keep the order, you have to compare each number to the previous ones instead of comparing it to the next ones. Your program becomes :
#include <iostream>
#include <iostream>
#include <fstream>
using namespace std;
#define SZ 11
int main(){
ifstream fs("data.txt");
if (!fs)
return 0;
int a[SZ];
for (int i = 0; i < SZ; ++i)
fs >> a[i];
// kk limits the number of iteration, k points to the number to test
for (int k=0, kk=0; kk<SZ; kk++, k++) {
for (int j=0; j< k ; j++) {
if (a[j]==a[k]) {
for (int l=k; l<SZ-1; l++) {
a[l]=a[l+1];
}
a[SZ - 1]=a[j];
// a[k] is a new number and must be controlled at next iteration
k -= 1;
break;
}
}
}
for (int i = 0; i < SZ; ++i)
cout << a[i];
return 1;}
I'm inclined to try out a solution that uses std::remove_if and has a deduping unary predicate. That should retain the order of your duplicate elements.
The OP's (#kuvvetkolu) original example has O(SZ^3) complexity, which is brutal. #RSahu's solution is O(SZ^2), an improvement (and correct), but this should not require O(N^2)...
Here's a version that incurs only space overhead (assuming O(1) hash table lookup). You can use a unordered_set (a hash table) to track whether you've already seen a particular number, put it in the appropriate vector and then merge the vectors at the end.
#include <iostream>
#include <fstream>
#include <unordered_set>
#include <vector>
int main() {
std::ifstream fs("data.txt");
if (!fs)
throw std::runtime_error("File not found!");
std::vector<int> a;
std::vector<int> dups;
std::unordered_set<int> seen;
int d;
while (fs) {
fs >> d;
if (seen.find(d) == seen.end())
{
a.push_back(d);
seen.insert(d);
}
else
{
dups.push_back(d);
}
}
a.insert(a.end(), dups.begin(), dups.end());
for (auto n : a)
std::cout << n << " ";
return 0;
}