栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

LeetCode 1491 - 1493

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

LeetCode 1491 - 1493

去掉最低工资和最高工资后的工资平均值

 

给出一个数组,数组中的值表示每个人的工资,数组里面所有数都是不一样的,每个人的工资是唯一的,去掉一个最小的数,去掉一个最大的数,求剩余所有人的平均工资

示例 1:

最小 1000,最大 4000,去掉最小和最大的,剩下 3000 和 2000 取平均,答案是 2500

数据范围大于等于 3,也就是说去掉最大数和最小数之后,至少会剩一个数

在遍历的时候求总和,同时记录最大数和最小数,算完总和后,减去一个最大数,再减去一个最小数,就是剩下所有数的和,最后再除以 n - 2 即可

只需要扫描一遍,时间复杂度是 O( n )

class Solution {
public:
    double average(vector& salary) {
        //定义总和
        double s = 0;
        //定义最大数和最小数
        int maxv = INT_MIN,minv =INT_MAX;
        //遍历数组里面的所有数
        for(auto x : salary) {
            //总和加上当前这个数
            s += x;
            //更新最大值
            maxv = max(maxv, x);
            //更新最小值
            minv = min(minv, x);
        }
        //剩下所有数的平均数
        return (s - maxv - minv) / (salary.size() - 2);
    }
};
n 的第 k 个因子

 

求: 从小到大数,n 的第 k 个约数是什么?

示例 1:

n = 12,12 的所有约数(因子)是 1,2,3,4,6,12,需要求从小到大数它的第 3 个因子,也就是 3,返回 3 即可

如果 k 大于 n 的因子个数的话,返回 - 1

数据范围:n 和 k 都是 1000,由于 n 和 k 很小,可以直接从小到大枚举,枚举到第 k 个直接输出即可,时间复杂度为 O( n )

第十二届蓝桥杯省赛第二场C++B组真题_小雪菜本菜的博客-CSDN博客

n 的所有的约数都是成对出现的,枚举的时候只需要枚举到 √ n 就可以了,时间复杂度由 O( n ) 降到 O( √ n )

暴力做法

class Solution {
public:
    int kthFactor(int n, int k) {
        //从小到大枚举
        for(int i = 1;i <= n;i++ )
            //如果当前i是n的约数 k--
            if(n % i == 0 && -- k == 0)
                //如果k--后k=0答案就是i
                return i;
        //约数个数不足k个返回-1
        return -1;
    }
};

如果 d 是 n 的约数,那么 n / d 也一定是 n 的约数,所有的约数一定是成对出现的,枚举的时候可以枚举较小的一半约数即可,枚举的 d 满足 d ≤ n / d,d ≤ √ n,只需要枚举到 √ n 即可

优化做法

需要注意一种特殊情况:如果 n 是完全平方数,那么满足 x^2 = n 的因子被枚举了两次,需要忽略其中的一次。

class Solution {
public:
    int kthFactor(int n, int k) {
        //定义答案数组
        vector res;
        //i从 1 开始枚举
        for(int i = 1;i <= n / i;i++ ) {
            //如果 n % i 等于 0 说明 i 是 n 的约数
            if(n % i == 0) {
                //把 i 加到数组中
                res.push_back(i);
                //把 n / i 加到数组中 
                if(i != n / i) res.push_back(n / i);
            }
        }
        //需要排序:从小到大
        sort(res.begin(),res.end());
        if(k > res.size()) return -1;
        return res[k - 1];
    }
};
删除一个元素以后全为 1 的最长子数组

 

给我们一个只包含 0 和 1 的数组,要从里面删掉一个数,删完之后,求最长的一段连续的 1 有多少个?

示例 1:

1 1 0 1

可以把 0 删除后,删除 0 后,就剩 3 个 1 是连续的,答案是 3

示例 2:

删除位置 4 的 0,5 个 1 就是连续的,答案是 5

先预处理 f[ i ],表示以 i 结尾的最长连续 1 的个数,正向枚举一遍,再反向枚举一遍,空间复杂度高

也可以用双指针算法

用两个指针维护一个区间,使得这个区间中最多只有一个 0,枚举的是每一个区间的右端点 i,对于每一个 i 都要找一个最靠左的 j,使得 i 和 j 之间最多只有一个 0,对于这样一个区间,每次可以把这里面的 0 删掉,以 i 结尾的区间里面最长的长度就是 i - j + 1,i 每次往后移动一步,j 一直往后移动,直到满足区间里面最多只有一个 0 为止

每次枚举一个 i 之后,都可以求出以 i 结尾的所有区间里面最长的一个满足要求的区间

在所有的 i 里面取一个 max,就是答案

两个指针只会往前走,不会回头,每个元素只会走两遍,时间复杂度为 O( n ),空间复杂度:没有开数组,O( 1 )

class Solution {
public:
    int longestSubarray(vector& nums) {
        //定义答案
        int res = 0;
        //z记录0的个数 i、j都从0开始
        for(int i = 0,j = 0,z = 0;i < nums.size();i++ ) {
            //判断
            if(nums[i] == 0) z++;
            //z > 1 表示区间中多于1个0 就把j一直往右走 直到区间里面最多只有一个0为止 如果是0就减1 不是0就不减1
            while(z > 1) z -= !nums[j++];
            //更新答案 区间总长度i - j + 1 注意去掉1个0
            res = max(res,i - j + 1 - 1);
        }
        return res;
    }
};
并行课程 II

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/925408.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号