第三次周赛 总结:是的,我在进步中。。。

Posted 诚威_lol_中大努力中

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第三次周赛 总结:是的,我在进步中。。。相关的知识,希望对你有一定的参考价值。

T1:最长平衡子字符串:

给你一个仅由 0 和 1 组成的二进制字符串 s 。  

如果子字符串中 所有的 0 都在 1 之前 且其中 0 的数量等于 1 的数量,则认为 s 的这个子字符串是平衡子字符串。请注意,空子字符串也视作平衡子字符串。 

返回  s 中最长的平衡子字符串长度。

子字符串是字符串中的一个连续字符序列。

解:

1.关键:

(1)主要还是 贪心的 过程

(2)遍历一次,每次记录当前的 '0' 或者 '1'

 (3)具体情况,还是要分情况讨论,具体见代码,别忘了当s[n-1] == '1' 时的边界情况即可

2.代码:

class Solution 
public:
    int findTheLongestBalancedSubstring(string s) 
        //所有'0' 都在 '1'之前, 而且 0的数量必须等于1的数量,return cnt*2
        //直接 贪心遍历即可
        int cnt_0 = 0,cnt_1 = 0 , ans = 0;
        int n = s.size();
        //--
        for(int i=0;i<n;i++)
        
            //记录当前位置的 '0' 或者 '1'
            if(s[i] == '0')
            
                cnt_0++;
            
            else if(s[i]=='1')
            
                cnt_1++;
            
            //--然后 :处理刷新操作 和 得到ans的操作:
            //case1:if(i>0 && s[i-1] == '1' && s[i] == '0') 此时:更新ans并且刷新 cnt_0 和 cnt_1
            if(i>0 && s[i-1] == '1' && s[i] == '0')
            
                cnt_0--;
                int num = min(cnt_0,cnt_1);
                ans = max(ans,num);
                cnt_0 = 1;
                cnt_1 = 0; //刷新
            
        
        //最后一个位置还是需要考虑一下的:
        if(s[n-1] == '1')
        
            int num = min(cnt_0,cnt_1);
            ans = max(ans,num);
        
        return ans*2;
    
;

T2:转换为二维数组

给你一个整数数组 nums 。请你创建一个满足以下条件的二维数组:

  • 二维数组应该  包含数组 nums 中的元素。
  • 二维数组中的每一行都包含 不同 的整数。
  • 二维数组的行数应尽可能  。

返回结果数组。如果存在多种答案,则返回其中任何一种。

请注意,二维数组的每一行上可以存在不同数量的元素。

解:

1.关键:

之前没有读懂题目,其实就是 一行中每个元素都不同
直接利用一个map容器,记录每个元素nums[i] 重复的次数
好吧,本质上就是贪心算法 中的 “木桶 短板理论”,
行数 : 由重复最多的哪个元素的 重复次数决定
(1)先预处理,将答案存到二维数组ans中,用map1记录<val,cnt>,用max记录当前最大的重复次数
(2)从头 对nums数组进行遍历,并且分2中情况进行讨论
<1>这个元素nums[i]重复次数比max还要多,需要建立 新的一行
<2>否则,这个元素可以到ans[map1[nums[i]]].push_back(nums[i])中即可

2.代码:

class Solution 
public:
    vector<vector<int>> findMatrix(vector<int>& nums) 
        //我.。。,之前没有读懂题目,其实就是 一行中每个元素都不同
        //直接利用一个map容器,记录每个元素nums[i] 重复的次数
        //好吧,本质上就是贪心算法 中的 “木桶 短板理论”,
        //行数 : 由重复最多的哪个元素的 重复次数决定
        //1.预处理:
        vector<vector<int>> ans;
        unordered_map<int,int> map1;//<val,cnt> ,打擂台,找到cnt中的那个最大值
        int max = 0;
        int n= nums.size();
        //2.从头 对nums数组遍历一次
        for(int i=0;i<n;i++)
        
            map1[nums[i]]++;
            //(1)这个元素重复次数比max还要多,需要建立 新的一行
            if(map1[nums[i]] > max) 
            
                max = map1[nums[i]];
                vector<int> new_col;
                new_col.push_back(nums[i]); //把这个元素加入进去
                //把这个行加入到ans中
                ans.push_back(new_col);
            
            //(2)否则,这个元素可以到ans[map1[nums[i]]].push_back(nums[i])中即可
            else
            
                ans[map1[nums[i]]-1].push_back(nums[i]); //(次数-1)等于对应行的下标
            
        
        return ans;
        
    
;

T3:老鼠 和 奶酪

