Maximum and Minimum difference (greedy algorithm) - c++

Problem:
You are given an array A ,of n elements.You have to remove exactly n/2 elements from an array and add it to another array B
(intially empty).Find the maximum and minimum values of difference
between these two arrays.The difference between those two arrays is
sum(abs(A[i]-B[i]).
The code only works if the size of the array(N) is even.
Can someone provide a solution which works when the size of array is odd as well.
#include <bits/stdc++.h>
using namespace std;
//This code only works for even number of elements
int main(){
int n;
cin>>n;
vector<int> a(n);
for(int i=0;i<n;i++){
cin>>a[i];
}
sort(a.begin(), a.end());
long long mn = 0,mx = 0;
for(int i=0;i<n/2;i++){
mx+=a[i+n/2]-a[i];
mn+=a[2*i+1]-a[2*i];
}
cout<<abs(mn)<<" "<<abs(mx)<<" ";
return 0;
}

For me, I like to split up the work to easily visualize where efficiencies can be made in the algorithm. The following is very similar to your solution, but works fine for both even and odd length vectors. The average runtime is O(nlogn) for sort with space complexity as O(n) for the vectors.
// Given two arrays of equal length, returns their "Difference", O(n) runtime
int ArrayDiff(vector<int> A, vector<int> B)
{
if (A.size() != B.size() || A.size() == 0) return -1;
int sum = 0;
for (int i = 0; i < A.size(); i++)
{
sum += abs(A[i] - B[i]);
}
return sum;
}
// Given a vector arr, find the max and min "Difference"
void PrintMaxAndMin(vector<int> arr)
{
int n = arr.size();
if (n <= 0) return;
vector<int> Amax, Amin, Bmax, Bmin {};
// for each iteration of removing n/2 elements, we find the max and min of the arrays
sort(arr.begin(), arr.end());
for (int i = 0; i < n/2; i++)
{
Amax.push_back(arr[i]);
Bmax.push_back(arr[n-i-1]);
Amin.push_back(arr[n-i-1]);
Bmin.push_back(arr[n-i-2]);
}
cout << ArrayDiff(Amax, Bmax) << " " << ArrayDiff(Amin, Bmin) << endl;
}
// Run the above functions on a vector of odd and even sizes
int main(){
vector<int> arr_even = { 4,3,2,1 };
cout << "Even Length Vector: ";
PrintMaxAndMin(arr_even);
vector<int> arr_odd = { 5,4,3,2,1 };
cout << "Odd Length Vector: ";
PrintMaxAndMin(arr_odd);
return 0;
}
Here's the working example: live example. Hope this helped.
Program output:
Program stdout
Even Length Vector: 4 2
Odd Length Vector: 6 2

Related

give how many numbers in a vector that are less than itself

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.

Remove the duplicate elements in-place, given a sorted vector with O(1) extra memory

I am trying to remove the duplicate elements in a sorted vector such that each element appears only once.
My code:
#include <iostream>
#include <vector>
using namespace std;
void removeDuplicates(vector<int> &nums)
{
vector<int>::iterator it;
unsigned int j = 1;
while(j < nums.size()-1)
{
if(nums.at(j) == nums.at(j-1))
{
it = nums.begin()+j;
nums.erase(it);
--j; // for every removal, correct the index
}
j += 1; // increment the index
}
}
int main ()
{
vector <int> vect;
int arr[] = {0,0,1,1,1,1,1,2,2,3,3,4}; // the given array
int arrSize = sizeof(arr)/sizeof(arr[0]);
for (int i = 0; i <= arrSize-1; i++) // assign values to the vector
{
vect.push_back(arr[i]);
}
removeDuplicates(vect);
cout << "The unique vector elements are: ";
for (int i = 0; i < vect.size(); i++)
{
cout << vect[i] << " ";
}
cout << endl;
return 0;
}
When I run the code, the output is
The vector unique elements are: 0 1 2 3 4
The question gives the following instruction:
Do not allocate extra space for another array, you must do this by
modifying the input array in-place with O(1) extra memory.
In my code, the Big O time complexity is O(n).
How can I remove the duplicates in-place with an extra memory of O(1)?
How can remove the duplicates in-place with a time complexity of O(1)?
You can't. Even with the vector sorted, you simply must compare every single element to know whether it is unique or not. O(N) is optimal.
However, O(1) time complexity wasn't required by the task either:
... with O(1) extra memory.
There was no mention of time complexity constraint - only space complexity.
The simplest way to get rid of duplicates is to use what's already available in the standard library:
nums.erase(std::unique(nums.begin(), nums.end()), nums.end());
You can implement it in place (no extra memory) with a complexity O(n) by simply using two indices, one for reading the elements and one for writing.
#include <iostream>
#include <vector>
void removeDuplicates(std::vector<int> &nums)
{
unsigned int j = 1;
for (unsigned int i = 1; i < nums.size(); i++)
{
if(nums.at(i) != nums.at(i-1))
{
nums.at(j++) = nums.at(i);
}
}
nums.resize(j);
}
int main ()
{
std::vector <int> vect;
int arr[] = {0,0,1,1,1,1,1,2,2,3,3,4}; // the given array
int arrSize = sizeof(arr)/sizeof(arr[0]);
for (int i = 0; i <= arrSize-1; i++) // assign values to the vector
{
vect.push_back(arr[i]);
}
removeDuplicates(vect);
std::cout << "The unique vector elements are: ";
for (int i = 0; i < vect.size(); i++) {
std::cout << vect[i] << " ";
}
std::cout << "\n";
return 0;
}

Finding the second smallest sum of contiguous sub arrays

I am writing a function that takes in a pointer that points to an array that is dynamically allocated, in addition to the length of the array. I am trying to find the second smallest sum of it's contiguous sub arrays.
I have been writing code to calculate the second smallest value in an array, and also a piece of code that calculates the sum of all the contiguous sub arrays. I was hoping that I would be able to "merge" these two pieces together to get what my desired end result, but I am getting stuck. I would really appreciate any help.
Thank you.
#include <iostream>
using namespace std;
int secondSmallestSum(int *numbers,int length)
{
//Below shows the sum of all contiguous sub arrays.
for(i = 0; i<= length; ++i)
{
int sum = 0;
for(int j = i; j <= length; ++j)
{
sum+=*(numbers+j);
}
}
//Below calculates the second smallest element in an array
int smallest, secondsmallest;
if (*numbers < *(numbers+1))
{
smallest = *numbers;
secondsmallest = *(numbers+1) ;
}
else {
smallest = *(numbers+1) ;
secondsmallest = *(numbers) ;
}
for (i = 2; i < length; i++) {
if (*(numbers+i) < smallest)
{
secondsmallest = smallest;
smallest = *(numbers+i);
}
else if (*(numbers+i) < secondsmallest)
{
secondsmallest = *(numbers+i);
}
}
}
You can do something like this (of course you need to add range checking).
#include <iostream>
#include <vector>
#include <algorithm>
int main(int argc, char** argv) {
std::vector<int> v{3, 1, 4, 5, 6, 2};
std::nth_element(v.begin(), v.begin() + 1, v.end());
std::cout << "The second smallest element is " << v[1] << "\n";
}
Note: using nth_element will change the order of the elements in the vector.
Correct me if I understand you wrong,
by looking at "find the second smallest sum of it's contiguous sub arrays" and the code you posted, I'm assuming your logic is
calculate all sums of all possible contiguous sub arrays
find the second smallest value in the sums
Actually there is a well known algorithm, Kadane's algorithm, that serves a similar purpose (only Kadane's finds THE smallest, not second smallest). You may want to Google it to find more.
Back to your question, I believe the following code does what you want. The code is a variant of Kadane's algorithm.
#include <climits> // for INT_MAX
int findSecondMinOfContiguousSubarray(int arr[], int n)
{
// to store the minimum value that is ending
// up to the current index
int min_ending_here = INT_MAX;
int min = INT_MAX; // absolute min
int min_second = INT_MAX - 1; // second min <- this is what you want
// traverse the array elements
for (int i = 0; i<n/*it is <, not <=*/; i++)
{
// if min_ending_here > 0, then it could not possibly
// contribute to the minimum sum further
if (min_ending_here > 0)
min_ending_here = arr[i];
// else add the value arr[i] to min_ending_here
else
min_ending_here += arr[i];
// update min and min_second
if (min_second > min_ending_here) {
if (min > min_ending_here) {
min_second = min;
min = min_ending_here;
}
else {
min_second = min_ending_here;
}
}
}
return min_second;
}
BTW, I think your code (the piece under //Below shows the sum of all contiguous sub arrays.) can not find all contiguous sub arrays.
An example, arr={1, 2, 3}, your code only consider {1,2,3}, {2,3} and {3} as contiguous sub arrays, while in fact {1,2} should also be considered.
Brutal force o(n^2) complexity (in C++ style not C style):
template<typename Container, typename Func>
void forEachSubrange(Container &container, Func &&f)
{
for (auto subBegin = container.begin(); subBegin != container.end(); ++subBegin)
{
auto subEnd = subBegin;
do {
++subEnd;
f(subBegin, subEnd);
} while (subEnd != container.end());
}
}
int secondSmallestSubrangeSum(const std::vector<int> &a)
{
int firstSum = 0; // empty sub range has zero sum
int secondSum = 0;
forEachSubrange(a, [&firstSum, &secondSum](auto b, auto e) {
auto sum = std::accumulate(b, e, 0);
if (sum < firstSum) {
secondSum = firstSum;
firstSum = sum;
} else if (sum < secondSum) {
secondSum = sum;
}
});
return secondSum;
}
I'm sure it is possible to achieve o(n).
https://wandbox.org/permlink/9cplKBIpfZBPpZ27
or more talkative https://wandbox.org/permlink/X21TdH6xtbMLpV19

Error:No matching function for call to

I am very very new to C++ and I am trying to call the function "jacobi" which performs a user specified number of iterations for the jacobi method (or at least I hope so). On the line where I call 'jacobi' I get the error "No matching function to call to "jacobi". I have read other posts similar to this one and have tried to apply it to my own code but I have been unsuccessful. Maybe there are other issues in my code causing this problem. As mentioned I am very new C++ so any help would be appreciated and please break it down for me.
#include <iostream>
using namespace std;
void jacobi (int size, int max, int B[size], int A[size][size], int init[size], int x[size]){
////
//// JACOBI
////
int i,j,k,sum[size];
k = 1;
while (k <= max) // Only continue to max number of iterations
{
for (i = 0; i < size; i++)
{
sum[i] = B[i];
for (j = 0; j < size; j++)
{
if (i != j)
{
sum[i] = sum[i] - A[i][j] * init[j]; // summation
}
}
}
for (i = 0; i < size; i++) ////HERE LIES THE DIFFERENCE BETWEEN Guass-Seidel and Jacobi
{
x[i] = sum[i]/A[i][i]; // divide summation by a[i][i]
init[i] = x[i]; //use new_x(k+1) as init_x(k) for next iteration
}
k++;
}
cout << "Jacobi Approximation to "<<k-1<<" iterations is: \n";
for(i=0;i<size;i++)
{
cout <<x[i]<< "\n"; // print found approximation.
}
cout << "\n";
return;
}
int main (){
// User INPUT
// n: number of equations and unknowns
int n;
cout << "Enter the number of equations: \n";
cin >> n;
// Nmax: max number of iterations
int Nmax;
cout << "Enter max number of interations: \n";
cin >> Nmax;
// int tol;
// cout << "Enter the tolerance level: " ;
// cin >> tol;
// b[n] and a[n][n]: array of coefficients of 'A' and array of int 'b'
int b[n];
int i,j;
cout << "Enter 'b' of Ax = b, separated by a space: \n";
for (i = 0; i < n; i++)
{
cin >> b[i];
}
// user enters coefficients and builds matrix
int a[n][n];
int init_x[n],new_x[n];
cout << "Enter matrix coefficients or 'A' of Ax = b, by row and separate by a space: \n";
for (i = 0; i < n; i++)
{
init_x[i] = 0;
new_x[i] = 0;
for (j = 0; j < n; j++)
{
cin >> a[i][j];
}
}
jacobi (n, Nmax, b, a, init_x, new_x);
}
The problem:
There are several problems, related to the use of arrays:
You can't pass arrays as parameter by value.
You can't pass multidimensional arrays as parameter if the dimensions are variable
You can't define arrays of variable length in C++
Of course there are ways to do all these kind of things, but it uses different principles (dynamic allocation, use of pointers) and requires additional work (especially for the access of multidimensional array elements).
Fortunately, there is a much easier solution also !
The solution:
For this kind of code you should go for vector : these manage variable length and can be passed by value.
For the jacobi() function, all you have to do is to change its definition:
void jacobi(int size, int max, vector<int> B, vector<vector<int>> A, vector<int> init, vector<int> x) {
int i, j, k;
vector<int> sum(size); // vector of 'size' empty elements
// The rest of the function will work unchanged
...
}
Attention however: the vectors can be of variable size and this jacobio implementation assumes that all the vectors are of the expected size. In professional level code you should check that it's the case.
For the implementation of main(), the code is almost unchanged. All you have to do is to replace array definitions by vector definitions:
...
vector<int> b(n); // creates a vector that is initialized with n elements.
...
vector<vector<int>> a(n,vector<int>(n)); // same idea for 2 dimensional vector (i.e. a vector of vectors)
vector<int> init_x(n), new_x(n); // same principle as for b
...

Sorting vector (c++)

I have to sort a vector N into M equals parts(M less than N).
But those equal parts have to be in the middle. If I have parts that are not equal i need to put them in the first and/or last element.Difference between first and last has to be minimal. I have managed to make a sort of that function. Function is making new vector(sizeof(M)) and inside stores number of parts from vector N.
ex. 10/7 vector M [1 1 2 2 2 1 1] 1+1+2+2+2+1+1=10 into 7 parts. Meaning I am taking n or n+1 objects for vector N and storing index in vector M. Values inside do not have to be equal.
Now I am having trouble because my deviations can only be first and last element.
And also i am having problems whit for
ex. 12/9 because i get M[1 1 1 2 2 2 1 1 1 ]
but if I can only have first and last as different
then it should be like M[3 1 1 1 1 1 1 1 2]
So my question : Is there any better way of making this?
#include "stdafx.h"
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
int N = 12; // size of vector
int M = 9; // numbers of divisions
static void subsizes(int vecSize, int subCount, vector<int> &v)
{
int baseSize = vecSize / subCount;
int bumps = vecSize % subCount;
int i,n=0,nPlus,counterPlus=0,counterN,counterLeft;
vector<int> temp(subCount); // for new results
vector<int> proba(subCount);
for (i = 0; i < subCount; i++) //dividing to n, n+1 and placing them in vector
{
temp[i]= baseSize + (i < bumps);
}
for (i=0; i<subCount; i++) // finding what numbers are n, n+1
{
nPlus=temp[i];
if(n==0 && n<nPlus){
n=nPlus;}
}
for(i=0; i<subCount;i++) //counting n, n+1
{
if(nPlus==temp[i])counterPlus++;
}
counterN=subCount-counterPlus;
counterLeft=counterPlus-2;
for(i=0; i<counterPlus/2; i++) //placing them in right order
temp[i]=nPlus;
for(i=counterPlus/2; i<counterPlus/2+counterN; i++)
temp[i]=n;
for(i=counterPlus/2+counterN; i<subCount; i++)
temp[i]=nPlus;
cout<<endl<<"Divided vector is :"<<endl; //printing results
for(i=0; i<subCount;i++)
{
int part = temp[i];
cout<<"At : vector["<<i<<"] nubmer of objects is --- "<<part<<endl;
}
putchar('\n');
}
int _tmain(int argc, _TCHAR* argv[])
{
vector<int> vec(N);
int vecSize = vec.size(); //length of original vector
int subCount=M; //number of sub-vectors parts
generate(vec.begin(), vec.end(), rand); // filling vector with C function rand()
cout<<"Vector is [ ";
for (auto i : vec) // printing out a vector
{
cout<<i<<" ";
}
cout<<"]"<<endl;
subsizes(vecSize,subCount,vec); // calling funciton that divideds and print results
system("PAUSE");
return 0;
}
You are complicating this, a lot.
If I understand you correctly
you want to take a vector of size N and divide it into M parts
Each of the M parts should have the same length
If there is remaining elements in N, you want to distribute the remainder to extra sub-parts at the beginning and end
Your output is a vector of the sizes of sub-parts
edit: it seems my assumption of "you want to distribute the remainder to extra sub-parts at the beginning and end" was wrong
If that is indeed what you want then you can just do this
void subsizes(int vecSize, int subCount, vector<int> &v)
{
int regular_size = (vecSize+2) / subCount;
int remainder = vecSize - regular_size * subCount;
vector<int> sizes(subCount, regular_size);
int front_remainder = remainder - (remainder / 2);
int back_remainder = remainder / 2;
sizes.front() += front_remainder;
sizes.back() += back_remainder;
for (int i = 0; i<sizes.size(); i++)
{
int part = sizes[i];
cout << "At : vector[" << i << "] nubmer of objects is --- " << part << endl;
}
putchar('\n');
}
I'm not sure I have a complete grip on your problem, but it appears that you are allowed to change the elements contained in vec. In which case, this is probably what you are looking for:
void subsizes(vector<int>& vec)
{
if(vec.size() > 1) // Don't do anything if there aren't at least 2 elements
{
// Get the sum of all the elements,
// but we're going to be adding back in 1s in every element but the last
// so subtract (vec.size() - 1) from this total.
// This is done by initializing accumulate to 1 - vec.size()
int last = accumulate(vec.begin(), vec.end(), 1 - vec.size());
// Now put 1s in all the elements
fill(vec.begin(), vec.end(), 1);
// Change the last element to the value accumulated in last
vec.back() = last;
}
}