【Leetcode Sheet】Weekly Practice 7

2023-09-18 10:55:47

Leetcode Test

1462 课程表Ⅳ(9.12)

你总共需要上 numCourses 门课,课程编号依次为 0numCourses-1 。你会得到一个数组 prerequisite ,其中 prerequisites[i] = [ai, bi] 表示如果你想选 bi 课程,你 必须 先选 ai 课程。

  • 有的课会有直接的先修课程,比如如果想上课程 1 ,你必须先上课程 0 ,那么会以 [0,1] 数对的形式给出先修课程数对。

先决条件也可以是 间接 的。如果课程 a 是课程 b 的先决条件,课程 b 是课程 c 的先决条件,那么课程 a 就是课程 c 的先决条件。

你也得到一个数组 queries ,其中 queries[j] = [uj, vj]。对于第 j 个查询,您应该回答课程 uj 是否是课程 vj 的先决条件。

返回一个布尔数组 answer ,其中 answer[j] 是第 j 个查询的答案。

提示:

  • 2 <= numCourses <= 100
  • 0 <= prerequisites.length <= (numCourses * (numCourses - 1) / 2)
  • prerequisites[i].length == 2
  • 0 <= ai, bi <= n - 1
  • ai != bi
  • 每一对 [ai, bi]不同
  • 先修课程图中没有环。
  • 1 <= queries.length <= 104
  • 0 <= ui, vi <= n - 1
  • ui != vi

【广度优先 + 拓扑】官解

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
bool* checkIfPrerequisite(int numCourses, int** prerequisites, int prerequisitesSize, int* prerequisitesColSize, int** queries, int queriesSize, int* queriesColSize, int* returnSize){
    int g[numCourses][numCourses];
    int gColSize[numCourses], indgree[numCourses];
    bool isPre[numCourses][numCourses];
    memset(gColSize, 0, sizeof(gColSize));
    memset(indgree, 0, sizeof(indgree));
    memset(isPre, 0, sizeof(isPre));
    for (int i = 0; i < prerequisitesSize; i++) {
        int *p = prerequisites[i];
        ++indgree[p[1]];
        g[p[0]][gColSize[p[0]]++] = p[1];
    }

    int queue[numCourses];
    int head = 0, tail = 0;
    for (int i = 0; i < numCourses; ++i) {
        if (indgree[i] == 0) {
            queue[tail++] = i;
        }
    }
    while (head != tail) {
        int cur = queue[head];
        head++;
        for (int j = 0; j < gColSize[cur]; j++) {
            int ne = g[cur][j];
            isPre[cur][ne] = true;
            for (int i = 0; i < numCourses; ++i) {
                isPre[i][ne] = isPre[i][ne] | isPre[i][cur];
            }
            --indgree[ne];
            if (indgree[ne] == 0) {
                queue[tail++] = ne;
            }
        }
    }

    bool *res = (bool *)malloc(sizeof(char) * queriesSize);
    for (int i = 0; i < queriesSize; i++) {
        int *query = queries[i];
        res[i] = isPre[query[0]][query[1]];
    }
    *returnSize = queriesSize;
    return res;
}

2596 检查骑士巡视方案(9.13)

骑士在一张 n x n 的棋盘上巡视。在有效的巡视方案中,骑士会从棋盘的 左上角 出发,并且访问棋盘上的每个格子 恰好一次

给你一个 n x n 的整数矩阵 grid ,由范围 [0, n * n - 1] 内的不同整数组成,其中 grid[row][col] 表示单元格 (row, col) 是骑士访问的第 grid[row][col] 个单元格。骑士的行动是从下标 0 开始的。

如果 grid 表示了骑士的有效巡视方案,返回 true;否则返回 false

注意,骑士行动时可以垂直移动两个格子且水平移动一个格子,或水平移动两个格子且垂直移动一个格子。下图展示了骑士从某个格子出发可能的八种行动路线。

提示:

  • n == grid.length == grid[i].length
  • 3 <= n <= 7
  • 0 <= grid[row][col] < n * n
  • grid 中的所有整数 互不相同

【哈希表】

