A:水题,求数组中只出现一次的元素的和。
1 class Solution { 2 public: 3 int sumOfUnique(vector<int>& nums) { 4 unordered_map<int,int> m; 5 for(auto x:nums){ 6 m[x]++; 7 } 8 int res=0; 9 for(auto x:m){ 10 if(x.second==1){ 11 res+=x.first; 12 } 13 } 14 return res; 15 } 16 };
B:找出子数组和的绝对值的最大值。
解法一:应用求最大子数组的双指针模型。
最终的答案要么是正数(非常大),要么是负数(非常小),应用两遍求最大子数组的双指针模型就可以求出答案。
1 class Solution { 2 public: 3 int maxAbsoluteSum(vector<int>& nums) { 4 int n=nums.size(); 5 int l=0,r=0; 6 int sum=0,res=0; 7 while(r<n){ 8 sum+=nums[r]; 9 r++; 10 while(sum<0){ 11 sum-=nums[l]; 12 l++; 13 } 14 res=max(res,sum); 15 } 16 l=0,r=0; 17 sum=0; 18 while(r<n){ 19 sum+=nums[r]; 20 r++; 21 while(sum>0){ 22 sum-=nums[l]; 23 l++; 24 } 25 res=max(res,-sum); 26 } 27 28 return res; 29 } 30 };
解法二:利用前缀和
如果将原数组前缀和之后的话,就只需要枚举左右端点,但是时间上还是过不去。
然后发现如果此时我们求子数组最大值,那么对于每一个右端点i,我们需要知道的是1~i-1中的最小值。
如果求子数组的最小值,那么对于每一个右端点i,我们需要知道的是1~i-1中的最大值。
所以在前缀后之后,维护max_val,min_val就可以了。
1 class Solution { 2 public: 3 int maxAbsoluteSum(vector<int>& nums) { 4 int n=nums.size(); 5 vector<int> s(n+1); 6 for(int i=1;i<=n;i++){ 7 s[i]=s[i-1]+nums[i-1]; 8 } 9 int max_val=0,min_val=0;//初始化为0是因为要求的是abs,所以不能初始化为无穷 10 //而初始化为0正好满足选择空数组的情况 11 int res=0;//初始状态就是选择空数组 12 for(int i=1;i<=n;i++){ 13 res=max(res,abs(s[i]-max_val)); 14 res=max(res,abs(s[i]-min_val)); 15 max_val=max(max_val,s[i]); 16 min_val=min(min_val,s[i]); 17 } 18 return res; 19 } 20 };
C:给定一个字符串,若左端点==右端点,那么可以将左边和右边大于一个的字符删除。求删除后的最短长度。
证明:如果删的话,一定尽可能地全部删掉。
假设两边都不删完,那么下一次还是得删,所以不如删完。
假设其中一边不删完,不妨设是左边,那么删完之后的字符串必定左端点不等于右端点,不如删完。
所以每次如果左端点等于右端点的话,直接删完就好了。
考试的时候的代码:
1 class Solution { 2 public: 3 int minimumLength(string s) { 4 int begin=0,end=s.size()-1; 5 while(s[begin]==s[end]&&begin<end){ 6 int l=begin,r=end; 7 while(l<=end&&s[l]==s[begin]) l++; 8 while(r>=begin&&s[r]==s[end]) r--; 9 if(l>r) return 0; 10 begin=l,end=r; 11 } 12 return end-begin+1; 13 } 14 };
更简洁的代码:
1 class Solution { 2 public: 3 int minimumLength(string s) { 4 int i=0,j=s.size()-1; 5 while(i<j){ 6 if(s[i]!=s[j]) break; 7 char c=s[i]; 8 while(i<=j&&s[i]==c) i++; 9 while(i<=j&&s[j]==c) j--; 10 } 11 return j-i+1; 12 } 13 };
D:给定n个区间,每个区间有一个价值,选择k个不相交的价值最大的区间,返回最大价值。
因为计算f [ i ] [ j ]的时候,需要找到右端点小于i左端点的最右边的那个区间。
所以我们可以将区间按照右端点排序,然后利用二分来寻找该区间。
这样的话时间复杂度为n*k*log n
1 const int N=1e6+10; 2 struct Q{ 3 int s,e,v; 4 bool operator<(const Q& t){ 5 return e<t.e; 6 } 7 }q[N]; 8 class Solution { 9 public: 10 int maxValue(vector<vector<int>>& events, int k) { 11 int n=events.size(); 12 vector<vector<int>> f(n+1,vector<int>(k+1)); 13 for(int i=1;i<=n;i++){ 14 q[i]={events[i-1][0],events[i-1][1],events[i-1][2]}; 15 } 16 sort(q+1,q+1+n); 17 for(int i=1;i<=n;i++){ 18 for(int j=1;j<=k;j++){ 19 f[i][j]=f[i-1][j];//不选第i个 20 int l=0,r=i-1; 21 while(l<r){ 22 int mid=l+r+1>>1; 23 if(q[mid].e<q[i].s) l=mid; 24 else r=mid-1; 25 } 26 f[i][j]=max(f[i][j] , f[r][j-1]+q[i].v); 27 } 28 } 29 return f[n][k]; 30 } 31 };
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
2020-02-09 P2921 在农场万圣节(非递归的类似于记忆化搜索的巧妙方法||记忆化搜索||tarjan)