7.12 卷积

发布于:2025-07-12 ⋅ 阅读:(18) ⋅ 点赞:(0)

格雷编码➕旋转

 

class Solution {
public:
    vector<int> circularPermutation(int n, int start) 
    {
        
        vector<int> ret;
        ret.push_back(0);
//初始化
         
        int head=1;
//层数看待
        for(int i=0;i<n;i++)
        {
         for(int j=ret.size()-1;j>=0;j--)
            {
                ret.push_back(head+ret[j]);
            }
            head<<=1;  //头部+1
        }
        vector<int> ans;
        int m=ret.size();
        int i=0;
        for(;i<m;i++)
        {
            if(ret[i]==start)
                break;
        }
       ans.insert(ans.end(),ret.begin()+i,ret.end());
       ans.insert(ans.end(),ret.begin(),ret.begin()+i);
       return ans;
        
        
    }
};

 

lc922.奇偶排序的两种解法

1.奇偶分离

class Solution {
public:
    vector<int> sortArrayByParityII(vector<int>& nums) {
        vector<int> odds, evens, res(nums.size());
        for (auto n : nums) {
            if (n & 1) odds.push_back(n);
            else evens.push_back(n);
        }
        for (int i = 0, oI = 1, eI = 0; i < odds.size(); ++i) {
            res[eI] = evens[i], eI += 2; // 装偶数
            res[oI] = odds[i], oI += 2; // 装厅数
        }
        return res;
    }
};
 

2.双指针


 

class Solution {
public:
    vector<int> sortArrayByParityII(vector<int>& nums) {
        for (int i = 0, j = 1; i < nums.size(); i += 2) {
            if (nums[i] % 2) {
                while (nums[j] % 2) {
                    j += 2;
                }
                swap(nums[i], nums[j]);
            }
        }
        return nums;
    }
};

 

 

lc1900.模拟比赛

算出两个指定选手最早和最晚能在第几轮碰到。

还是建议dfs捏

 

模拟比赛,找出两个特定选手(firstPlayer和secondPlayer)最早和最晚相遇的轮次。
 
1. 定义了一个“选手”结构体,包含两个属性a(战斗力)和b(编号),并规定按b值排序。
2. 主函数里,根据总人数n设置模拟次数(人数越多模拟次数越多)。
3. 每次模拟时:
- 给所有选手随机分配战斗力,让两个特定选手战斗力最高(确保他们能赢到最后相遇)。
- 模拟比赛:每轮让第i名和第rest+1-i名选手对决,赢的留下。
- 检查这一轮是否是两个特定选手相遇,记录最早和最晚的轮次。
4. 最后返回这两个记录的轮次。
 
简单说就是通过多次模拟比赛,算出两个指定选手最早和最晚能在第几轮碰到。

struct node
{
    int a , b;
    bool operator <(const node &p)
    {
        return b < p.b;
    }
}player[30];

 

class Solution {
public:
    vector<int> earliestAndLatest(int n, int firstPlayer, int secondPlayer) 
    {
        srand(time(NULL));

        // 根据n的大小设置模拟次数
        int N;
        if(n <= 10)
            N = 800;
        else if (n <= 20)
            N = 8000;
        else N = 38000;

        int ans1 = 9999 , ans2 = 0 , rest , now;
        
        while(N--)
        {
            // 剩余的运动员
            rest = n;

            // 初始化战斗力
            for(int i = 1 ; i <= n ; i++)
            {
                player[i].a = rand() % 1075943;
                player[i].b = i;
            }
            player[firstPlayer].a = 11000000;
            player[secondPlayer].a = 10999999;
            
            // 统计轮次
            now = 1;
         
            // 模拟比赛
            while(rest > 1)
            {
                for(int i = 1 ; i <= rest / 2 ; i++)
                {
                    if(player[i].a < player[rest + 1 - i].a)
                        player[i] = player[rest + 1 - i];

                    // 统计firstPlayer和secondPlayer相遇轮次的最大值和最小值
                    if(player[i].b == firstPlayer && player[rest + 1 - i].b == secondPlayer)
                        ans1 = min(ans1 , now) , ans2 = max(ans2 , now);
                }
                now++;
                rest = (rest + 1) / 2;
                sort(player + 1 , player + rest + 1);

            }
        }
        vector<int> ans = {ans1 , ans2};
        return ans;

    }
};

dfs

class Solution {
    bitset<1 << 15> m;
    int the_max = 0, the_min = INT_MAX;