bool checkValidGrid(int** grid, int gridSize, int* gridColSize){
    //初始化hash-table
    int n=gridSize;
    int *x=malloc(sizeof(int)*(n*n));
    int *y=malloc(sizeof(int)*(n*n));
    for(int i=0;i<n*n;i++){
        x[i]=0;
        y[i]=0;
    }

    //遍历矩阵,赋值hash-table
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            int pos=grid[i][j]; //grid中的数字
            x[pos]=i;   //hash-x
            y[pos]=j;   //hash-y
        }
    }

    //定义初始值
    int xx=x[0],yy=y[0];
    bool flag=1;
    if(xx!=0 || yy!=0) return 0;    //骑士的行动是从下标 0 开始的。

    //遍历hash-table
    for(int i=1;i<n*n;i++){
        if( (abs(x[i]-xx)==1 && abs(y[i]-yy)==2) || (abs(x[i]-xx)==2 && abs(y[i]-yy)==1) ){
            xx=x[i];
            yy=y[i];
            //更新上一个值
        }
        else{
            flag=0;
            break;
        }
    }
    return flag;
}

1222 可以攻击国王的皇后(9.14)

在一个 8x8 的棋盘上,放置着若干「黑皇后」和一个「白国王」。

给定一个由整数坐标组成的数组 queens ,表示黑皇后的位置;以及一对坐标 king ,表示白国王的位置,返回所有可以攻击国王的皇后的坐标(任意顺序)。

提示:

  • 1 <= queens.length <= 63
  • queens[i].length == 2
  • 0 <= queens[i][j] < 8
  • king.length == 2
  • 0 <= king[0], king[1] < 8
  • 一个棋盘格上最多只能放置一枚棋子。

【模拟】从king开始,向8个方向寻找queen

/**
 * Return an array of arrays of size *returnSize.
 * The sizes of the arrays are returned as *returnColumnSizes array.
 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 */
int** queensAttacktheKing(int** queens, int queensSize, int* queensColSize, int* king, int kingSize, int* returnSize, int** returnColumnSizes){
    //many blank, one white, 8x8
    //queens -- blanks, king -- white
    int n=queensSize;
    int pos[8][8]={0};
    for(int i=0;i<n;i++){
        pos[queens[i][0]][queens[i][1]]=1;
    }
    //queen matrix

    int **res=(int**)malloc(sizeof(int)*(2*n));
    *returnColumnSizes=(int*)malloc(sizeof(int)*(2*n));
    *returnSize=0;
    
    int x=king[0],y=king[1];
    int dir[8][2]={
        {1,0},{0,1},{-1,0},{0,-1},{1,1},{-1,1},{1,-1},{-1,-1}
    };
    //direction for attack

    for(int i=0;i<8;i++){
        int tx=x+dir[i][0];
        int ty=y+dir[i][1];
        while(tx>=0 && tx<8 && ty>=0 && ty<8 && pos[tx][ty]!=1){
            tx+=dir[i][0];
            ty+=dir[i][1];
        }//move to the first 

        bool flag=1;
        if(tx<0 || tx>7 || ty<0 || ty>7){
            flag=0;
        }
        if(!flag){
            continue;
        }
        //judge if pos out of range

        if(pos[tx][ty]==1){
            res[*returnSize]=(int*)malloc(sizeof(int)*2);
            (*returnColumnSizes)[(*returnSize)]=2;  //每一个小数组,包含2维
            res[(*returnSize)][0]=tx;
            res[(*returnSize)][1]=ty;
            (*returnSize)++;
        }
    }
    return res;
}

LCP 50 宝石补给(9.15)

欢迎各位勇者来到力扣新手村,在开始试炼之前,请各位勇者先进行「宝石补给」。

每位勇者初始都拥有一些能量宝石, gem[i] 表示第 i 位勇者的宝石数量。现在这些勇者们进行了一系列的赠送,operations[j] = [x, y] 表示在第 j 次的赠送中 第 x 位勇者将自己一半的宝石(需向下取整)赠送给第 y 位勇者。

在完成所有的赠送后,请找到拥有最多宝石的勇者和拥有最少宝石的勇者,并返回他们二者的宝石数量之差

注意:

  • 赠送将按顺序逐步进行。

提示:

  • 2 <= gem.length <= 10^3
  • 0 <= gem[i] <= 10^3
  • 0 <= operations.length <= 10^4
  • operations[i].length == 2
  • 0 <= operations[i][0], operations[i][1] < gem.length

【模拟】temp的那步很抽象,必须单独设置一个中间变量。

int cmp(void *a,void *b){
    return *(int*)a-*(int*)b;
}

