本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问。

周赛 347 概览

T1. 移除字符串中的尾随零(Easy)

  • 标签:模拟、字符串

T2. 对角线上不同值的数量差(Easy)

  • 标签:前后缀分解

T3. 使所有字符相等的最小成本(Medium)

  • 标签:模拟、贪心

T4. 矩阵中严格递增的单元格数(Hard)

  • 标签:排序、动态规划


T1. 移除字符串中的尾随零(Easy)

https://leetcode.cn/problems/remove-trailing-zeros-from-a-string/

题解(模拟)

基于 StringBuilder:

class Solution {
fun removeTrailingZeros(num : String): String {
if (num.length == 1) return num
val builder = StringBuilder(num)
while (builder.last() == '0') {
builder.deleteCharAt(builder.lastIndex)
}
return builder.toString()
}
}

基于正则表达式匹配:

class Solution {
fun removeTrailingZeros(num : String): String {
return num.replace(Regex("0*$"), "")
}
}

复杂度分析:

  • 时间复杂度:$O(n)$
  • 空间复杂度:$O(1)$ 不考虑结果字符串

T2. 对角线上不同值的数量差(Easy)

https://leetcode.cn/problems/difference-of-number-of-distinct-values-on-diagonals/

题解(前后缀分解)

第一次扫描增加正权,第二次扫描增加负权:

class Solution {
fun differenceOfDistinctValues(grid: Array<IntArray>): Array<IntArray> {
// 两次扫描
val n = grid.size
val m = grid[0].size
val ret = Array(n) { IntArray(m) } for (row in 0 until n) {
var i = row
var j = 0
val set = HashSet<Int>()
while (i < n && j < m) {
ret[i][j] += set.size
set.add(grid[i][j])
i++
j++
}
} for (col in 1 until m) {
var i = 0
var j = col
val set = HashSet<Int>()
while (i < n && j < m) {
ret[i][j] = set.size
set.add(grid[i][j])
i++
j++
}
} for (row in 0 until n) {
var i = row
var j = m - 1
val set = HashSet<Int>()
while (i >= 0 && j >= 0) {
ret[i][j] = Math.abs(ret[i][j] - set.size)
set.add(grid[i][j])
i--
j--
}
} for (col in 0 until m - 1) {
var i = n - 1
var j = col
val set = HashSet<Int>()
while (i >= 0 && j >= 0) {
ret[i][j] = Math.abs(ret[i][j] - set.size)
set.add(grid[i][j])
i--
j--
}
}
return ret
}
}

复杂度分析:

  • 时间复杂度:$O(nm)$
  • 空间复杂度:$O(nm)$

T3. 使所有字符相等的最小成本(Medium)

https://leetcode.cn/problems/minimum-cost-to-make-all-characters-equal/

题解一(模拟)

从中间开始翻转,将不符合目标的字符向两端推,选择反转到 ‘1’ 和 ‘0’ 两个方案的最优解:

class Solution {

    private fun op(s:String, target:Char) :Long {
val n = s.length
var ret = 0L
var flag = true
for (i in n / 2 - 1 downTo 0) {
if ((flag && s[i] != target) || (!flag && s[i] == target)) {
ret += i + 1
flag = !flag
}
}
flag = true
for (i in n / 2 until n) {
if ((flag && s[i] != target) || (!flag && s[i] == target)) {
ret += n - i
flag = !flag
}
}
return ret
} fun minimumCost(s: String): Long {
return Math.min(op(s,'0'), op(s,'1'))
}
}

复杂度分析:

  • 时间复杂度:$O(n)$
  • 空间复杂度:$O(1)$

题解二(找规律)

当相邻字符串不相等时,必然需要反转。如果接近左边往左边翻转的成本更低,同时,如果接近右边,往右边翻转的成本更低。

class Solution {
fun minimumCost(s: String): Long {
val n = s.length
var ret = 0L
for (i in 1 until n) {
if (s[i - 1] != s[i]) {
ret += Math.min(i, n - i)
}
}
return ret
}
}

复杂度分析:

  • 时间复杂度:$O(n)$
  • 空间复杂度:$O(1)$

T4. 矩阵中严格递增的单元格数(Hard)

https://leetcode.cn/problems/maximum-strictly-increasing-cells-in-a-matrix/
  • 错误思路:

从最大值开始逆向推导,但是最优路径不一定会经过最大值。

  • 正确思路:

只有小的数字才能到大的数字,因此我们先将所有数字进行排序,对于每个数字储存其对应的所有位置。此时,每个位置的 LIS 最长序列长度只跟其排序前面的数字中位于同行和同列的数字有关,即前面数字且处于同行同列的最长路径 + 1。

class Solution {
fun maxIncreasingCells(mat: Array<IntArray>): Int {
val n = mat.size
val m = mat[0].size
var ret = 0
// 排序
val map = TreeMap<Int, MutableList<IntArray>>()
for (i in 0 until n) {
for (j in 0 until m) {
map.getOrPut(mat[i][j]) { LinkedList<IntArray>() }.add(intArrayOf(i, j))
}
}
val rowMax = IntArray(n)
val colMax = IntArray(m)
// 枚举
for ((x, indexs) in map) {
val mx = IntArray(indexs.size)
// LIS
for (i in indexs.indices) {
mx[i] = Math.max(rowMax[indexs[i][0]], colMax[indexs[i][1]]) + 1
ret = Math.max(ret, mx[i])
}
for (i in indexs.indices) {
rowMax[indexs[i][0]] = Math.max(rowMax[indexs[i][0]], mx[i])
colMax[indexs[i][1]] = Math.max(colMax[indexs[i][1]], mx[i])
}
}
return ret
}
}