有两只老鼠和 n 块不同类型的奶酪,每块奶酪都只能被其中一只老鼠吃掉。

下标为 i 处的奶酪被吃掉的得分为:

  • 如果第一只老鼠吃掉,则得分为 reward1[i] 。
  • 如果第二只老鼠吃掉,则得分为 reward2[i] 。

给你一个正整数数组 reward1 ,一个正整数数组 reward2 ,和一个非负整数 k 。

请你返回第一只老鼠恰好吃掉 k 块奶酪的情况下,最大 得分为多少。

解:

1.关键:

又是一个贪心的问题: 只要计算reward1[i] 和 reward2[i] 的差值数组diff[i]即可
(1)因为需要取k个reward1,所以diff[i] = reward1[i] - reward2[i]
(2)然后,找到diff[i]中最大的那k个, 求和sum_diff
直接对diff进行排序即可,然后从后面取到k个元素的和
(3)计算 reward2中的所有和 sum2, 最终 ans = sum2 + sum_diff
总的来说,就一点,尽可能的让第一只老鼠吃到的那k个奶酪“赚得相对于让第二只老鼠来吃 更多一些”

2.代码:

class Solution 
public:
    int miceAndCheese(vector<int>& reward1, vector<int>& reward2, int k) 
        //简单,又是一个贪心的问题: 只要计算reward1[i] 和 reward2[i] 的差值数组diff[i]即可
        //因为需要取k个reward1,所以diff[i] = reward1[i] - reward2[i]
        //然后,找到diff[i]中最大的那k个, 求和sum_diff
        //直接对diff进行排序即可,然后从后面取到k个元素的和
        //计算 reward2中的所有和 sum2, 最终 ans = sum2 + sum_diff
        
        int n = reward1.size();
        int sum_diff = 0;
        int sum2 = 0;
        vector<int> diff(n,0);
        for(int i=0;i<n;i++)
        
            sum2+= reward2[i];
            diff[i] = reward1[i] - reward2[i];
        
        //排序
        sort(diff.begin(),diff.end()); //从后往前求和
        for(int i=n-1;i>=(n-k);i--)
        
            sum_diff += diff[i];
        
        return sum2+sum_diff;
    
;

T4:最少翻转操作数

给你一个整数 n 和一个在范围 [0, n - 1] 以内的整数 p ,它们表示一个长度为 n 且下标从 0 开始的数组 arr ,数组中除了下标为 p 处是 1 以外,其他所有数都是 0 。

同时给你一个整数数组 banned ,它包含数组中的一些位置。banned 中第 i 个位置表示 arr[banned[i]] = 0 ,题目保证 banned[i] != p 。

你可以对 arr 进行 若干次 操作。一次操作中,你选择大小为 k 的一个 子数组 ,并将它 翻转 。在任何一次翻转操作后,你都需要确保 arr 中唯一的 1 不会到达任何 banned 中的位置。换句话说,arr[banned[i]] 始终 保持 0 。

请你返回一个数组 ans ,对于 [0, n - 1] 之间的任意下标 i ,ans[i] 是将 1 放到位置 i 处的 最少 翻转操作次数,如果无法放到位置 i 处,此数为 -1 。

  • 子数组 指的是一个数组里一段连续 非空 的元素序列。
  • 对于所有的 i ,ans[i] 相互之间独立计算。
  • 将一个数组中的元素 翻转 指的是将数组中的值变成 相反顺序 。

解:

1.关键:

备注这里借鉴了 妙蛙种子 的思路,添加了一些个人的理解

(1)先考虑特殊情况,k==1时,不能跳到其它位置

(2)将banned数组转移到 一个set中,方便访问

(3)把除了p下标位置 和 ban中的下标位置,分奇偶放到2个set容器中:

之所以这么做,就是因为 每次跳跃的区间向右移动一次后,从当前的下标位置now可以达到的下一个位置now' 其实向左 移动了2个位置,所以,对于任何一个k值,先看now+k-1也就是向右最远可以跳到的下标位置时 奇数 还是 偶数,之后就只能在 奇数或者 偶数容器set中去找下一个可以到达的位置

注意:只要在 最左边可以到达的位置 和 最右边可以到达的位置之间的 所有的奇数 或者 偶数 set中的位置,从当前的now位置下一次跳跃都是 可以到达的!!!

(4)利用一个 队列容器q进行bfs 广搜:

初值:起点位置 --就是p点下标,先入队 ,-- 一下解释 bfs的while循环的具体代码的含义

<1>取出队首元素 , 并且记得出队

<2>先Left可以移动 和 向Right可以移动的 最大距离:

<3>//悟了:之所以计算x = (now+k-1)%2作为st的下标

