I have to solve a problem that consist of sorting a list of number in c++.
The condition is :
the positive, and 0 must be sorted ascending
negative numbers- descending
if A = {4,-8,7,-6,0,-7,5} the at the final B = {0,4,5,7,-6,-7,-8 }
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
int i,j,n,A[100],B[100],A_nenegative[100],A_negative[100],aux,m=0,k=0;
cout<<"max elements"; cin>>n;
cout<<"elements are"<<endl;
for(i=0;i<n;i++)
{
cin>>A[i];
}
for(i=0;i<n;i++)
for(j=i+1;j<n;j++)
if(A[i]>A[j])
{
aux=A[i];
A[i]=A[j];
A[j]=aux;
}
for(i = 0; i< n; i++)
if(A[i]>=0) {
A_nenegative[i]=A[i];
B[i]=A_nenegative[i];
k++;
}
for(i=0;i<n;i++)
for(j=i+1;j<n;j++)
if(A[i]<A[j])
{
aux=A[i];
A[i]=A[j];
A[j]=aux;
}
for(i=0;i<n;i++)
if(A[i]<0)
{
A_negative[i]=A[i];
m++;
}
}
here is where i stopped. I sort positive numbers in A_nenegative and negative numbers in A_negative. So the question is how can attribute to B first- A_nenegative and then A_negative.
I try after sorting positive numbers immediate to attribute to B , something like that:
for(i = 0; i< n; i++)
if(A[i]>=0) {
A_nenegative[i]=A[i];
B[i]=A_nenegative[i];
k++;
}
But i don't know what to do next
Just use predicate.
std::sort(std::begin(a), std::end(a), [](int a, int b) {
if(a >= 0) {
if(b >= 0) return a < b;
else return true;
}
else {
if(b >= 0) return false;
else return a > b;
}
});
Predicate returns true if a needs to go before b in array, false - otherwise.
So, if a >= 0 and b >= 0 --- we check whether a < b (sort non-negative values in ascending order).
if a >= 0 and b < 0 --- then b needs to go after a, because all negative values go after non-negative.
if a < 0 and b >= 0 --- then b needs to go before a.
if a < 0 and b < 0 --- check whether a > b (to sort in descending order).
Use appropriate predicate with std::sort:
std::sort(std::begin(A), std::end(A), [](int lhs, int rhs) {
auto score = [](int n){ return std::make_tuple(n < 0, std::abs(n)); }
return score(lhs) < score(rhs);
});
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
int n,A[100],B[100],Merge_Array[200],aux;
cout<<"max elements"; cin>>n;
cout<<"elements are"<<endl;
int temp,index_A=0,index_B=0;
for(int i=0;i<n;i++)
{
cin>>temp;
if(temp>=0){
A[index_A++]=temp; //One array for positive
}
else{
B[index_B++]=temp; //Another one for negative
}
}
//Sort positive in ascending
for(int i=0;i<index_A;i++)
{
for(int j=i+1;j<index_A;j++)
if(A[i]>A[j])
{
aux=A[i];
A[i]=A[j];
A[j]=aux;
}
}
//Sort negative in descending
for(int i=0;i<index_B;i++)
for(int j=i+1;j<index_B;j++)
if(B[i]<B[j])
{
aux=B[i];
B[i]=B[j];
B[j]=aux;
}
//Merge A and B
for(int i=0;i<index_A;i++){
Merge_Array[i]=A[i];
}
for(int i=index_A,k=0;i<n;i++,k++){
Merge_Array[i]=B[k];
}
//Print the Merged Array
for(int i=0;i<n;i++){
cout<<Merge_Array[i];
}
}
Hi Cristyan. All others have answered your question. But I still see you are following C type coding for C++. In C++ you are free to declare your variables anywhere not necessarily at the start of the function.
Eg:- for(int i=0;;) is feasible.
Moreover, you have not used dynamic arrays. I know for starters using new and delete can be intimidating. But instead, you can use vectors which offers various functionalities, so pointing you to that vectors.
I like expressive C++:
#include <array>
#include <iostream>
int main() {
auto a = std::array<int, 7>{4, -8, 7, -6, 0, -7, 5};
auto it = std::partition(std::begin(a), std::end(a),
[](const int val) noexcept { return val >= 0; });
std::sort(begin(a), it);
std::sort(it, std::end(a), std::greater<int>());
for(const auto& elem : a) {
std::cout << elem << "\n";
}
}
I would iterate over your input and put every value >= 0 into an array POS and any value < 0 into an array NEG.
Then sort both array ascending and separately and use the absolute value to compare the elements (no effect in POS but required for NEG).
For last push NEG to POS and you have it.
Think thats simple and straight forward.
Related
Question: Smallest Positive missing number
What is wrong with this code?
class Solution
{
public:
//Function to find the smallest positive number missing from the array.
int missingNumber(int arr[], int n)
{
// Your code here
sort(arr,arr+n);
int index=1;
int a;
for(int i=0;i<n;i++){
if(arr[i]>0){
if(arr[i]!=index){
a=index;
break;
}
else{
index++;
}
}
}
return index;
}
};
In every iteration your i is increasing, so this condition which you have written in your for loop:
arr[i]!=index
Here, let's say if the input array has duplicate elements, then for 2 consecutive values of i you will get the same value in arr[i]. In the first comparison, this condition will hold false, so you go to the else part and increment the index value. In the next iteration, your condition arr[i]!=index is always going to be true, as arr[i] is still the same but the index is increased. Thus your program will break from the for loop and the index value is getting returned. That is where it's failing.
So, it will always fail whenever you have duplicate positive elements in your input array. Except for the case when the largest item in the array is the only duplicate in input.
Here's one hint:
for(int i=0;i<n;i++){
if(arr[i]>0){
if(arr[i]!=index){
a=index;
break;
}
else{
index++;
}
}
}
imagine your sorted array is [-10, -5, 0, 1, 2, 3, 4, 5]
When i==3. arr[3] is equal 1, which is the first number you want to evaluate against index. But index will be equal to 3, not 1 as you might have intended.
And as others have pointed out - duplicate numbers in the array are not handled either.
Second hint:
What if I told you... that there was a way to solve this problem without having to sort the input array at all? What if you had an allocated an array of bools of length N to work with....
You should only increase index if arr[i] == index or else you'll get the wrong result for arrays with duplicates, like {1,2,3,4,5,5,6,7}.
int missingNumber(int arr[], int n) {
std::sort(arr,arr + n);
int index=1;
int a;
for(int i=0; i < n; i++) {
if(arr[i] > 0) {
if(arr[i] == index) { // equal, step
++index;
} else if(arr[i] > index) { // greater, we found the missing one
a=index;
break;
} // else, arr[i] == index - 1, don't step
}
}
return index;
}
You are missing a great opportunity to use the sorted array though. Since you're only interested in positive numbers, you can use std::upper_bound to find the first positive number. This search is done very efficiently and it also means that you don't have to check if(arr[i] > 0) in every iteration of your loop.
Example:
int missingNumber(int arr[], int n) {
int* end = arr + n;
std::sort(arr, end);
int* it = std::upper_bound(arr, end, 0); // find the first number greater than 0
int expected = 1;
while(it != end && *it <= expected) {
if(*it == expected) ++expected;
++it;
}
return expected;
}
Alternatively, std::partition the array to put the positve numbers first in the array even before you sort it. That means that you'll not waste time sorting non-positive numbers.
int missingNumber(int arr[], int n) {
int* end = arr + n;
end = std::partition(arr, end, [](int x){ return x > 0; });
std::sort(arr, end);
int expected = 1;
for(int* it = arr; it != end && *it <= expected; ++it) {
if(*it == expected) ++expected;
}
return expected;
}
You can try using a counting array and then walk the array until you come to an empty space.
int main() {
int N;
cin >> N;
int num; // set to zero b/c zero is out lowest possible number
vector<int> numbers;
while (cin >> num) {
numbers.push_back(num);
}
//create a counting array to add a 1 to all the positions that exist
int * cA = new int[10000] {0};
for (int i = 0; i < N; i++) {
if (numbers[i] >= 0) {
cA[numbers[i]]++;
}
}
for (int i = 1; i < 10000; i++) {
if (cA[i] == 0) {
num = i;
break;
}
}
cout << num;
delete []cA;
return 0;
}
How Code Works : first get element count and add all items into Vector by Loop,with second loop going to 1000 i check from 1 to 1000 if any of 1,2,3,4,... is not in the vector i print missing,i do this with bool variable res,if any of loop counter starting from 1 to 1000 is in the vector res variable is set to True otherwise False.be careful in each run of For Loop from 1 to 1000 you should set res=False
#include <iostream>
#include <vector>
using namespace std;
//Programmer : Salar Ashgi
int main()
{
vector<int> v;
int k=0;
cout<<"Enter array count ?\n";
cin>>k;
int n;
for(int i=0;i<k;i++)
{
cout<<"Enter num "<<i+1<<" : ";
cin>>n;
v.push_back(n);
}
bool res=false;
for(int i=1;i<=1000;i++)
{
res=false;
for(int j=0;j<k;j++)
{
if(v[j]==i)
{
res=true;
break;
}
}
if(!res)
{
cout<<i<<" is missing !";
break;
}
}
}
i have to find how many other numbers are less than nums[i] and return them in another vector, for example [6,5,4,8] nums[0] = 6 so there is two numbers less than 6. so 2 would be pushed to the other vector. i am not getting 3 when it comes to checking the last element
class Solution {
public:
vector<int> smallerNumbersThanCurrent(vector<int>& nums) {
vector<int> nums2;
for(int i =0; i< nums.size(); ++i){
int max = nums[i];
int count = 0;
for(int j =0; j < nums.size(); ++j){
if(nums[j] < max && j!=0)
count++;
else
continue;
}
nums2.push_back(count);
}
return nums2;
}
};
You exclude the first element when counting in the condition:
if(nums[j] < max && j!=0)
// ^^ ---- remove this
There are algorithms that do want you need. std::transform transforms one range of values to another one and count_if counts how often a predicate returns true for a given range:
#include <vector>
#include <iostream>
#include <algorithm>
std::vector<size_t> count_if_smaller(const std::vector<int>& v) {
std::vector<size_t> result(v.size());
std::transform(v.begin(),v.end(),result.begin(),
[&](int x){
return std::count_if(v.begin(),v.end(),[&](int y){
return y < x;
});
} );
return result;
}
int main() {
std::vector<int> v{6,5,4,8};
auto r = count_if_smaller(v);
for (auto e : r) std::cout << e << " ";
}
One advantage of using algorithms is that you need not bother about indices of single elements. Introducing the same bug as in your code would be more difficult in the above. In other words, using algorithms is less error prone. Consider to use them when you can.
PS: Your current approach has complexity O(N^2). If you sort the input vector you could get O(N log N) easily.
I am making a program to identify whether a 5 card ( user input ) array is a certain hand value. Pair, two pair, three of a kind, straight, full house, four of a kind ( all card values are ranked 2-9, no face cards, no suit ). I am trying to do this without sorting the array. I am currently using this to look through the array and identify if two elements are equal to each other
bool pair(const int array[])
{
for (int i = 0; i < array; i++)
{
if (array[i]==aray[i+1])
{
return true;
}
else
return false;
}
Does this section of code only evaluate whether the first two elements are the same, or will it return true if any two elements are the same? I.E if the hand entered were 2,3,2,4,5 would this return false, where 2,2,3,4,5 would return true? If so, how do I see if any two elements are equal, regardless of order, without sorting the array?
edit: please forgive the typos, I'm leaving the original post intact, so as not to create confusion.
I was not trying to compile the code, for the record.
It will do neither:
i < array will not work, array is an array not an int. You need something like int arraySize as a second argument to the function.
Even if you fix that then this; array[i]==aray[i+1] will cause undefined behaviour because you will access 1 past the end of the array. Use the for loop condition i < arraySize - 1.
If you fix both of those things then what you are checking is if 2 consecutive cards are equal which will only work if the array is sorted.
If you really cant sort the array (which would be so easy with std::sort) then you can do this:
const int NumCards = 9; // If this is a constant, this definition should occur somewhere.
bool hasPair(const int array[], const int arraySize) {
int possibleCards[NumCards] = {0}; // Initialize an array to represent the cards. Set
// the array elements to 0.
// Iterate over all of the cards in your hand.
for (int i = 0; i < arraySize; i++) {
int myCurrentCard = array[i]; // Get the current card number.
// Increment it in the array.
possibleCards[myCurrentCard] = possibleCards[myCurrentCard] + 1;
// Or the equivalent to the above in a single line.
possibleCards[array[i]]++; // Increment the card so that you
// count how many of each card is in your hand.
}
for (int i = 0; i < NumCards; ++i) {
// If you want to check for a pair or above.
if (possibleCards[i] >= 2) { return true; }
// If you want to check for exactly a pair.
if (possibleCards[i] == 2) { return true; }
}
return false;
}
This algorithm is actually called the Bucket Sort and is really still sorting the array, its just not doing it in place.
do you know the meaning of return keyword? return means reaching the end of function, so in your code if two adjacent values are equal it immediately exits the function; if you want to continue checking for other equality possibilities then don't use return but you can store indexes of equal values in an array
#include <iostream>
using namespace std;
int* CheckForPairs(int[], int, int&);
int main()
{
int array[ ]= {2, 5, 5, 7, 7};
int nPairsFound = 0;
int* ptrPairs = CheckForPairs(array, 5, nPairsFound);
for(int i(0); i < nPairsFound; i++)
{
cout << ptrPairs[i] << endl;
}
if(ptrPairs)
{
delete[] ptrPairs;
ptrPairs = NULL;
}
return 0;
}
int* CheckForPairs(int array[] , int size, int& nPairsFound)
{
int *temp = NULL;
nPairsFound = 0;
int j = 0;
for(int i(0); i < size; i++)
{
if(array[i] == array[i + 1])
nPairsFound++;
}
temp = new int[nPairsFound];
for(int i(0); i < size; i++)
{
if(array[i] == array[i + 1])
{
temp[j] = i;
j++;
}
}
return temp;
}
You could use a std::unordered_set for a O(n) solution:
#include <unordered_set>
using namespace std;
bool hasMatchingElements(const int array[], int arraySize) {
unordered_set<int> seen;
for (int i = 0; i < arraySize; i++) {
int t = array[i];
if (seen.count(t)) {
return true;
} else {
seen.insert(t);
}
}
return false;
}
for (int i = 0; i < array; i++)
{
if (array[i]==aray[i+1])
{
return true;
}
else
return false;
This loop will only compare two adjacent values so the loop will return false for array[] = {2,3,2,4,5}.
You need a nested for loop:
#include <stdio.h>
#include <stdbool.h>
int main()
{
int unsortedArray[] = {2,3,2,4,5};
int size = 5;
for(int i=0;i<size-1;i++)
{ for(int j=i+1;j<size;j++)
{ if(unsortedArray[i]==unsortedArray[j])
{ printf("matching cards found\n");
return 0;
}
}
}
printf("matching cards not found\n");
return 0;
}
----EDIT------
Like Ben said, I should mention the function above will only find the first instance of 2 matching cards but it can't count how many cards match or if there are different cards matching. You could do something like below to count all the number of matching cards in the unsortedArray and save those values into a separate array. It's messier than the implementation above:
#include <iostream>
#include <stdio.h>
#include <stdbool.h>
#defin NUM_CARDS 52;
using namespace std;
int main()
{
int T;
cin>>T;
while(T--)
{
int N,i,j;
cin>>N;
int unsortedArray[N];
for(int i=0;i<N;i++)
cin>>unsortedArray[i];
int count[NUM_CARDS]={0};
int cnt = 0;
for( i=0;i<N-1;i++)
{
for( j=i+1;j<N;j++)
{ if(unsortedArray[i]==-1)
break;
if(unsortedArray[i]==unsortedArray[j])
{
unsortedArray[j]=-1;
cnt++;
}
}
if(unsortedArray[i]!=-1)
{
count[unsortedArray[i]]=cnt; //in case you need to store the number of each cards to
// determine the poker hand.
if(cnt==1)
cout<<" 2 matching cards of "<<unsortedArray[i]<<" was found"<<endl;
else if(cnt>=2)
cout<<" more than 2 matching cards of "<<unsortedArray[i]<<" was found"<<endl;
else
cout<<" no matching cards of "<<unsortedArray[i]<<" was found"<<endl;
cnt = 0;
}
}
I'm trying to delete all elements of an array that match a particular case.
for example..
if(ar[i]==0)
delete all elements which are 0 in the array
print out the number of elements of the remaining array after deletion
what i tried:
if (ar[i]==0)
{
x++;
}
b=N-x;
cout<<b<<endl;
this works only if i want to delete a single element every time and i can't figure out how to delete in my required case.
Im assuming that i need to traverse the array and select All instances of the element found and delete All instances of occurrences.
Instead of incrementing the 'x' variable only once for one occurence, is it possible to increment it a certain number of times for a certain number of occurrences?
edit(someone requested that i paste all of my code):
int N;
cin>>N;
int ar[N];
int i=0;
while (i<N) {
cin>>ar[i];
i++;
}//array was created and we looped through the array, inputting each element.
int a=0;
int b=N;
cout<<b; //this is for the first case (no element is deleted)
int x=0;
i=0; //now we need to subtract every other element from the array from this selected element.
while (i<N) {
if (a>ar[i]) { //we selected the smallest element.
a=ar[i];
}
i=0;
while (i<N) {
ar[i]=ar[i]-a;
i++;
//this is applied to every single element.
}
if (ar[i]==0) //in this particular case, we need to delete the ith element. fix this step.
{
x++;
}
b=N-x;
cout<<b<<endl;
i++;
}
return 0; }
the entire question is found here:
Cut-the-sticks
You could use the std::remove function.
I was going to write out an example to go with the link, but the example form the link is pretty much verbatim what I was going to post, so here's the example from the link:
// remove algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::remove
int main () {
int myints[] = {10,20,30,30,20,10,10,20}; // 10 20 30 30 20 10 10 20
// bounds of range:
int* pbegin = myints; // ^
int* pend = myints+sizeof(myints)/sizeof(int); // ^ ^
pend = std::remove (pbegin, pend, 20); // 10 30 30 10 10 ? ? ?
// ^ ^
std::cout << "range contains:";
for (int* p=pbegin; p!=pend; ++p)
std::cout << ' ' << *p;
std::cout << '\n';
return 0;
}
Strictly speaking, the posted example code could be optimized to not need the pointers (especially if you're using any standard container types like a std::vector), and there's also the std::remove_if function which allows for additional parameters to be passed for more complex predicate logic.
To that however, you made mention of the Cut the sticks challenge, which I don't believe you actually need to make use of any remove functions (beyond normal container/array remove functionality). Instead, you could use something like the following code to 'cut' and 'remove' according to the conditions set in the challenge (i.e. cut X from stick, then remove if < 0 and print how many cuts made on each pass):
#include <iostream>
#include <vector>
int main () {
// this is just here to push some numbers on the vector (non-C++11)
int arr[] = {10,20,30,30,20,10,10,20}; // 8 entries
int arsz = sizeof(arr) / sizeof(int);
std::vector<int> vals;
for (int i = 0; i < arsz; ++i) { vals.push_back(arr[i]); }
std::vector<int>::iterator beg = vals.begin();
unsigned int cut_len = 2;
unsigned int cut = 0;
std::cout << cut_len << std::endl;
while (vals.size() > 0) {
cut = 0;
beg = vals.begin();
while (beg != vals.end()) {
*beg -= cut_len;
if (*beg <= 0) {
vals.erase(beg--);
++cut;
}
++beg;
}
std::cout << cut << std::endl;
}
return 0;
}
Hope that can help.
If you have no space bound try something like that,
lets array is A and number is number.
create a new array B
traverse full A and add element A[i] to B[j] only if A[i] != number
assign B to A
Now A have no number element and valid size is j.
Check this:
#define N 5
int main()
{
int ar[N] = {0,1,2,1,0};
int tar[N];
int keyEle = 0;
int newN = 0;
for(int i=0;i<N;i++){
if (ar[i] != keyEle) {
tar[newN] = ar[i];
newN++;
}
}
cout<<"Elements after deleteing key element 0: ";
for(int i=0;i<newN;i++){
ar[i] = tar[i];
cout << ar[i]<<"\t" ;
}
}
Unless there is a need to use ordinary int arrays, I'd suggest using either a std::vector or std::array, then using std::remove_if. See similar.
untested example (with c++11 lambda):
#include <algorithm>
#include <vector>
// ...
std::vector<int> arr;
// populate array somehow
arr.erase(
std::remove_if(arr.begin(), arr.end()
,[](int x){ return (x == 0); } )
, arr.end());
Solution to Cut the sticks problem:
#include <climits>
#include <iostream>
#include <vector>
using namespace std;
// Cuts the sticks by size of stick with minimum length.
void cut(vector<int> &arr) {
// Calculate length of smallest stick.
int min_length = INT_MAX;
for (size_t i = 0; i < arr.size(); i++)
{
if (min_length > arr[i])
min_length = arr[i];
}
// source_i: Index of stick in existing vector.
// target_i: Index of same stick in new vector.
size_t target_i = 0;
for (size_t source_i = 0; source_i < arr.size(); source_i++)
{
arr[source_i] -= min_length;
if (arr[source_i] > 0)
arr[target_i++] = arr[source_i];
}
// Remove superfluous elements from the vector.
arr.resize(target_i);
}
int main() {
// Read the input.
int n;
cin >> n;
vector<int> arr(n);
for (int arr_i = 0; arr_i < n; arr_i++) {
cin >> arr[arr_i];
}
// Loop until vector is non-empty.
do {
cout << arr.size() << endl;
cut(arr);
} while (!arr.empty());
return 0;
}
With a single loop:
if(condition)
{
for(loop through array)
{
if(array[i] == 0)
{
array[i] = array[i+1]; // Check if array[i+1] is not 0
print (array[i]);
}
else
{
print (array[i]);
}
}
}
I want to remove similar elements from 2 vectors (or list) . I found a similar question here, he used <algorimth> to solve the problem. My question is is the any other approaches without using <algorimth>?
Mine is I create a vector to save the indices of the common elements, then delete the elements have the 'tagged' index. Wild idea though, this ain't work.
An example :
Vector A={1,2,3,4,5};
Vector B={2,3,4,6};
Vector result={1,5};
Here is a solution with lists that already takes care to SORT and UNIQUE the input.
//
#include "stdafx.h"
#include <list>
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int A_arrey[] = { 1, 2, 4, 5, 7, 8 };
int B_arrey[] = { 1, 2, 3, 5, 6, 8, 9 };
list<int> A_list(A_arrey, A_arrey + 6);
list<int> B_list(B_arrey, B_arrey + 7);
A_list.sort();
A_list.unique();
B_list.sort();
B_list.unique();
for (int i = 0; i < sizeof(A_arrey) / sizeof(A_arrey[0]); i++)
B_list.remove(A_arrey[i]);
for (int i = 0; i < sizeof(B_arrey) / sizeof(B_arrey[0]); i++)
A_list.remove(B_arrey[i]);
A_list.merge(B_list);
cout << "My list contains:";
for (list<int>::iterator it = A_list.begin(); it != A_list.end(); it++)
std::cout << ' ' << *it;
cout << '\n';
}
In a case where all values are unique and sorted, the following would work:
#include <iostream>
#include <vector>
using namespace std;
vector<int> A={1,2,3,4,5};
vector<int> B={2,3,4,6};
vector<int> result;
int main()
{
int a = 0;
int b = 0;
while(a < A.size() && b < B.size())
{
/* Same value - skip to next on both sides */
if (A[a] == B[b])
{
a++;
b++;
}
else
/* Smaller value is unique, so push back that */
if (A[a] < B[b])
{
result.push_back(A[a]);
a++;
}
else
{
result.push_back(B[b]);
b++;
}
}
while (a < A.size())
{
result.push_back(A[a]);
a++;
}
while (b < B.size())
{
result.push_back(B[b]);
b++;
}
for(auto r : result)
{
cout << r << ", ";
}
cout << endl;
return 0;
}
There are a number of other methods. If the values aren't enormous, one could use an array to count up when you encounter the value in A, then count down for B, and then go through the array of counters when finished to give a list of unique values.
Edit: Updated with complete code that "works".
I think you need something like this:
vector<T> v(SIZE);
T tmp=v[0];
// ... Fill your vector here
for(int i=0;i<SIZE;++i)
v[i]==tmp?v.erase(i):tmp=v[i];