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

6/27力扣双周赛的部分题解_第1张图片

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

6/27力扣双周赛的部分题解_第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 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;
    }
};

6/27力扣双周赛的部分题解_第3张图片

	小编想法:
		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 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

6/27力扣双周赛的部分题解_第4张图片

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

附上其他人的代码:

class Solution {
public:
    int minNumberOfSemesters(int n, vector>& dependencies, int k) {
        vector 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< 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<

你可能感兴趣的:(刷题心得,算法,动态规划)