int giveGem(int* gem, int gemSize, int** operations, int operationsSize, int* operationsColSize){
    int n=operationsSize;
    for(int i=0;i<n;i++){
        int left=operations[i][0],right=operations[i][1];
        int temp=gem[left]/2;
        gem[left]-=temp;
        gem[right]+=temp;
    }
    qsort(gem,gemSize,sizeof(int),cmp);
    return gem[gemSize-1]-gem[0];
}

198 打家劫舍(9.16)

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警

给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

提示:

  • 1 <= nums.length <= 100
  • 0 <= nums[i] <= 400

【动态规划】
d p [ 0 ] = n u m s [ 0 ] dp[0]=nums[0] dp[0]=nums[0]

d p [ 1 ] = m a x ( n u m s [ 0 ] , n u m s [ 1 ] ) dp[1]=max(nums[0],nums[1]) dp[1]=max(nums[0],nums[1])

d p [ n ] = m a x ( d p [ n − 1 ] , d p [ n − 2 ] + n u m s [ i ] ) , 其中 n > 1 dp[n]=max(dp[n-1],dp[n-2]+nums[i]) ,其中n>1 dp[n]=max(dp[n1],dp[n2]+nums[i]),其中n>1

其中Ⅲ式的含义如下:
d p [ n − 1 ] :打劫过上一家,不能打劫当前家 dp[n-1]:打劫过上一家,不能打劫当前家 dp[n1]:打劫过上一家,不能打劫当前家

d p [ n − 2 ] + n u m s [ i ] :打劫当前家,不能打劫上一家 dp[n-2]+nums[i]:打劫当前家,不能打劫上一家 dp[n2]+nums[i]:打劫当前家,不能打劫上一家

int rob(int* nums, int numsSize){
    //dynamic programming
    if(numsSize==0) return 0;
    else if(numsSize==1) return nums[0];
    else if(numsSize==2) return fmax(nums[0],nums[1]);

    int *dp=malloc(sizeof(int)*numsSize);
    dp[0]=nums[0];
    dp[1]=fmax(nums[0],nums[1]);
    for(int i=2;i<numsSize;i++){
        dp[i]=fmax(dp[i-2]+nums[i],dp[i-1]);
    }
    return dp[numsSize-1];
}

213 打家劫舍Ⅱ(9.17)

你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警

给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。

提示:

  • 1 <= nums.length <= 100
  • 0 <= nums[i] <= 1000

【动态规划】参考灵神的思路

int originrob(int *nums,int start,int end){
    int f0=0,f1=0;
    for(int i=start;i<end;i++){
        int newf=fmax(f1,f0+nums[i]);
        f0=f1;
        f1=newf;
    }
    return f1;
}

int rob(int* nums, int numsSize){
    //环形 考虑是否偷取num[0]
    //偷:dp为num[2],num[n-2]
    //不偷:dp为num[1],num[n-1]
    int n=numsSize;
    return fmax(nums[0]+originrob(nums,2,n-1),originrob(nums,1,n));
}

337 打家劫舍Ⅲ(9.18)

小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root

除了 root 之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。

给定二叉树的 root 。返回 *在不触动警报的情况下 ,小偷能够盗取的最高金额* 。

提示:

  • 树的节点数在 [1, 104] 范围内
  • 0 <= Node.val <= 104

【哈希表 + 动态规划】

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */

//f代表选择当前节点,g代表不选择
//当前节点选择,子节点不能选,f(cur)=g(left)+g(right)
//当前节点不选择,子节点可选可不选,g(cur)=max{f(left),g(left)} + max{f(right),g(right)}

class Solution {
public:
    unordered_map<TreeNode*,int> f,g;

    void dfs(TreeNode* node){
        if(node==NULL) return;
        dfs(node->left);
        dfs(node->right);
        f[node]=node->val+g[node->left]+g[node->right];
        g[node]=max(f[node->left],g[node->left])+max(f[node->right],g[node->right]);
    }

    int rob(TreeNode* root) {
        dfs(root);
        return max(f[root],g[root]);
    }
};
更多推荐

HAM高可用配置及故障切换

1.什么是MHAMHA(MasterHighAvailability)是一套优秀的MySQL高可用环境下故障切换和主从复制的软件。MHA的出现就是解决MySQL单点的问题。MySQL故障切换过程中,MHA能做到0-30秒内自动完成故障切换操作。MHA能在故障切换的过程中最大程度上保证数据的一致性,以达到真正意义上的高可

