min difference between two unsorted arrays - c++

I have to find min absolute difference between two elements of unsorted arrays.
My approach is to first sort both the array, run a loop over one array and find lower bound of each element of this array in another array.
And then check whether it is minimum or not and store it for further comparisons
Test Case:
2
8 1 3 5 7 9 7 3 1
8 2 4 6 8 10 8 6 2
8 2 3 5 10 9 3 2 1
7 1 2 6 12 13 3 2
Output :
1
0
result : passed
Explanation:
1) min will be abs(a[7]-b[7])
2) min will be abs(a[0]-b[(1)])
But when i am submitting to spoj I am getting wrong answer ,it look like I am missing some thing else .
problem https://www.spoj.com/problems/ACPC11B/
Please help where I am doing wrong?
My code:
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
vector <int> a;
vector <int> b;
int main(){
int t;
cin>>t;
while(t--){
int na;
cin>>na;
for(int i=0;i<na;i++){
int temp;
cin>>temp;
a.push_back(temp);
}
int nb;
cin>>nb;
for(int i=0;i<nb;i++){
int temp;
cin>>temp;
b.push_back(temp);
}
sort(a.begin(),a.end());
sort(b.begin(),b.end());
int ans=a[0]-b[0];
for(int i=0;i<a.size();i++){
int bval = lower_bound(b.begin(),b.end(),a[i])-b.begin();
ans = min(ans,abs(a[i]-b[bval]));
if(bval>0)
ans = min(ans,abs(a[i]-b[bval-1]));
}
cout<<ans<<endl;
a.clear();
b.clear();
}
}

Your version has several issues:
a[0]-b[0] which might be negative, invalidating remaining computation.
lower_bound which might result in b.end() leading to out of bound access.
You can do something like the following:
std::size_t min_distance(std::vector<int> v1, std::vector<int> v2)
{
std::sort(v1.begin(), v1.end());
std::sort(v2.begin(), v2.end());
auto it1 = v1.begin();
auto it2 = v2.begin();
auto min = std::abs(*it1 - *it2);
while (min != 0 && it1 != v1.end() && it2 != v2.end()) {
min = std::min(min, std::abs(*it1 - *it2));
if (*it1 < *it2) {
++it1;
} else /*if (*it2 <= *it1)*/ {
++it2;
}
}
return min;
}
Demo

Related

Why does my algorthim for insertion sort return different values , when I use the same value in condition statement?

# At first case I put the temp variable to condition statement in while loop#
int tab[8]={0,1,7,8,7,6,5,2};
int n=8;
int j;
int temp;
for(int i=1;i<n;i++)
{
temp=tab[i];
j=i-1;
while(j>=0&&tab[j]>temp)
{
tab[j+1]=tab[j];
--j;
}
tab[j+1] = temp;
}
And the resault that I get is :
0 1 7 8 7 6 5 2
0 1 2 5 6 7 7 8
But on the other hand when instead I use tab[i] in condition statement in while loop
for(int i=1;i<n;i++)
{
temp=tab[i];
j=i-1;
while(j>=0&&tab[j]>tab[i])
{
tab[j+1]=tab[j];
--j;
}
tab[j+1] = temp;
}
I get this result:
0 1 7 8 7 6 5 2
0 1 7 7 6 5 2 8
And I can't find any difference between passing these values and why it behaves like that.
I think that I am using the same values.
It's mine first question on that page , be kind to me please, have a nice day
Because in first iteration of while loop if tab[j] > tab[i]
tab[j+1]=tab[j]; changes tab[i] to tab[i - 1],
So essentially your whole program in second case is equivalent to this
#include <iostream>
int main ()
{
int tab[8]={0,1,7,8,7,6,5,2};
int n=8;
int j;
int temp;
for(int i=1;i<n;i++)
{
temp=tab[i];
j=i-1;
if (tab[j]>tab[i])
{
tab[j+1]=tab[j];
--j;
}
tab[j+1] = temp;
}
for(auto&& a: tab) {
std::cout << a << " ";
}
}

set_difference not always returns the right answer

