leedcode第241场周赛(我太菜了,类的那道题给我整的蒙了,,,,,)


这周的周赛打的很不好,以后还是得多练练,主要是leedcode不熟悉操作(一个类就直接给我整蒙了,,,,最后dp状态转移方程还没想到,差一点点就。。。。)
1.直接dfs搜索一下就好了,每个数都有两种情况(异或和不异或)
2.计算‘0’和‘1’的个数,如果个数相差大于1的话直接就-1了,因为肯定够不成交替序列,之后就直接推两种情况找最小值就行了,别忘了除以2。
3.(看了大佬的代码)对,就是这道题目,前一个操作加数就直接加,后面的操作可以构建个映射,直接去枚举另一个数组就行了,时间复杂度是O(n)。
4.(看了大佬的代码)动态规划标准题,其实只要去找状态转移方程就好了,从n-1到n,考虑(n-1,k)和(n-1,k-1)怎么变化到(n,k)的。

5759. 找出所有子集的异或总和再求和

在这里插入图片描述
在这里插入图片描述

这道题还是很容易的,只要dfs一下就可以了,只要考虑一下每个数去做不做异或就可以了,最后直接求和就得到答案了。

int ans;
int t;
int sum;
bool pan[20];
class Solution {
public:
    void dfs(int a,vector<int>& nums)
    {
        if(a==t)
        {
            ans+=sum;
        }
        else
        {
            dfs(a+1,nums);
            pan[a]=true;
            int q=sum;
            sum=sum^nums[a];
            dfs(a+1,nums);
            pan[a]=false;
            sum=q;
        }
    }
    int subsetXORSum(vector<int>& nums) {
        ans=0;
        sum=0;
        t=nums.size();
        memset(pan,0,sizeof(pan));
        dfs(0,nums);
        return ans;
    }
};

5760. 构成交替字符串需要的最小交换次数

在这里插入图片描述
在这里插入图片描述

这道题主要是看着复杂,仔细想想其实很简单。
1.首先,你需要考虑字符串中‘0’和‘1’的个数,如果个数相差大于1的话,肯定够不成交替的01字符串(这个应该很好想吧),所以此时只需要返回-1就行了。
2.之后,能够完成01交替字符串的,目标状态只有两种,一种是0101010…,另一种是1010101010…,所以现在只要考虑找到变成这两种状态的步数的最小值就是答案啦。
3.第一种情况和第二种情况的思想其实是一样的,只要看奇数位置或者偶数位置的字符是不是‘0‘或者’1’就行了,如果不是的话就令改变次数加1就行了。
4.最后的话,因为规定的操作是交换字符而不是直接改字符,所以再使操作数除以2(如果此时世是奇数除以2的话,直接取另外一个,不需要考虑别的,因为奇数不能完成交换字符操作),最后最小的就是答案了。

class Solution {
public:
    int minSwaps(string s) {
        int ans=0;
        int nums0=0;
        int nums1=0;
        int len=s.length();
        for(int i=0;i<len;i++)
        {
            if(s[i]=='0')
            {
                nums0++;
            }
            else
            {
                nums1++;
            }
        }
        if(abs(nums0-nums1)<=1)
        {
            int ans1=0;int ans2=0;
            for(int i=0;i<len;i++)
            {
                if(i%2==0)
                {
                    if(s[i]!='1')
                    {
                        ans1++;
                    }
                }
                else
                {
                    if(s[i]!='0')
                    {
                        ans1++;
                    }
                }
            }
            for(int i=0;i<len;i++)
            {
                if(i%2==1)
                {
                    if(s[i]!='1')
                    {
                        ans2++;
                    }
                }
                else
                {
                    if(s[i]!='0')
                    {
                        ans2++;
                    }
                }
            }
            //cout<<ans1<<" "<<ans2<<endl;
            if(ans1%2!=0||ans2%2!=0)
            {
                if(ans1%2!=0)
                {
                    ans=ans2/2;
                }
                else if(ans2%2!=0)
                {
                    ans=ans1/2;
                }
            }
            else
            {
                ans1=ans1/2;
                ans2=ans2/2;
                ans=min(ans1,ans2);
            }
        }
        else
        {
            ans=-1;
        }
        return ans;
    }
};

5761. 找出和为指定值的下标对

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这题目主要是遇到类别蒙(泪目!!!!),第一个操作就直接加就完事了,第二个操作需要构建一个映射,使得直接去枚举另一个数组就可以了,将时间复杂度降到O(n)。

class FindSumPairs {
public:
    int a[200005], b[200005];
    int n, m;
    map<int, int> hsh;
    FindSumPairs(vector<int>& nums1, vector<int>& nums2) {
        n = nums1.size(), m = nums2.size();
        hsh.clear();
        for (int i = 0; i < m; i ++) {
            hsh[nums2[i]] ++;
        }
        for (int i = 0; i < n; i ++) a[i + 1] = nums1[i];
        for (int i = 0; i < m; i ++) b[i + 1] = nums2[i];
    }
    void add(int index, int val) {
        hsh[b[index + 1]] --;
        b[index + 1] += val;
        hsh[b[index + 1]] ++;
    }
    int count(int tot) {
        int ans = 0;
        for (int i = 1; i <= n; i ++) ans += hsh[tot - a[i]];
        return ans;
    }
};

/**
 * Your FindSumPairs object will be instantiated and called as such:
 * FindSumPairs* obj = new FindSumPairs(nums1, nums2);
 * obj->add(index,val);
 * int param_2 = obj->count(tot);
 */

5762. 恰有 K 根木棍可以看到的排列数目

在这里插入图片描述
在这里插入图片描述

这就是一道常规动态规划题目,只要去构造状态转移方程就可以了,其实从n-1加上一个数到n是怎么变化的
1.n-1->n,添加的这个数要比所有数大,如果此时从(n-1,k)->(n,k)这个变化考虑的话,其实就是用n去替换变换前的n-1,之后在考虑前面构成的子序列的变化,因为前面有n-1个数,还有一个数可以替换,所以共有n-1种替换方法。
2.n-1->n,添加的这个数要比所有数大,如果此时从(n-1,k-1)->(n,k)这个变化考虑的话,那么这个数只要填到变化前的数列n-1的后面就可以了,只有1种替换方法。
综上,(n,k)=(n-1)*(n-1,k)+(n-1,k-1).
接着就是dp起来,,,,,,,,,,

class Solution {
public:
    bool vis[1005][1005];
    int f[1005][1005];
    const int mod = (int )1e9 + 7;
    int dp(int n, int k) {
        if (n == 0 && k == 0) return 1;
        if (k == 0) return 0;
        if (n == 0) return 0;
        if (vis[n][k]) return f[n][k];
        vis[n][k] = true;
        return f[n][k] = (1LL * (n - 1) * dp(n - 1, k) + dp(n - 1, k - 1)) % mod;
    }
    int rearrangeSticks(int n, int k) {
        return dp(n, k);
    }
};

本人很菜,不要喷我,呜呜呜呜…,自己的水平还是太低,常规的动态规划题目反应太慢了,状态转移方程推不出来,并且常规的空间换时间的思想还是用的不太好。继续加油!!!!!
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

初见。。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值