• LeetCode第29场双周赛题解


    第一题


    用一个新数组newSalary保存去掉最低和最高工资的工资列表,然后遍历newSalary,计算总和,除以元素个数,就得到了平均值。

    class Solution {
    public:
        double average(vector<int>& salary) {
            sort(salary.begin(), salary.end());
            vector<int> newSalary;
            for(int i = 1; i < salary.size() - 1; ++i) {
                newSalary.push_back(salary[i]);
            }
            double res = 0;
            for(int i = 0; i < newSalary.size(); ++i) {
                res += newSalary[i];
            }
            res /= newSalary.size();
            return res;
        }
    };
    

    第二题


    直接从小到达枚举所有的因子,最后返回第k个因子即可。

    class Solution {
    public:
        int kthFactor(int n, int k) {
            vector<int> factor;
            factor.push_back(1);            //1是所有数的因子
            for(int i = 2; i < n; ++i) {
                if(n % i == 0) {
                    factor.push_back(i);
                }
            }
            factor.push_back(n);            //这个数本身也是自己的因子
            int size = factor.size();
            if(size < k) {
                return -1;
            } else {
                return factor[k - 1];
            }
        }
    };
    

    第三题


    用一个zeroPos数组存放原数组所有的0的位置。然后枚举所有删除0的情况,每个情况都用一个新数组newArray存储删除掉0之后剩下的元素。
    然后遍历新数组newArray,计算连续的1的长度。 这样,当枚举完所有删除位置,以及对应的连续1的最大长度之后,就能得到答案。

    class Solution {
    public:
        int longestSubarray(vector<int>& nums) {
            vector<int> zeroPos;            //存储nums中0的位置
            for(int i = 0; i < nums.size(); ++i) {
                if(nums[i] == 0) {
                    zeroPos.push_back(i);
                }
            }
            if(zeroPos.size() == 0) {            //如果原数组没有0,即全1
                return nums.size() - 1;          //那么删除一个元素之后,连续1的最大长度为nums.size() - 1
            }
            int res = 0;
            for(int i = 0; i < zeroPos.size(); ++i) {      //枚举所有删除位置
                vector<int> newArray;                      //存储删除一个0之后剩下的元素组成的数组
                int delPos = zeroPos[i];                   //删除位置
                for(int j = 0; j < nums.size(); ++j) {
                    if(j == delPos) {                      //如果是删除位置,就不加入新数组
                        continue;
                    } else {
                        newArray.push_back(nums[j]);
                    }
                }
                
                for(int j = 0; j < newArray.size(); ) {    //遍历新数组,计算连续1的最大长度
                    if(newArray[j] == 0) {                  
                        ++j;
                    } else {
                        int L = j, R = j + 1;              //双指针计算连续1的最大长度
                        while(R < newArray.size() && newArray[R] == 1) {  
                            ++R;
                        }
                        res = max(res, R - L);             //当前连续1的长度为R - L,更新一下res
                        j = R;                             //下一次 j 从 R的位置开始枚举即可
                    }
                }
            }
            return res;
        }
    };
    

    这题还有一个双指针做法。 用两个变量start和end指向子数组的开始和结束下标,两个指针只会向右移动,我们需要寻找这样一个子数组nums[start ~ end],满足start ~ end之间0的个数不超过1个(1个或0个),这样我们删去一个元素(0或1)剩下的子数组就满足连续1的条件,然后我们更新长度。由于此时子数组的长度为end - start + 1,又因为题目要求必须删掉一个元素(就算子数组全部是1,也得删掉一个1),所以我们得到res = max(res, end - start); end - start是子数组长度减1得来的。

    class Solution {
    public:
        int longestSubarray(vector<int>& nums) {
            int res = 0;
            for(int start = 0, end = 0, zeroNum = 0; end < nums.size(); ++end) {      //zeroNum表示当前子数组中0的个数
                if(nums[end] == 0) {                        //如果尾指针指向的元素为0,增加zeroNum
                    ++zeroNum;
                }
                while(zeroNum > 1) {                        //如果子数组中0的个数大于1,我们需要增加头指针
                    zeroNum -= !nums[start++];              //这句话的意思是,如果start指向的元素为0,则增加start,同时子数组中0的数量减一;否则增加start,子数组中0的数量保持不变。 只有子数组中0的数量减到1以下时才跳出循环,暂时不用增加start
                }
                res = max(res, end - start);                //此时子数组的大小为end - start + 1, 由于要减去一个要删除的元素,所以更新的长度为end - start
            }
            return res;
        }
    };
    

    使用双指针做法,左右指针只会在一层循环内向右移动,因此时间复杂度为O(n);由于无需额外的辅助数组,因此空间复杂度为O(1).

    第四题


    状态压缩DP,留个坑明天填上。

  • 相关阅读:
    安全系列之二:OAuth2.0 开放授权协议
    安全系列之一:忘记密码
    Tomcat剖析(五):Tomcat 容器
    如何做好项目?
    SonarLint(Sonar) 代码质量管理
    一个JavaWeb项目开发总结
    Tomcat剖析(四):Tomcat默认连接器(2)
    Tomcat剖析(四):Tomcat默认连接器(1)
    Spring mvc 字节流
    spring mvc 之初体验
  • 原文地址:https://www.cnblogs.com/linrj/p/13200645.html
Copyright © 2020-2023  润新知