I am currently working on an evolutionary algorithm. I write a program to implement the crossover function, i.e., exchange k elements between vectors A and B. Here is the code:
#include <algorithm>
#include <cstdio>
#include <ctime>
#include <iostream>
#include <iterator>
#include <random>
#include <set>
#include <vector>
using namespace std;
vector<int> reservoir_sampling(vector<int> input, int k)
{
vector<int> output(k);
int i;
for (i = 0; i < k; i++)
{
output[i] = input[i];
}
srand(time(nullptr));
while(i < input.size())
{
int j = rand() % (i+1);
if (j < k)
{
output[j] = input[i];
}
i++;
}
return output;
}
template<typename T>
void vprintf(vector<T> V)
{
for (T v : V)
{
cout << v << " ";
}
cout << endl;
}
void test()
{
// crossover between A and B at k points
vector<int> A = {0, 1, 2, 3, 4, 5};
vector<int> B = {6, 7, 8, 9};
printf("A: ");
vprintf(A);
printf("B: ");
vprintf(B);
int k = 2;
vector<int> outers = reservoir_sampling(A, k);
vector<int> inners = reservoir_sampling(B, k);
printf("outers: ");
vprintf(outers);
printf("inners: ");
vprintf(inners);
// uS = A + inners
vector<int> uS;
set_union(A.begin(), A.end(), inners.begin(), inners.end(), inserter(uS, uS.end()));
sort(uS.begin(), uS.end());
printf("uS = A + inners: ");
vprintf(uS);
// dS = uS - outers
vector<int> dS;
set_difference(uS.begin(), uS.end(), outers.begin(), outers.end(), inserter(dS, dS.end()));
sort(dS.begin(), dS.end());
printf("dS = uS - outers: ");
vprintf(dS);
}
int main()
{
test();
return 0;
}
Sometimes, the output is right, like:
A: 0 1 2 3 4 5
B: 6 7 8 9
outers: 3 4
inners: 9 7
uS = A + inners: 0 1 2 3 4 5 7 9
dS = uS - outers: 0 1 2 5 7 9
Sometimes, the output is not right, like:
A: 0 1 2 3 4 5
B: 6 7 8 9
outers: 3 1
inners: 9 7
uS = A + inners: 0 1 2 3 4 5 7 9
dS = uS - outers: 0 1 2 4 5 7 9
It turns out set_union is always OK, but set_difference is not. I don't have any clue where I am wrong. Almighty users of SO, please help me out!
You violate the preconditions of std::set_union and std::set_difference:
Constructs a sorted union beginning at d_first consisting of the set of elements present in one or both sorted ranges [first1, last1) and [first2, last2).
Copies the elements from the sorted range [first1, last1) which are not found in the sorted range [first2, last2) to the range beginning at d_first.
The reservoir_sampling function does not produce a sorted vector in the general case. The behaviour of your program is undefined.
The standard library provides std::sample function for random sampling. It preserves the relative order of selected elements if you give it a pair of forward or random access iterators.
template<typename T>
std::vector<T> sampling(const std::vector<T>& input, std::size_t k) {
std::vector<T> output;
output.reserve(k);
std::sample(input.begin(), input.end(), std::back_inserter(output),
k, std::mt19937{std::random_device{}()});
// the relative order of elements in output is the same as in input
return output;
}

Program Aborts when using vector iterators

Can somebody tell me what is the problem with this program?
The idea is to display "Yes" if the vector array satisfies all these criteria:
The array elements are not sorted in ascending order.
The array contains distinct elements.
All the array elements should have a value between 1 to n inclusive.
Otherwise "No".
The program aborts when it reaches the line at if(bSort).
Is there anything wrong with the iterator increment?
#include <iostream>
#include <string>
#include <bits/stdc++.h>
using namespace std;
std::string solve(vector <int> &a, int n) {
vector<int> visited (n);
int i=0;
for(std::vector<int>::iterator it = a.begin(); it != a.end(); ++it) {
i++;
if((it+1)!=a.end() && (*it > *(it+1)))
{
bSort = false;
}
if(std::find(visited.begin(), visited.end(), *it)!=visited.end())
{
return "No";
}
else
{
visited[i] = *it;
}
if(*it <= 0 || *it > n)
{
return "No";
}
}
if(bSort)
return "No";
else
return "Yes";
}
int main() {
int q;
cin >> q;
for(int a0 = 0; a0 < q; a0++){
int n;
cin >> n;
vector<int> a(n);
for(int a_i = 0; a_i < n; a_i++){
cin >> a[a_i];
}
std::string result = solve(a,n);
cout << result << endl;
}
return 0;
}
The issue appears to be happening only with the following input:
1
30
18 8 24 20 7 17 5 9 26 21 25 12 11 15 30 13 19 16 22 10 14 1 3 29 23 2 6 28 4 27
I'm not sure the problem has to do with iterators specifically.
At the very beginning of the loop, variable i is incremented before it's used, which means the set of numbers that i will range between is [1, vector.size()]. This means that at some point, you'll access vector[vector.size()], which is undefined behavior and can crash your program.
In your program specifically, given the input you provided, because none of the numbers in your example code are duplicated, the else branch of the std::find(...) conditional statement is always executed, which means you end up calling visited[30] at some point, which again, is out of bounds and undefined behavior, potentially causing a crash.

checking if given vector contains already elements of pair in c++

