给一个数组,一次操作能够将相邻两个元素互换,问最少多少次操作之后,能够使得数组奇偶相间。
首先我们考虑我们的目标序列该是什么样子,当我们在某个位置需要一个特定的奇数或者偶数时,我们肯定是拿最近的来填,所以我们按顺序将数组分成奇偶两个,然后从这两个数组中一边拿一个就构成了我们最终的目标序列。
当然,其中有一些细节,比如元素总数为偶数,我们需要考虑起始为奇数和偶数的情况,若元素总数为奇数,那么我们肯定是只能以更多的那个为起始,若奇数偶数之差大于等于2,则不存在目标序列。
那么现在的问题就变成了,从一个序列,到目标序列,最少需要多少次相邻交换,这个问题和逆序对数量是高度匹配的,所以我们提取目标序列的序号,然后求一遍逆序对,即为目标序列转换为原始序列的操作次数。
1 class Solution { 2 public: 3 vector<int> back; 4 int ans; 5 vector<int> make_v(vector<int> t1,vector<int> t2){ 6 vector<int> res; 7 int i=0,j=0; 8 while(i<t1.size()||j<t2.size()){ 9 if(i<t1.size()) res.push_back(t1[i++]); 10 if(j<t2.size()) res.push_back(t2[j++]); 11 } 12 return res; 13 } 14 15 //求逆序对数目,merge_sort 16 void get(vector<int>& q,int l,int r){ 17 if(l>=r) return ; 18 int mid=l+r>>1; 19 get(q,l,mid); 20 get(q,mid+1,r); 21 int i=l,j=mid+1,k=l; 22 while(i<=mid&&j<=r){ 23 if(q[i]<=q[j]) back[k++]=q[i++]; 24 else{ 25 back[k++]=q[j++]; 26 ans+=mid-i+1; 27 } 28 } 29 while(i<=mid) back[k++]=q[i++]; 30 while(j<=r) back[k++]=q[j++]; 31 for(int k=l;k<=r;k++){ 32 q[k]=back[k]; 33 } 34 } 35 int minSwaps(vector<int>& nums) { 36 int n=nums.size(); 37 back.resize(n); 38 vector<int> v0,v1; 39 for(int i=0;i<nums.size();i++){ 40 if(nums[i]%2==0) v0.push_back(i); 41 else v1.push_back(i); 42 } 43 int n0=v0.size(),n1=v1.size(); 44 if(abs(n0-n1)>=2) return -1; 45 int res=INT_MAX; 46 if(nums.size()%2==1){ 47 if(v0.size()<v1.size()) swap(v0,v1); 48 vector<int> t; 49 int i=0,j=0; 50 vector<int> v=make_v(v0,v1); 51 ans=0; 52 get(v,0,v.size()-1); 53 res=min(res,ans); 54 }else{ 55 vector<int> tmp1=make_v(v0,v1); 56 vector<int> tmp2=make_v(v1,v0); 57 ans=0; 58 get(tmp1,0,tmp1.size()-1); 59 res=min(res,ans); 60 61 ans=0; 62 get(tmp2,0,tmp2.size()-1); 63 res=min(res,ans); 64 } 65 return res; 66 } 67 };
给定坐标系上n个点,问底边与坐标轴平行的最大三角形面积是多少,为避免除以2,返回三角形面积的两倍。
三角形面积为底乘高,高可用min和max来维护,比如要求一个底与y轴平行,位于x=2的,底为base的三角形的最大面积,那么显然S=max(x-minx,maxx-x)*base。
那么我们需要维护三角形的底最大为多少即可。
1 typedef long long LL; 2 class Solution { 3 public: 4 long long maxArea(vector<vector<int>>& cor) { 5 int n=cor.size(); 6 if(n<3) return -1; 7 int minx=INT_MAX,maxx=INT_MIN; 8 int miny=INT_MAX,maxy=INT_MIN; 9 map<int,pair<int,int>> xg,yg;//xg[x]为当前x值下,最大的y值和最小的y值分别是多少 10 for(int i=0;i<n;i++){ 11 int x=cor[i][0],y=cor[i][1]; 12 minx=min(minx,x); 13 maxx=max(maxx,x); 14 miny=min(miny,y); 15 maxy=max(maxy,y); 16 if(!xg.count(x)) xg[x]={y,y}; 17 else{ 18 xg[x].first=min(xg[x].first,y); 19 xg[x].second=max(xg[x].second,y); 20 } 21 if(!yg.count(y)) yg[y]={x,x}; 22 else{ 23 yg[y].first=min(yg[y].first,x); 24 yg[y].second=max(yg[y].second,x); 25 } 26 } 27 LL ans=-1; 28 for(auto [x,yrange]:xg){ 29 LL base = yrange.second-yrange.first;//底边长 30 if(base==0) continue; 31 LL height = max(x-minx,maxx-x); 32 ans=max(ans,base*height); 33 } 34 for(auto [y,xrange]:yg){ 35 LL base = xrange.second-xrange.first; 36 if(base==0) continue; 37 LL height = max(y-miny,maxy-y); 38 ans=max(ans,base*height); 39 } 40 if(ans==0) return -1; 41 return ans; 42 } 43 };
给定一个数组,问有多少个子数组满足其中至少两个质数,而且最大的质数减去最小的质数小于等于k。
显然,当子数组的右端点右移时,左端点要不保持不动,要不跟着右移,所以可以用双指针来解决这个问题。
再维护当前子数组的最大质数和最小质数,即可O(1)判断小于等于k,再维护一个质数队列。
1 const int N = 5e4+10; 2 class Solution { 3 public: 4 vector<bool> primes; 5 void init(){ 6 primes.resize(N); 7 for(int i=2;i<N;i++){ 8 if(primes[i]==false) 9 for(int j=i+i;j<N;j+=i) 10 primes[j]=true; 11 } 12 } 13 bool isprime(int x){ 14 if(x<=1) return false; 15 return !primes[x]; 16 } 17 int primeSubarray(vector<int>& nums, int k) { 18 init(); 19 deque<int> maxx,minn,p; 20 int i=0; 21 int n=nums.size(); 22 int res=0; 23 for(int j=0;j<n;j++){ 24 if(isprime(nums[j])){ 25 while(!maxx.empty()&&nums[maxx.back()]<=nums[j]) maxx.pop_back(); 26 maxx.push_back(j); 27 while(!minn.empty()&&nums[minn.back()]>=nums[j]) minn.pop_back(); 28 minn.push_back(j); 29 p.push_back(j); 30 while(!maxx.empty()&&!minn.empty()&&i<=j&& 31 nums[maxx.front()]-nums[minn.front()]>k){ 32 i++; 33 while(!maxx.empty()&&maxx.front()<i) maxx.pop_front(); 34 while(!minn.empty()&&minn.front()<i) minn.pop_front(); 35 while(!p.empty()&&p.front()<i) p.pop_front(); 36 } 37 } 38 if(p.size()>=2){ 39 int t=p[p.size()-2]; 40 res+=t-i+1; 41 } 42 } 43 return res; 44 } 45 };
浙公网安备 33010602011771号