RK3588修改eth0和eth1,对调这两个网卡设备的名称

1、以太网卡的名称一般是ethX(X可以是0,1,2,3…),一般我们的设备只有一个网卡,并且一般也不会改变它的网卡名称,所以不需要关注此问题,但是有一些设备有两三个网卡,有时候我们需要eth0是指定的硬件网卡设备,此时我们就需要人为干预一下,修改一下网卡的名称,使其满足我们的使用场景。2、在rk平台,假如你的两个网卡

蓝蓝设计提供地理信息系统GIS界面设计

北京蓝蓝设计(北京兰亭妙微科技有限公司)是一家专业的设计公司,致力于为客户打造卓越的用户体验和品牌价值。他们在地理信息系统(GIS)UI界面设计领域拥有丰富的经验和专业的设计团队。他们深入了解地理信息系统的特点和用户需求,通过用户研究和数据分析,精心设计出符合用户习惯和心理的GISUI界面。他们注重界面的布局和排版,确

软文发稿:软文发稿小技巧让你瞬间爆红

欢迎阅读本篇科普文章,我们将为您介绍软文发稿推广的小技巧,帮助您快速在网络平台上获得广泛关注。不仅仅是吸引眼球,我们还将分享实用的策略,帮助您提高软文的质量,提升传播效果。1.精准抓住受众要瞬间爆红,首先要明确目标受众。在撰写软文之前,进行市场调研是必不可少的步骤。了解受众的年龄、性别、兴趣爱好、需求等信息,有助于您编

深圳企业智荟康亮相深圳教装展,大力推动校园健康午休工程

2023年9月15日上午,第五届深圳教育装备博览会在深圳(福田)会展中心隆重开幕。本届教博会以“数字赋能·先行示范”为主题,这场盛会吸引了来自全国各地的众多教育界人士和专业观众。主办方介绍,本次展会将有效推动教育装备领域的技术革新和产业升级,将继续引领行业风向,加速促进产业融合,为各级各类教育机构和教育装备企业提供新技

Python爬虫技术系列-01请求响应获取-urllib库

Python爬虫技术系列-01请求响应获取-urllib库1urllib库1.1urllib概述1.1.1urllib简介1.1.2urllib的robotparser模块1.1.3request模块1.1.4Error1.1.5parse模块1.2urllib高级应用1.2.1Opener1.2.2代理设置1urll

2023常用的原型设计软件推荐

美观易操作的产品原型可以帮助团队构建积极的用户体验,帮助团队理解产品交互逻辑。因此,可互动、易修改的产品原型设计对产品的点击率和回访率具有重要意义。选择专业的产品原型设计工具,可以为团队和企业带来高效的产品设计体验。本文选择了四种产品原型设计工具,可以为实际工作带来方便。让我们看看。即时设计即时设计是国内首款专业级的U

SpringBoot

SpringBoot1.概念和介绍Spring用于简化Java程序的开发,而SpringBoot为了简化Spring程序开发。SpringBoot是Spring脚手架。可以快速完成Java程序的创建、提高开发效率等。SpringBoot的优点:快速集成框架,提供启动依赖的功能,可以集成各种框架。内置了运行容器、无需配置

酷开科技,让家庭娱乐生活充满激情

近几年,随着智能电视在家庭生活中的广泛应用,让人们的家庭娱乐生活有了更多的选择,但随之而来的是消费者的需求也在不断地升级,个性化、细分化的需求趋势越加凸显。而酷开科技正是抓住了这个机遇,不断赋能家庭娱乐生活场景,获得了更多消费者的青睐。与此同时,酷开科技凭借自身包容的开放生态体验,以及为消费者提供更丰富、更多元的内容,

C++实现观察者模式(包含源码)

文章目录观察者模式一、基本概念二、实现方式三、角色四、过程五、结构图六、构建思路七、完整代码观察者模式一、基本概念观察者模式(又被称为模型(Model)-视图(View)模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供

网络编程.

网络编程就相当于通过网络进行数据的传输,可以传给别人,不仅限于自己;常见软件架构BS优点1.不需要开发客户端,只需要页面+服务器2.不用下载缺点如果应用过大cs优点1.画面精美缺点1.客户端,服务端都要开发三要素:IP设备在网络中的地址,是唯一的标识端口号应用程序在设备中唯一的标识协议数据在网络中传输的规则,常见的协议

热文推荐