复杂度分析:

  • 时间复杂度:$O(nm·lg(nm))$ 瓶颈在排序
  • 空间复杂度:$O(nm)$

往期回顾

LeetCode 周赛 347(2023/05/28)二维空间上的 LIS 最长递增子序列问题的更多相关文章

  1. Leetcode 673.最长递增子序列的个数

    最长递增子序列的个数 给定一个未排序的整数数组,找到最长递增子序列的个数. 示例 1: 输入: [1,3,5,4,7] 输出: 2 解释: 有两个最长递增子序列,分别是 [1, 3, 4, 7] 和[ ...

  2. 【LeetCode动态规划#14】子序列系列题(最长递增子序列、最长连续递增序列、最长重复子数组、最长公共子序列)

    最长递增子序列 力扣题目链接(opens new window) 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度. 子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其 ...

  3. [LeetCode] Longest Increasing Path in a Matrix 矩阵中的最长递增路径

    Given an integer matrix, find the length of the longest increasing path. From each cell, you can eit ...

  4. [LeetCode] Longest Increasing Subsequence 最长递增子序列

    Given an unsorted array of integers, find the length of longest increasing subsequence. For example, ...

  5. [LeetCode] 300. Longest Increasing Subsequence 最长递增子序列

    Given an unsorted array of integers, find the length of longest increasing subsequence. Example: Inp ...

  6. [leetcode]300. Longest Increasing Subsequence最长递增子序列

    Given an unsorted array of integers, find the length of longest increasing subsequence. Example: Inp ...

  7. leetcode最长递增子序列问题

    题目描写叙述: 给定一个数组,删除最少的元素,保证剩下的元素是递增有序的. 分析: 题目的意思是删除最少的元素.保证剩下的元素是递增有序的,事实上换一种方式想,就是寻找最长的递增有序序列.解法有非常多 ...

  8. Java实现 LeetCode 673 最长递增子序列的个数(递推)

    673. 最长递增子序列的个数 给定一个未排序的整数数组,找到最长递增子序列的个数. 示例 1: 输入: [1,3,5,4,7] 输出: 2 解释: 有两个最长递增子序列,分别是 [1, 3, 4, ...

  9. Java实现 LeetCode 583 两个字符串的删除操作(求最长公共子序列问题)

    583. 两个字符串的删除操作 给定两个单词 word1 和 word2,找到使得 word1 和 word2 相同所需的最小步数,每步可以删除任意一个字符串中的一个字符. 示例: 输入: " ...

  10. 【LeetCode】300.最长递增子序列——暴力递归(O(n^3)),动态规划(O(n^2)),动态规划+二分法(O(nlogn))

    算法新手,刷力扣遇到这题,搞了半天终于搞懂了,来这记录一下,欢迎大家交流指点. 题目描述: 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度. 子序列是由数组派生而来的序列,删除(或不删 ...

随机推荐

  1. 自己动手从零写桌面操作系统GrapeOS系列教程——17.用汇编语言清空屏幕

    学习操作系统原理最好的方法是自己写一个简单的操作系统. 在QEMU中会默认输出一些字符,有时候会干扰我们自己输出的字符.一个比较好的办法是向将屏幕清空,再输出我们想要输出的字符.下面就来学习如何清空屏 ...

  2. 如何获取obs视频帧的二进制数据

    前面几篇文章梳理了obs的录屏和推流流程,几条纵线整理下来,算是基本理清了obs的工作流程. 现在回到第一个目标:捕捉桌面的帧数据,用rendertarget显示并输出到UE5材质. 那么,帧数据到底 ...

  3. java创建线程的方式有几种?

    java中创建线程的方式有多少种,这个问题也是众多纷纭,这个时候更应该参考官方文档(https://docs.oracle.com/javase/8/docs/api/java/lang/Thread ...

  4. HTTP TCP UDP WEBSOCKET

    概念: TCP和UDP:传输层协议:(卡车) HTTP:应用层协议:(货物).HTTP(超文本传输协议)是利用TCP在两台电脑(通常是Web服务器和客户端)之间传输信息的协议.客户端使用Web浏览器发 ...

  5. SQL Server修改sa用户密码

     SQL Server数据库使用windows用户登录,安全性->登录名->找到sa用户->属性: 可直接修改sa用户密码(可去掉勾选强制实施密码策略)

  6. React的行内样式与CSS

    如何为组件添加 CSS 的 class? 传递一个字符串作为 className 属性: render() { return <span className="menu navigat ...

  7. w32模块模拟鼠标键盘操作

    win32api.keybd_event 该函数原型:keybd_event(bVk, bScan, dwFlags, dwExtraInfo) 第一个参数:虚拟键码(键盘键码对照表见附录): 第二个 ...

  8. odbe简介

    Odbc简介 今天工作中遇到一个问题,缺少某个数据库驱动程序,百度半天才发现原来室odbc原因,所以,就捎带学习了一下odbc, ODBC数据源中文名称:开放数据库互联英文名称:Open Databa ...

  9. python去掉重复值的方法--四种

    my_list = [1,1,1,1,2,3,3,3,4,5,5,56,6,7,77,7,5,5,3]# 集合法:缺点是结果会打乱原始数据的顺序print(set(my_list)) # 列表法:缺点 ...

  10. LeeCode 栈与队列问题(一)

    LeeCode 20: 有效的括号 题目描述 给定一个只包括 '(', ')', '{', '}', '[', ']' 的字符串s,判断字符串是否有效. 有效字符串满足: 左括号必须用相同类型的右括号 ...