Leetcode 问题

个人编程笔记

思路

  • 序列计数问题,先考虑DP
  • 最大化最小值,最小化最大值,最优化问题,考虑二分答案
  • 求第k小,二分答案,判定ok:找出小于或者等于x的数量,这个数量必须大于等于k,二分这个满足这个条件的最小值
  • 环链转换,对于环的问题,考虑第一个和最后一个元素的关系,在环上他们是相邻的,在链上不是,通过分类讨论他们是不是都选、都不选、选哪一个分成几种情况按链进行处理
  • 循环数组,将其复制一份构造一个长度为2*n的数组进行处理
  • 出现次数相同 出现次数为偶数 -> 异或为0 -> 前缀异或和

debug

  • l 写成 1 ,找半天没找出来 (别用 l 做变量名, left, right, lo, hi, st, ed)
  • 不带引用TLE,带了AC:for (auto &e : edges) {}
  • 带了引用runtime error,不带AC:auto [x, d] = queue.front(); queue.pop()
  • 下标数组最好预留buffer,不要写a[n],永远写a[n+1];
  • 传入的参数里已经有k/m/n之类的常用变量,注意不要重复定义变量覆盖了原先的值,找半天找不出来
  • sort的时候看排序的是什么,如果是vector之类的要用引用,不然TLE

问题

  • 1 两数之和 - 数组中找到和为t的两个数
    枚举第二个数,维护见过数字的哈希表,在里面查找第一个数

  • 9980 不同路径数 - 有障碍的二维矩阵起点到终点经过所有点的路径数目
    假如当前在某个点,枚举四个方向的,dfs往这个方向走一步的方案数。由于需要经过所有点,点数不超过20,考虑使用状态压缩使用20位保存一个点是否访问过的状态。dfs过程中可能重复状态,考虑根据 (x, y, state)进行记忆化搜索,然后三个数字可以进一步压缩为一个数字。

  • 1235 规划工作 - 给(startTime, endTime, profit)数组,安排工作求最大工资
    类似背包:f[i] = max(f[i-1], f[j] + profit[i]),j为在startTime[i]前的第一个区间(<=x 的最大数,upper_bound再减一得到)
    为了避免-1负数,把f的下标都+1:f[i+1] = max(f[i], f[j+1] +profit[i]),相当于f数组的意义都向右推了一格
    profit的下标不变,遍历时还是[0,n)

  • 1388 3n块披萨 - 每次选一块,相邻两块会被选走,求最大和
    问题等价于在长为3n的环上选n个不相邻的数字,和最大。考虑第一个和最后一个数字转环为链,他们不能同时选择,分两次处理,第一次删第一个元素,第二次删最后一个元素,求两次的链最大和的较大一个。
    链上问题可以dp解决
    状态:dp[i][j] - 前i个数字中选择了j个数字的最大和
    转移:dp[i][j] = max(dp[i-1][j], dp[i-2][j-1] + a[i]),第i个数要么选要么不选

  • 1547 切棍子最小成本 - 长为n的棍子,每次切成本为棍子长度,给定若干个切割点
    给定一个棍子,首先切成两半,两半分别是长度更短的子问题,考虑区间DP。每次切割,棍子左端点要么是0,要么是前面某次切割的断点,右端点同理,考虑往切割数组中加入0和n简化处理。
    状态:dp[i][j] 切割数组中[i,j]切完的最小成本
    转移:dp[i][j] = max(dp[i][k] + dp[k][j]) + len(i, j)

  • 1928 规定时间内到达终点的最小花费 - 带权无向图每个点有费用,每条边有时间,起点到终点的在时间内最小费用
    状态: dp[t][i] 在时间t到达城市i的最小费用
    转移: dp[t][i] = min(dp[t-cost(i,j)][j]) +fee(i),枚举能够到达i的所有城市j取最小值

  • 1937 矩阵最大得分 - 每行取一个数,相邻两行的数代价为列数的差的绝对值
    从上往下逐行处理,处理第i行的数字时枚举第i-1行的结果求max
    状态:dp[i][j]表示处理到第i行,并且第i行选了第j个数时的最大得分
    转移:dp[i][j] = a[i][j] + max(dp[i-1][k] - abs(j - k)),对于每个i j要枚举k,复杂度为o(m*n^2),太高。去掉绝对值为
    dp[i][j] = a[i][j] + max(dp[i-1][k] + k) - j, k <= j
    max(dp[i-1][k] - k) + j, k > j
    则可以在遍历j的时候顺便维护关于k的最值,分从左到右和从右到左两次遍历,维护dp[i-1][k]+k 和 dp[i-1][k]-k的最大值。

  • 1944 队列看到的人数 - 给身高数组,一个人能看到右边一个人如果他们之间所有人比他们矮
    i能看到j,j左边不能有比j高的(都 <j),有单调递增的性质。从后往前扫描,如果栈顶比当前数小,栈顶没有意义了,因为后面扫描的数都看不到他,因为他被当前数挡住了,弹出。
    答案在出栈的时候加1,最后栈不空说明还有一个比当前数大的,还加1。

  • 2209 覆盖后的最少白色块 - 用若干个长度相同的黑色地毯覆盖一维黑白地面
    从左往右处理(枚举右端点),用地毯覆盖后缀后,剩下的前缀是个类似的子问题。
    状态:dp[i][j] 用i个地毯覆盖[0,j]地板的最少剩余白色块
    转移:dp[i][j] = max(dp[i][j-1], dp[i-1][j-len]),第j块要么不填,要么填
    枚举j时可以从ilen开始枚举,当j < ilen时,地板可以完全覆盖,答案为0

  • 2430 删除字符串最大步数 - 每次删除整串 或者 前i个字符(如果后面i个字符相同)
    每次删除前缀后,剩下的后缀是一个类似的子问题,考虑使用后缀作为状态进行DP
    状态:dp[i],s[i:]的最大删除步数
    转移:枚举删除长度,dp[i] = max(dp[i+len] + 1),枚举删除长度时需要判断两个子串的前缀,预处理这个信息然后O(1)判断
    预处理:lcp[i][j]表示s[i:]和s[j:]的最长公共前缀,则lcp[i][i+len] > len时可以删除这len个字符,lcp本身dp预处理:lcp[i+1][j+1] + 1

  • 2747 没有收到请求的服务器数目 - 给定请求记录数组(server, time),查询窗口长度和查询时间点数组,求不在查询窗口内的服务器数量
    查询窗口长度固定,考虑将查询排序再滑动窗口,将请求记录按时间排序,枚举每个查询,移动前指针添加元素进去,移动后指针移除元素),使用map维护窗口内的元素及数量

  • 6957 范围内步进数字(相邻数字差1)数目
    状态:dp[i][x],前i位最后一位为x的数目
    转移:dp[i][x] = sum(dp[i+1][y]),y满足和x相差1(如果是第一个数字,则可以为任意数字)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值