1.微扰理论二分法
class Solution { struct cmp { bool operator() (const vector<int> &a,const vector<int> &b) { if(a[0]+a[1] == b[0]+b[1]){ return a[1] > b[1]; }else{ return a[0]+a[1] > b[0]+b[1]; } } }; public: vector<vector<int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) { vector<vector<int>> ret; priority_queue <vector<int>,vector<vector<int>>,cmp > q; int len1=nums1.size(),len2=nums2.size(); long long left=long(nums1[0])+long(nums2[0]), right=((long(nums1[len1-1])-long(nums1[0]))/len1+(long(nums2[len2-1])-long(nums2[0]))/len2+(long(nums1[0])+long(nums2[0]))/k)/2*k, mid=0; int cnt=0,j=0; vector<int> vp; //cout<<len1<<":"<<len2<<endl; //k超过最大范围直接输出 if(k>=len1*len2){ for(int i=0;i<len1;i++){ j=0; while(j<len2){ vp={nums1[i], nums2[j]}; q.push(vp); j++; } } while(k&&!q.empty()){ k--; ret.push_back(q.top()); q.pop(); } return ret; } if(left>=right){ left=right; } int last=0; //cout<<left<<":"<<right<<endl; while(left <= right){ mid=left + (right-left)/2; cnt=0; for(int i=0;i<len1;i++){ j=0; while(j<len2&&(nums1[i]+nums2[j])<=mid)j++; cnt+=j; if(j==0){ break; } } //cout<<cnt<<endl; if(cnt==k||(cnt>k&&last<k)){ for(int i=0;i<len1;i++){ j=0; while(j<len2&&(nums1[i]+nums2[j])<=mid){ vp={nums1[i], nums2[j]}; q.push(vp); //q.emplace(nums1[i], nums2[j]); //cnt++; j++; } if(j==0){ break; } } while(k&&!q.empty()){ k--; ret.push_back(q.top()); q.pop(); } return ret; } if(left==right&&last<=k){ right+=right/2+1; } last=cnt; //二分搜索操作 if (cnt < k) left = mid+1; else right = mid; //cout<<"last:"<<last<<"left:"<<left<<"right:"<<right<<"mid:"<<mid<<endl; } return ret; } };