算法题记录 12
1206.设计跳表(困难)
不使用任何库函数,设计一个 跳表 。
跳表 是在 O(log(n)) 时间内完成增加、删除、搜索操作的数据结构。跳表相比于树堆与红黑树,其功能与性能相当,并且跳表的代码长度相较下更短,其设计思想与链表相似。
例如,一个跳表包含 [30, 40, 50, 60, 70, 90] ,然后增加 80、45 到跳表中。
跳表中有很多层,每一层是一个短的链表。在第一层的作用下,增加、删除和搜索操作的时间复杂度不超过 O(n)。跳表的每一个操作的平均时间复杂度是 O(log(n)),空间复杂度是 O(n)。
在本题中,你的设计应该要包含这些函数:
bool search(int target) : 返回target是否存在于跳表中。
void add(int num): 插入一个元素到跳表。
bool erase(int num): 在跳表中删除一个值,如果 num 不存在,直接返回false. 如果存在多个 num ,删除其中任意一个即可。
注意,跳表中可能存在多个相同的值,你的代码需要处理这种情况。
涉及知识点
跳表
解决思路
跳表是一个不怎么被提及,但是效率很高,并且在工业界被广泛使用的数据结构,其核心思想跟操作系统中的多级页表类似,都是采用空间换时间的策略。对于这类特殊的数据结构,进行记忆熟悉保证能复现、使用即可。
1 | class Node: |
3240.最少翻转次数使二进制矩阵回文2(2080)
给你一个 m x n 的二进制矩阵 grid 。
如果矩阵中一行或者一列从前往后与从后往前读是一样的,那么我们称这一行或者这一列是 回文 的。
你可以将 grid 中任意格子的值 翻转 ,也就是将格子里的值从 0 变成 1 ,或者从 1 变成 0 。
请你返回 最少 翻转次数,使得矩阵中 所有 行和列都是 回文的 ,且矩阵中 1 的数目可以被 4 整除 。
涉及知识点
分类讨论
解决思路
该题要讨论的比较复杂,涉及奇偶分析。根据题意,我们可以锁定任意矩形的四角必定为一样的值。若mxn矩阵为边为偶数的矩形,那么就不需要讨论其他情况了。如果边长一奇数、一偶数,那我们要单独判断中间一列或一行的回文。如果是边长都为奇数,那么我们要判断中间一列和中间一行的回文。而锁定任意矩形四角时,0、1的个数都为4的倍数,所以不关1的个数能否被4整除的事。我们只需要对中间的特殊列、行进行奇偶分析即可,如果此时镜像位置相同的1的个数能被4整除,那么镜像位置不同的数对中把1全换成0即可。如果不被4整除,我们考虑两种情况:镜像位置不同的数个数>0,此时需要一对1,而不同的数代表有一个0和一个1,我们只需要把0变成1即可,其它的对数都变成0.如果镜像位置不同的数个数=0,也就是说现在全是1,但是多了一对1。我们就随便选一队1换成0即可。
1 | class Solution: |
999.可以被一步捕获的棋子数(1318)
给定一个 8 x 8 的棋盘,只有一个 白色的车,用字符 ‘R’ 表示。棋盘上还可能存在白色的象 ‘B’ 以及黑色的卒 ‘p’。空方块用字符 ‘.’ 表示。
车可以按水平或竖直方向(上,下,左,右)移动任意个方格直到它遇到另一个棋子或棋盘的边界。如果它能够在一次移动中移动到棋子的方格,则能够 吃掉 棋子。
注意:车不能穿过其它棋子,比如象和卒。这意味着如果有其它棋子挡住了路径,车就不能够吃掉棋子。
返回白车 攻击 范围内 兵的数量。
涉及知识点
表格
解决思路
秒答题,要模拟车的移动解题可以,记录象和卒的位置进行数学判断也可以。
1 | class Solution: |
2286.以组为单位订音乐会的门票(2470)
一个音乐会总共有 n 排座位,编号从 0 到 n - 1 ,每一排有 m 个座椅,编号为 0 到 m - 1 。你需要设计一个买票系统,针对以下情况进行座位安排:
同一组的 k 位观众坐在 同一排座位,且座位连续 。
k 位观众中 每一位 都有座位坐,但他们 不一定 坐在一起。
由于观众非常挑剔,所以:
只有当一个组里所有成员座位的排数都 小于等于 maxRow ,这个组才能订座位。每一组的 maxRow 可能 不同 。
如果有多排座位可以选择,优先选择 最小 的排数。如果同一排中有多个座位可以坐,优先选择号码 最小 的。
请你实现 BookMyShow 类:
BookMyShow(int n, int m) ,初始化对象,n 是排数,m 是每一排的座位数。
int[] gather(int k, int maxRow) 返回长度为 2 的数组,表示 k 个成员中 第一个座位 的排数和座位编号,这 k 位成员必须坐在 同一排座位,且座位连续 。换言之,返回最小可能的 r 和 c 满足第 r 排中 [c, c + k - 1] 的座位都是空的,且 r <= maxRow 。如果 无法 安排座位,返回 [] 。
boolean scatter(int k, int maxRow) 如果组里所有 k 个成员 不一定 要坐在一起的前提下,都能在第 0 排到第 maxRow 排之间找到座位,那么请返回 true 。这种情况下,每个成员都优先找排数 最小 ,然后是座位编号最小的座位。如果不能安排所有 k 个成员的座位,请返回 false 。
涉及知识点
线段树
解决思路
无论怎么卖票都不会出现空隙
一个[m] * n 数组记录每排左到哪了
一个区间极小线段树(m - 区间极小就是区间的最大连座数),给 gather 用
一个区间和线段树,给 scatter 用
外加一个minFull指针,也是给 scatter 用的,记录从左往右已经卖完票的最大排号
线段树的实现可以上leetcode看解析。
1 | class BookMyShow: |
声明
题目均来源于leetcode公开题库,部分方法解析来源于高赞题解,如有不妥请联系。