我需要k在两个排序的数组中找到最大的元素,但要有所不同。
k
该算法假设k<=max(m,n),索引在时出错k>max(m,n)。在我的问题中,我知道这将一直存在k>(m+n)/2,因此k>min(m,n)我需要稍微改变JulesOlléon的答案…我只是看不到哪一点:〜
k<=max(m,n)
k>max(m,n)
k>(m+n)/2
k>min(m,n)
我在第3页找到了此链接,但是那里存在bug(实施后,它不会返回正确的答案)
我知道一个快速的解决方法是将两个数组都乘以-1,然后取最小的那个联合的k,然后再将答案乘以-1,但这会使代码不可读。
这 不是 功课。
好的,我想我误会了尼尔的答案或其他原因,因为这就是我给“他”的意思
#include <algorithm> #include <fstream> #include <iostream> #include <stdio.h> #include <stdlib.h> #include <time.h> #include <vector> #include <Eigen/Dense> using namespace Eigen; using Eigen::VectorXf; using Eigen::VectorXi; float getNth(VectorXf& v1,VectorXf& v2,int& n){ int step=(n/4),i1=(n/2),i2=(n-i1); while(!(v2(i2)>=v1(i1-1) && v1(i1)>v2(i2-1))){ if(v1(i1-1)>=v2(i2-1)){ i1-=step; i2+=step; } else { i1+=step; i2-=step; } step/=2; if(!step) step=1; } if(v1(i1-1)>=v2(i2-1)) return v1(i1-1); else return v2(i2-1); } int main(){ int p,q,n,k,l; float sol; std:: cout << "enter p " << std::endl; std::cin >> p; std:: cout << "enter q " << std::endl; std::cin >> q; n=p+q; std:: cout << " enter k larger than " << std::min(p,q) << " and smaller than " << n-1 << std::endl; std::cin >> k; k=n-k-1; srand(time(NULL)); VectorXf v1=VectorXf::Random(p); srand(time(NULL)); VectorXf v2=VectorXf::Random(q); VectorXf v3(n); v3 << v1, v2; std::sort(v3.data(),v3.data()+v3.size(),std::greater<float>()); //std::greater<float>() std::sort(v1.data(),v1.data()+v1.size(),std::greater<float>()); std::sort(v2.data(),v2.data()+v2.size(),std::greater<float>()); sol=getNth(v1,v2,k); std::cout << sol << std::endl; std::cout << v3(k) << std::endl; return 0; }
这就是我得到的:
enter p 12 enter q 32 enter k larger than 12 and smaller than 43 13 nthoftwo: /Desktop/work/p1/geqw4/vi3/out/sp/ccode/eigen/Eigen/src/Core/DenseCoeffsBase.h:409: Eigen::DenseCoeffsBase<Derived, 1>::Scalar& Eigen::DenseCoeffsBase<Derived, 1>::operator()(Eigen::DenseCoeffsBase<Derived, 1>::Index) [with Derived = Eigen::Matrix<float, -0x00000000000000001, 1>, Eigen::DenseCoeffsBase<Derived, 1>::Scalar = float, Eigen::DenseCoeffsBase<Derived, 1>::Index = long int]: Assertion `index >= 0 && index < size()' failed. Aborted (core dumped)
如果您不熟悉本征:错误是由以下原因引起的索引超出范围错误 getNth(v1,v2,k)
getNth(v1,v2,k)
这是对JF Sebastian下面简单而优雅的解决方案的一个很小的修改-所有错误都是我的,但似乎可行。目的是使用原始索引(即,我不确定尼尔的想法必不可少)。
#include <algorithm> #include <fstream> #include <iostream> #include <stdio.h> #include <stdlib.h> #include <time.h> #include <vector> #include <cassert> #include <iterator> #include <Eigen/Dense> using namespace Eigen; using Eigen::VectorXf; using Eigen::VectorXi; template<class RandomIterator,class Compare> typename std::iterator_traits<RandomIterator>::value_type nsmallest(RandomIterator firsta,RandomIterator lasta,RandomIterator firstb,RandomIterator lastb,size_t n,Compare less) { assert(n<static_cast<size_t>((lasta-firsta)+(lastb-firstb))); if (firsta==lasta) return *(firstb+n); if (firstb==lastb) return *(firsta+n); size_t mida=(lasta-firsta)/2; size_t midb=(lastb-firstb)/2; if ((mida+midb)<n) return less(*(firstb+midb),*(firsta+mida))? nsmallest(firsta,lasta,firstb+midb+1,lastb,n-(midb+1),less): nsmallest(firsta+mida+1,lasta,firstb,lastb,n-(mida+1),less); else return less(*(firstb+midb),*(firsta+mida))? nsmallest(firsta,firsta+mida,firstb,lastb,n,less): nsmallest(firsta,lasta,firstb,firstb+midb,n,less); } int main(){ int p,q,n,k,l; float sol; std:: cout << "enter p " << std::endl; std::cin >> p; std:: cout << "enter q " << std::endl; std::cin >> q; n=p+q; std:: cout << " enter k larger than " << std::min(p,q) << " and smaller than " << n-1 << std::endl; std::cin >> k; srand(time(NULL)); VectorXf v1=VectorXf::Random(p); srand(time(NULL)); VectorXf v2=VectorXf::Random(q); VectorXf v3(n); v3 << v1, v2; std::sort(v3.data(),v3.data()+v3.size()); std::sort(v1.data(),v1.data()+v1.size()); std::sort(v2.data(),v2.data()+v2.size()); sol=nsmallest(v1.data(),v1.data()+v1.size(),v2.data(),v2.data()+v2.size(),k,std::less<float>()); //if it works, these two should return the same. std::cout << sol << std::endl; std::cout << v3(k) << std::endl; return 0; }
从您的评论中我了解到,您想找到给定2个反向排序数组的第k个最小值,例如for a={5,4,3}, b={2,1,0};和k=1,预期结果就是0最小值-第一个最小值(表示k从算起1)。
a={5,4,3}, b={2,1,0};
k=1
0
1
给定的nsmallest()函数可用于排序数组并接受自定义比较器,您可以:
nsmallest()
#include <functional> // greater<> #include <iostream> #define SIZE(a) (sizeof(a) / sizeof(*a)) int main() { int a[] = {5,4,3}; int b[] = {2,1,0}; int k = 1; // find minimum value, the 1st smallest value in a,b int i = k - 1; // convert to zero-based indexing int v = nsmallest(a, a + SIZE(a), b, b + SIZE(b), SIZE(a)+SIZE(b)-1-i, std::greater<int>()); std::cout << v << std::endl; // -> 0 return v; }
我已经使用@Neil的建议来修复索引和@lambdapilgrim对于算法的答案:
#include <cassert> #include <iterator> template<class RandomIterator, class Compare> typename std::iterator_traits<RandomIterator>::value_type nsmallest(RandomIterator firsta, RandomIterator lasta, RandomIterator firstb, RandomIterator lastb, size_t n, Compare less) { assert(n < static_cast<size_t>((lasta - firsta) + (lastb - firstb))); if (firsta == lasta) return *(firstb + n); if (firstb == lastb) return *(firsta + n); size_t mida = (lasta - firsta) / 2; size_t midb = (lastb - firstb) / 2; if ((mida + midb) < n) return less(*(firstb + midb), *(firsta + mida)) ? nsmallest(firsta, lasta, firstb + midb + 1, lastb, n - (midb + 1), less) : nsmallest(firsta + mida + 1, lasta, firstb, lastb, n - (mida + 1), less); else return less(*(firstb + midb), *(firsta + mida)) ? nsmallest(firsta, firsta + mida, firstb, lastb, n, less) : nsmallest(firsta, lasta, firstb, firstb + midb, n, less); }