    void dfs(int serial, int n, int firstPlayer, int secondPlayer) {
        int mask = (n << 10) + (firstPlayer << 5) + secondPlayer;
        int ff = n - firstPlayer + 1, fs = n - secondPlayer + 1;
        if (ff == secondPlayer) {
            the_max = max(the_max, serial);
            the_min = min(the_min, serial);
            return;
        }
        if (m[mask]) return;
        m.set(mask);

        int arr[] {firstPlayer, secondPlayer, ff, fs};
        sort(arr, arr + 4);
        int f_index = lower_bound(arr, arr + 4, firstPlayer) - arr;
        int s_index = lower_bound(arr, arr + 4, secondPlayer) - arr;
        for (int i = 0; i < arr[0]; ++i) {
            for (int j = 0; j < arr[1] - arr[0]; ++j) {
                int fi = arr[0] - 1 - i;
                int fj = arr[1] - arr[0] - 1 - j;
                int mid = (arr[2] - arr[1]) / 2;

                int val[] { i, i + j, i + j + mid, i + j + mid + fj };

                if (f_index == 0 && s_index == 1) {
                    dfs(serial + 1, (n + 1) / 2, val[0] + 1, val[1] + 2);
                } else if (f_index == 2 && s_index == 3) {
                    dfs(serial + 1, (n + 1) / 2, val[2] + 1, val[3] + 2);
                } else if (f_index == 0 && s_index == 2) {
                    dfs(serial + 1, (n + 1) / 2, val[0] + 1, val[2] + 2);
                } else {
                    assert(f_index == 1 && s_index == 3);
                    dfs(serial + 1, (n + 1) / 2, val[1] + 1, val[3] + 2);
                }
            }
        }
    }

public:
    vector<int> earliestAndLatest(int n, int firstPlayer, int secondPlayer) {
        dfs(1, n,firstPlayer, secondPlayer);
        return { the_min, the_max };
    }
};

计算两个特定选手(firstPlayer和secondPlayer)在比赛中最早和最晚相遇的轮次。

1. 用深度优先搜索(dfs)模拟比赛过程,不是真的比胜负,而是追踪两个选手的位置变化。

2. 每次递归代表一轮比赛,选手按规则配对后,胜者进入下一轮,位置会重新排列。

3. 代码通过记录状态(当前总人数、两个选手的位置)避免重复计算,高效找出两人相遇的最早和最晚轮次。

简单说,就是用递归模拟每一轮比赛,追踪两个指定选手的位置变化,最终得出他们最早和最晚能碰上的轮次。

 

找回自信dp

class Solution {
public:
    int minCostClimbingStairs(vector<int>& cost) {
        int n=cost.size();
        //初始化一个dp表
        vector<int> dp(n+1,0);
        //初始化
        dp[0]=dp[1]=0;
        //填表
        for(int i=2;i<n+1;i++)
        //根据状态转移方程得
        dp[i]=min(cost[i-1]+dp[i-1],cost[i-2]+dp[i-2]);
        //一步两步当中,勇敢取小
        return dp[n];

    }
};

 


在 C++ 中, queue  可以存储 vector ,因为 queue  是一种容器适配器,它可以容纳任何符合要求的元素类型,包括标准容器(如 vector )。

accumulate()累加求和

accumulate  是 C++ 标准库 <numeric>  里的一个实用工具,专门用来做累加求和

accumulate(vec开始位置, vec结束位置, 0);

eg.(nums.begin(),nums.end(),0)
           


 

lc2428.沙漏

可以固定左上角的点枚举,也可以用3*3卷积

更完善一点的,可以开辟空间

存储每个3x3区域的计算结果
 vector<vector<int>> nums(m - 2, vector<int>(n - 2, 0));

 

class Solution {

public:

    int maxSum(vector<vector<int>>& grid) {

        int m = grid.size(), n = grid[0].size();

        int ret=0;

        // 定义十字形卷积核, 处理映射

        vector<vector<int>> Kernel = {{1,1,1}, {0,1,0}, {1,1,1}};

        

        for (int i = 0; i <= m - 3; ++i) {

            for (int j = 0; j <= n - 3; ++j) {

                int sum=0;

                for (int k = 0; k < 3; ++k) {

                    for (int l = 0; l < 3; ++l) {

              sum += grid[i + k][j + l] * Kernel[k][l];

                    }

                }

                ret=max(ret,sum);

            }

        }

        return ret;

    }

};

 

对称二叉树

class Solution {

public:

    bool isSymmetric(TreeNode* root) 

    {

        if(!root) return true;

        return com(root->left,root->right);

    }

    

    bool com(TreeNode* left,TreeNode* right)

    {

      //对称

        if(!left && !right)

            return true;

        if(!left ||!right)

            return false;

        return (left->val==right->val)

        && com(left->left,right->right)

        && com(left->right,right->left);

    }

};

 


网站公告

今日签到

点亮在社区的每一天
去签到