//是因为,从now这个点可以到达的点之间 都是相隔2位的,这一点见csdn笔记

//从st[x]中找到刚好大于now+L的位置

//然后,从左 到右,然所有now可以到达的位置全部到达一次

2.具体代码如下:

class Solution 
public:
    vector<int> minReverseOperations(int n, int p, vector<int>& banned, int k) 
        //审题:
        //第一:只有下标 p 位置为1
        //第二:banned[i]这个下标位置 永远不能为1
        //第三:每一次操作,选择一个大小为k的子数组,并反转它
        //保证,每次反转后,这个唯一的“1”还是不会到达banned[i]这个下标
        //也就是说arr[banned[i]] == 0 恒成立
        //第四:返回一个一维数组vector<int> ans
        //ans[i]--的含义是 将唯一的1 移动到下标i位置需要的最少“操作次数”
        //不能在某一次移动的结果中让banned[i]位置变成1
        //如果做不到,ans[i] = -1即可
        //开始动手:
        //思路:算了,先借鉴 妙蛙种子的 思路好了
        //(1)特殊
        vector<int> ans(n,-1);
        if(k == 1)
        
            ans[p] = 0;
            return ans;
        
        //(2)将banned数组转移到 一个set中,方便访问
        unordered_set<int> ban;
        for(auto item:banned)
        
            ban.insert(item);
        
        //(3)把除了p下标位置 和 ban中的下标位置,分奇偶放到2个set容器中:
        set<int> st[2];
        for(int i=0;i<n;i++)
        
            if(i!=p && ban.count(i) == 0)
            
                st[i%2].insert(i);
            
        
        //(4)利用一个 队列容器q进行bfs 广搜:
        queue<int> q;
        ans[p] = 0; // 初值:起点位置(相当于 一个跳跃游戏)
        q.push(p);
        //while循环进行搜索 和 update
        while(!q.empty())
        
            //<1>取出队首元素 , 并且记得出队
            int now = q.front(); q.pop();
            //<2>先Left可以移动 和 向Right可以移动的 最大距离:
            int L = max(-(k-1) , k-1 - 2*now);
            int R = min(k-1 ,(n-1)-(k-1)+(n-1)-2*now);
            //<3>
            //悟了:之所以计算x = (now+k-1)%2作为st的下标:
            //是因为,从now这个点可以到达的点之间 都是相隔2位的,这一点见csdn笔记
            int x = (now+k-1)%2;
            //从st[x]中找到刚好大于now+L的位置
            auto it =st[x].lower_bound(now+L);
            //然后,从左 到右,然所有now可以到达的位置全部到达一次
            while(it!= st[x].end())
            
                if(*it > now+R)
                
                    break; //已经超出可以到达的 最右边的位置了
                
                //访问这个位置,并且更新ans,同时从st[x]中删除这个位置
                ans[*it] = ans[now] + 1;
                q.push(*it); //入队。作为之后的起点
                it = st[x].erase(it);//删除后,返回下一个位置的 迭代器
            
        
        return ans;
    
;

总结part:

这一次明显在思维上有所进步,能够独立思考出 很多东西,而且我发现,如果一边嗑巴西松子一边思考,更容易 集中注意的 思考出大体的思路!非常美妙

ssm框架整合-过程总结(第三次周总结)

本周主要是完成前端界面和后端的整合。

犹豫前后端的工作完成程度不一致,只实现了部分整合。

技术分享图片

登录界面。

 

可能自己最近没有把重心放在短学期的项目上,导致我们工作的总体进度都要比别慢。

虽然我们只是三个人的小组,但我觉得还是需要一位同学担起带领整个团队的重任,不然可能8周结束后都不能完成任务。

 

犹豫前端方面,组员不能及时的完成任务,所以作为后端的我,需要及时跟上,先放一下后端的任务,帮助前端完成任务。

这周主要精力花在了,寻找合适的模版和修改模板上,前端知识没有系统的学习过,自己搭建比较困难,所以选择修改模版的方式,加快前端开发。

技术分享图片

 

这是我修改部分的后台首页。

 

技术分享图片

 

还有添加菜品页面,也完成了其他的页面,这里不过多展示。

 

下周目标:

完成后端的大部分设计、和本周设计出来页面的功能实现。

以上是关于第三次周赛 总结:是的,我在进步中。。。的主要内容,如果未能解决你的问题,请参考以下文章

PSP第三次周总结03

第三次周总结

ssm框架整合-过程总结(第三次周总结)

企业订餐系统(第二次周总结)

SWPUACM第二次周赛

FJUT2019暑假第二次周赛 A题