let us suppose have following pairs
0 -1
0 -2
0 -3
1- 2
2 -3
3- 4
2 -4
4- 5
5 -6
i would like to insert those pairs into vector , so that i should have each element only one times , for instance
start with empty vector :
0-1 is inserted
now we are checking 0-2 , there exist 0, but not 2, so 0-2 is inserted, we have
0-1
0-2
now 0-3 , 3 is not in the list, so we can insert
0-1
0-2
0-3
now lets us consider 1-2 , of course we have both of them , so skip, now let us consider 2-3, again we can skip, 3-4 , 3 exist but not 4, so we can insert
3-4 , after inserting of 4 , 4 also exist,so reject 2-4 then comes 4-5 and 5-6, so we have following list
0-1
0-2
0-3
3-4
4-5
5-6
i have following code
#include<iostream>
#include<vector>
#include<set>
#include<algorithm>
using namespace std;
struct edge
{
int a, c;
float weight;//edge a-c has weight
bool operator() (edge x, edge y)
{
x.weight < y.weight;
}
};
int noncyclical_sum(vector<edge>s)
{
int total = 0;
std::vector<std::pair<int, int>> b;
auto m = make_pair(s[0].a, s[0].c);
b.push_back(m);
total = total + s[0].weight;
vector<edge>::iterator it;
for (int i = 1; i < s.size(); i++)
{
auto m = make_pair(s[i].a, s[i].c);
//if (find(b.begin(), b.end(), s[i].a) != b.end() && find(b.begin(), b.end(), s[i].c) != b.end())
if (find(b.begin(), b.end(), m.first) != b.end() && find(b.begin(), b.end(), m.second) != b.end())
{
continue; //both element is in the vector
}
else
{
b.push_back(m);
total = total + s[i].weight;
}
std::vector<std::pair<int, int>>::iterator ii;
for (ii = b.begin(); ii != b.end(); ii++)
cout << ii->first << " " << ii->second;
}
}
int main()
{
return 0;
}
at first time , i have pushed first pair, starting from the second one, i am checking if at the same time both element is in vector, i am rejecting pairs and continue, otherwise i push new pairs and continuing , but i have following error
Severity Code Description Project File Line Suppression State
Error C2678 binary '==': no operator found which takes a left-hand operand of type 'std::pair<int,int>' (or there is no acceptable conversion) kurskal_algorithm c:\program files (x86)\microsoft visual studio\2017\enterprise\vc\tools\msvc\14.10.25017\include\xutility 3161
what is wrong ? thanks in advance
The problem is in this line:
if (find(b.begin(), b.end(), m.first) != b.end() && find(b.begin(), b.end(), m.second) != b.end())
Let's check the arguments of std::find call: b.begin() and b.end() are std::vector<std::pair<int, int>>::iterators while m.first is int.
So, you're trying to find int in the vector of pairs. You can't do that.
Also, all of your functions lack the required return statements.

C++: St9bad_alloc failure for small Input

I built a program for converting a multigraph into undirected graph with multiple edges and self loops removed using adjacency-list as Graph representation.
`
#include<iostream>
#include<istream>
#include<algorithm>
#include<list>
using namespace std;
int main()
{
list<int> adj[3];
list<int> auxArray[3];
list<int> adjnew[3];
cout<<adjnew[2].back()<<endl; // Gives output 0, whereas it should have some garbage
//value
for(int i = 0;i<3;i++){
int x;
while(true){ // reading a line of integers until new line is encountered , peek()
returns the next input character without extracting it.
cin>>x;
adj[i].push_back(x);
auxArray[i].push_back(x);
if(cin.peek() == '\n') break;
}
}
//flatten the adj-list
for(int i = 0;i<3;i++){
list<int>::iterator it = adj[i].begin();
while(it != adj[i].end()){
auxArray[*it].push_back(i);
it++;
}
}
for(int i = 0;i<3;i++){
list<int>::iterator it = auxArray[i].begin();
while(it != auxArray[i].end()){
//cout<<*it<<" "<<adjNew[*it].back()<<endl;
if((*it != i) && ((adjnew[*it].back()) != i)){
// cout<<*it<<" -> "<<i<<endl;
adjnew[*it].push_back(i);
}
it++;
}
}
for(int i = 0;i<3;i++){
list<int>::iterator it = adjnew[i].begin();
while(it != adjnew[i].end()){
cout<<*it<<" ";
it++;
}
cout<<endl;
}
return 0;
}
`
But it shows St9bad_alloc error whereas my list has size of just 3.
Also, adjnew[2].back() is assigned to "0" without being initialized, whereas it should have some garbage value.
'
Input:
1 2 1
0
1 1
Output of Program(Incorrect because of 0 as back element in adjnew[2]):
1 2
0 2
1
Correct Output:
1 2
0 2
0 1
'
All suggestions are welcomed!
The
cout<<adjnew[2].back()<<endl;
at begin is plain undefined behavior on an empty container.
valgrind gives
Conditional jump or move depends on uninitialised value(s)
for this line:
if ((*it != i) && ((adjnew[*it].back()) != i))
Again an undefined behavior on an empty container.
Hint: You could use container.at() instead of operator [] to have a range check.