A:3852. 不同频率的最小数对
给定一个数组,要求这个数组中频率不同的最小的两个数。
这个数组中的min是必选的,可由反证法证。假设ans=[a,b],二者都不为min,且freq(a)!=freq(b),那么一定可以将其中一个数替换为min,同样满足频率不同。
必须min,那么O(n)找另一个数即可。
1 class Solution { 2 public: 3 vector<int> minDistinctFreqPair(vector<int>& nums) { 4 int minn=*min_element(nums.begin(),nums.end()); 5 map<int,int> cnt; 6 for(int x:nums) 7 cnt[x]++; 8 for(auto [k,v]:cnt){ 9 if(v!=cnt[minn]){ 10 return {minn,k}; 11 } 12 } 13 return {-1,-1}; 14 } 15 };
合并距离小于等于k的相同字符,合并之后,会改变原有的字符串。
1 class Solution { 2 public: 3 string mergeCharacters(string s, int k) { 4 string ans=""; 5 map<char,int> last; 6 //ans.size()表示当前s[i]放到的位置 7 for(int i=0;i<s.size();i++){ 8 if(!last.count(s[i])||ans.size()-last[s[i]]>k){ 9 last[s[i]]=ans.size(); 10 ans+=s[i]; 11 } 12 } 13 return ans; 14 } 15 };
C:3854. 使数组奇偶交替的最少操作
问题分两问,首先问多少次操作能够使得数组变为奇偶交替,这一问比较简单,可以直接确定第一个元素的奇偶,然后O(n)比对即可。
第二问问在第一问的操作下,最小的max-min的值为多少,我们可以将一个可以改的元素x,看成x-1和x+1的列表,然后排序,找出最小的区间覆盖全部元素,具体可见力扣632题。
1 typedef pair<int,int> PII; 2 class Solution { 3 public: 4 vector<int> fun(int mode,vector<int>& nums){ 5 int n=nums.size(); 6 int ans1=0; 7 vector<PII> v; 8 //第一问,同时处理好第二问的数据 9 for(int i=0;i<n;i++){ 10 if((nums[i]&1)!=mode){ 11 ans1++; 12 v.push_back({nums[i]-1,i}); 13 v.push_back({nums[i]+1,i}); 14 }else{ 15 v.push_back({nums[i],i}); 16 } 17 mode^=1; 18 } 19 20 //第二问 21 sort(v.begin(),v.end()); 22 int empty=n; 23 int l=0; 24 int ans2=INT_MAX; 25 vector<int> cnt(n,0); 26 for(int r=0;r<v.size();r++){ 27 int val=v[r].first,id=v[r].second; 28 if(cnt[id]==0){ 29 empty--; 30 } 31 cnt[id]++; 32 while(empty==0){ 33 ans2=min(ans2,val-v[l].first); 34 if(cnt[v[l].second]==1) 35 empty++; 36 cnt[v[l].second]--; 37 l++; 38 } 39 } 40 return {ans1,ans2}; 41 } 42 vector<int> makeParityAlternating(vector<int>& nums) { 43 vector<int> a=fun(0,nums); 44 vector<int> b=fun(1,nums); 45 if(a[0]==b[0]) 46 return {a[0],min(a[1],b[1])}; 47 else if(a[0]<b[0]) 48 return a; 49 else 50 return b; 51 } 52 };
D:3855. 给定范围内 K 位数字之和
要求L-R的数字组合出的所有k位数字的和,可用贡献法。
设k为数的从低位数的第i位数为x,那么有一个这个的贡献即为x*10i,再乘以有多少个k为数即可求出这一位数字为x的贡献,其他位并无限制,所以有(r-l+1)k-1个。
所以这一位的贡献为∑∑(x*10i)*(r-l+1)k-1,两个求和分别对x和i,x的值为L~R,用等差数列求和,i的值为0~k-1,用等比数列求和。
可得ans=1/18 * (L+R)*(R-L+1)k*(10k-1),此处为模,需要求逆元,1e9+7为素数,所以可用费马小定理。
1 const int mod=1e9+7; 2 class Solution { 3 public: 4 int ksm(int a,int b){ 5 int res=1; 6 while(b){ 7 if(b&1) 8 res=1ll*res*a%mod; 9 a=1ll*a*a%mod; 10 b>>=1; 11 } 12 return res; 13 } 14 int sumOfNumbers(int l, int r, int k) { 15 return 1ll*ksm(18,mod-2)*(l+r)%mod*ksm(r-l+1,k)%mod*(ksm(10,k)-1)%mod; 16 } 17 };
浙公网安备 33010602011771号