6/27力扣双周赛的部分题解

在这里插入图片描述

	这道题目直接遍历找出最大最小值,统计好就好了。
	代码如下:
class Solution {
public:
    double average(vector<int>& salary) {
        int maxnum,minnum;
        maxnum = minnum = salary[0];
        double sum = 0; 
        for(int i = 0;i<salary.size();i++)
        {
            sum += salary[i];
            if(maxnum<salary[i])
                maxnum = salary[i];
            if(minnum>salary[i])
                minnum = salary[i];
        }
        return (sum - maxnum - minnum)/(salary.size()-2);
    }
};

在这里插入图片描述

 	这道题关键在于去重,比如25,因子:1,5,25。比如:1,因子只有1
 	我的想法是:
 		1.对于1经行特判
 		2.加入1,n这两个因子
 		3.从2开始,直到根号n。所有的不一样的因子加入进去
 		4.排序
 		5.输出
class Solution {
public:
    int kthFactor(int n, int k) {
        vector<int> p;
        if(n==1)
        {
            if(k==1)
                return 1;
            else
                return -1;
        }
        p.push_back(1);
        p.push_back(n);
        for(int i = 2;i<=sqrt(n);i++)
        {
            if(n%i==0)
            {
                p.push_back(i);
             if(n/i!=i)
                p.push_back(n/i);
            }
        }
        sort(p.begin(),p.end());
        if(k<=p.size())
            return p[k-1];
        return -1;
    }
};

在这里插入图片描述

	小编想法:
		1.我们先进行特判,全为0,输出0,全为1,输出n-1。(必须减去一个)
		2.我们统一看成0,1序列交替出现。
		3.统计个数,压入数组。偶数代表0的序列个数,单数代表1的序列个数
		4.从下标为:2开始判断是不是1。每次自加2。如果为1,查看是不是产生新的最大值
int flag = false;
        for(int i = 0 ;i < nums.size();i++)
        {
            if(nums[i]!=0)
            {
                flag = true;
            }
        }
        if(!flag)
            return 0;
        flag = false;
        for(int i = 0 ;i < nums.size();i++)
        {
            if(nums[i]!=1)
            {
                flag = true;
            }
        }
        if(!flag)
            return nums.size()-1;
        vector<int> tt;
        int sum = 0;
        int maxnum = 0;
        for(int i = 0 ;i < nums.size();i++)
        {
            sum = 0;
            for(;i < nums.size();i++)
            {
                if(nums[i]!=0)
                {
                    break;
                }
                sum++;
            }
            tt.push_back(sum);
            sum = 0;
            for(;i < nums.size();i++)
            {
                if(nums[i]!=1)
                {
                    break;
                }
                sum++;
            }
            maxnum = max(sum,maxnum);
            tt.push_back(sum);
            i--;//自加会导致如果少算一个0
        }
        for(int i = 2;i<tt.size();i+=2)
        {
            if(tt[i]==1&&i+1<tt.size())
            {
                 maxnum = max(tt[i-1]+tt[i+1],maxnum);
            }
        }
        return maxnum;
    }

在这里插入图片描述

这道题我有两种思路,但是在写博客前没有去证明这是对的
方法一:
	1.用并查集选出层次最多的树,毕竟在怎么排,都不可能小于这个值
	2.然后选出层次次一点的树,加入在之前的树没有排满的学期,插进去
方法二:
	1.回溯遍历出所有的情况,可以使用剪枝的方法,减少复杂度。

附上其他人的代码:

class Solution {
public:
    int minNumberOfSemesters(int n, vector<vector<int>>& dependencies, int k) {
        vector<int> pre(n); //如果pre[i]的二进制第j位是1,表示j到i有一条边
        for(auto& e : dependencies){
            e[0] -= 1; //序号变成[0,n)
            e[1] -= 1;
            pre[e[1]] |= 1 << e[0]; //根据定义,将pre[e[1]]的第e[0]位变成1
        }
        //如何用二进制表示集合:
        //i表示一个课程集合,如果i的二进制第j位1,那么表示第j个课程属于这个集合
        //i的取值范围是从二进制00...00到二进制11...11,也就是从0到(1<<n)-1
        vector<int> dp(1 << n, n);
        //dp[i]表示学完i表示的课程集合最少步数,初始化成n,因为学完所有课不可能超过n步
        dp[0] = 0; //不学任何课程只需要0步
        for(int i = 0; i < (1 << n); i += 1){//按某个顺序枚举i
            int ex = 0; //用ex表示学完i的课程后现在可以学哪些课程,如果ex的二进制第j位1,那么表示可以先第j个课程
            for(int j = 0; j < n; j += 1) if((i & pre[j]) == pre[j]) ex |= 1 << j;
            //枚举所有课程,(i&pre[j])==pre[j]表示pre[j]是i的子集,如果i包含pre[j],那么就可以学习j
            ex &= ~i;//从ex里去掉i,避免重复
            for(int s = ex; s; s = (s - 1) & ex) //这样可以枚举ex的所有非空子集s,具体见搜索引擎
                if(__builtin_popcount(s) <= k) //如果这个集合大小小于等于k
                    dp[i | s] = min(dp[i | s], dp[i] + 1);
                    //更新答案,由于i<(i|s),所以可以按i从小到大的顺序枚举
        }
        return dp.back();//最后一个值,也就是dp[(1<<n)-1]
    }
};

作者:何逊
链接:https://leetcode-cn.com/circle/discuss/zPlu04/view/bivCj2/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值