• leetcode周赛 227


    A:问能否将一个数组通过轮换的方式得到一个单调不减的数组。

    因为范围只有100,直接将数组拷贝并排序,然后对原数组轮换n次,每次进行一下判断。

     1 class Solution {
     2 public:
     3     bool check(vector<int>&a,vector<int>& b){
     4         int n=a.size();
     5         for(int i=0;i<n;i++){
     6             if(a[i]!=b[i]){
     7                 return false;
     8             }
     9         }
    10         return true;
    11     }
    12     bool check(vector<int>& nums) {
    13         int n=nums.size();
    14         vector<int> tmp=nums;
    15         sort(tmp.begin(),tmp.end());
    16         for(int i=0;i<n;i++){
    17             int t=tmp.back();
    18             tmp.pop_back();
    19             tmp.insert(tmp.begin(),t);
    20             if(check(tmp,nums)) return true;
    21         }
    22         return false;
    23     }
    24 };

    B:给定三堆石子,每次操作从其中两堆各拿走一个石子,获得价值1,问价值最大为多少。

    三堆石子数量分别为a,b,c。

    不妨设a<=b<=b。

      1.若a+b<=c,那么ans=a+b

      2.若a+b>c,那么必然可以消耗成两两之间的差小于等于1,即|a-b|<=1,|a-c|<=1,|b-c|<=1。

        而且可以发现,这种情况之后的都会一直保持上述性质。

        故最终答案为0,0,0或者0,0,1,1取决于石子总数的奇偶。

    1 class Solution {
    2 public:
    3     int maximumScore(int a, int b, int c) {
    4         int d[]={a,b,c};
    5         sort(d,d+3);
    6         if(d[0]+d[1]<=d[2]) return d[0]+d[1];
    7         else return (d[0]+d[1]+d[2])/2;
    8     }
    9 };

    C:给定两个字符串,每次操作选择其中一个串的首字符,放到res的末尾,问字典序最大的串是什么。

    原始写法:考试的时候想的是每次挑字典序大的字符,如果相同,就需要判断后面的字符的大小,假设A串为"ccbda",B串为"ccaza",那么我们应该先将A串的 ‘c’ 拿尽。

    根据这个思路,在每次A和B相同的时候就继续往后判断。

     1 class Solution {
     2 public:
     3     int finds(int i,int j,string& w1,string& w2){
     4         char c=w1[i];
     5         while(i<w1.size()&&j<w2.size()){
     6             if(w1[i]>w2[j]){
     7                 return 1;
     8             }else if(w1[i]<w2[j]){
     9                 return 2;
    10             }
    11             i++,j++;
    12         }
    13         while(i<w1.size()){
    14             if(w1[i]>c){
    15                 return 1;
    16             }else if(w1[i]<c){
    17                 return 2;
    18             }
    19             i++;
    20         }
    21         while(j<w2.size()){
    22             if(w2[j]>c){
    23                 return 2;
    24             }else if(w2[j]<c){
    25                 return 1;
    26             }
    27             j++;
    28         }
    29         return 1;
    30     }
    31     string largestMerge(string w1, string w2) {
    32         int i=0,j=0;
    33         string res="";
    34         while(i<w1.size()&&j<w2.size()){
    35             if(w1[i]>w2[j]){
    36                 res+=w1[i];
    37                 i++;
    38             }else if(w1[i]<w2[j]){
    39                 res+=w2[j];
    40                 j++;
    41             }else{
    42                 int t=finds(i,j,w1,w2);
    43                 if(t==1){
    44                     res+=w1[i];
    45                     i++;
    46                 }else{
    47                     res+=w2[j];
    48                     j++;
    49                 }
    50             }
    51         }
    52         while(i<w1.size()){
    53             res+=w1[i];
    54             i++;
    55         }
    56         while(j<w2.size()){
    57             res+=w2[j];
    58             j++;
    59         }
    60         return res;
    61     }
    62 };

    优化写法:如果两个串首字母相等,就比较往后的第一个不想的的字母的本质就是子串的比较。

        故可直接利用substr函数进行比较。

     1 class Solution {
     2 public:
     3     string largestMerge(string w1, string w2) {
     4         int i=0,j=0;
     5         string res="";
     6         while(i<w1.size()||j<w2.size()){
     7             if(w1.substr(i)>w2.substr(j)){
     8                 res+=w1[i++];
     9             }else{
    10                 res+=w2[j++];
    11             }
    12         }
    13         return res;
    14     }
    15 };

    D:给定一个长度为n的数组,从中选出一个子序列,其和记为sum,求|sum-goal|最小为多少,输出这个最小值。

    如果数组长度<20,那么就可以直接暴搜,时间复杂度为2^20=1e6

    如果要求的是最大和或者最小和,那么可以应用01背包的模型。

    而这个题数组长度为40,就需要用双向dfs来做。

    首先对前一半数组做一遍dfs,处理出全部的的和,再排序。

    对于后半部分的数组同样进行dfs,到终点时,利用二分找到和小于goal的最大值和大于goal的最小值。

     1 const int N=1e7;
     2 int q[N];
     3 class Solution {
     4 public:
     5     int cnt,res,n,goal;
     6     void dfs1(vector<int>& nums,int u,int s){
     7         if(u==(n+1)/2){
     8             q[cnt++]=s;
     9             return ;
    10         }
    11         dfs1(nums,u+1,s);
    12         dfs1(nums,u+1,s+nums[u]);
    13     }
    14     void dfs2(vector<int>&nums,int u,int s){
    15         if(u==n){
    16             int l=0,r=cnt-1;
    17             while(l<r){
    18                 int mid=l+r+1>>1;
    19                 if(q[mid]+s<=goal) l=mid;
    20                 else r=mid-1;
    21             }
    22             res=min(res,abs(q[r]+s-goal));
    23             if(r+1<cnt){
    24                 res=min(res,abs(q[r+1]+s-goal));
    25             }
    26             return ;
    27         }
    28         dfs2(nums,u+1,s);
    29         dfs2(nums,u+1,s+nums[u]);
    30     }
    31     int minAbsDifference(vector<int>& nums, int _goal) {
    32         n=nums.size();
    33         goal=_goal;
    34         res=INT_MAX;
    35         dfs1(nums,0,0);
    36         sort(q,q+cnt);
    37         dfs2(nums,(n+1)/2,0);
    38         return res;
    39     }
    40 };

    时间复杂度为1e6 + 1e6*log(1e6) + 1e6*log(1e6) 。

  • 相关阅读:
    Symfony2 多bundle及实体获取,app_dev及app下调试
    Symfony2 WebService(一) 配置篇
    Symfony2 数据调用常用方法
    Symfony2 配置自己的log日志、使用配置文件定义全局常量
    Symfony2 环境及基本命令
    Asterisk拨号函数Dial()详解
    C语言系统资源控制(getrlimit && setrlimit)
    centos FTP服务器的架设和配置
    MYSQL远程登录权限设置
    SIP keepalive方法
  • 原文地址:https://www.cnblogs.com/greenofyu/p/14407559.html
Copyright © 2020-2023  润新知