85. 最大矩形 Maximal Rectangle
给定一个仅包含 0
和 1
、大小为 rows x cols
的二维二进制矩阵,找出只包含 1
的最大矩形,并返回其面积。
示例 1:
输入:matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]
输出:6
解释:最大矩形如上图所示。
示例 2:
输入:matrix = []
输出:0
示例 3:
输入:matrix = [["0"]]
输出:0
示例 4:
输入:matrix = [["1"]]
输出:1
示例 5:
输入:matrix = [["0","0"]]
输出:0
提示:
rows == matrix.length
cols == matrix[0].length
1 <= row, cols <= 200
matrix[i][j]
为'0'
或'1'
代码1:动态规划
package main import ( "fmt" ) func maximalRectangle(matrix [][]byte) int { if len(matrix) == 0 { return 0 } rows, cols := len(matrix), len(matrix[0]) heights := make([]int, cols) maxArea := 0 for i := 0; i < rows; i++ { for j := 0; j < cols; j++ { if matrix[i][j] == '1' { heights[j]++ } else { heights[j] = 0 } } area := largestRectangleArea(heights) if area > maxArea { maxArea = area } } return maxArea } func largestRectangleArea(heights []int) int { stack := make([]int, 0) maxArea := 0 for i := 0; i <= len(heights); i++ { var h int if i == len(heights) { h = 0 } else { h = heights[i] } for len(stack) > 0 && h < heights[stack[len(stack)-1]] { height := heights[stack[len(stack)-1]] stack = stack[:len(stack)-1] var width int if len(stack) == 0 { width = i } else { width = i - stack[len(stack)-1] - 1 } area := height * width if area > maxArea { maxArea = area } } stack = append(stack, i) } return maxArea } func main() { matrix := [][]byte{{'1', '0', '1', '0', '0'}, {'1', '0', '1', '1', '1'}, {'1', '1', '1', '1', '1'}, {'1', '0', '0', '1', '0'}} fmt.Println(maximalRectangle(matrix)) }
代码2: 栈
package main import ( "fmt" ) func maximalRectangle(matrix [][]byte) int { if len(matrix) == 0 { return 0 } rows, cols := len(matrix), len(matrix[0]) heights := make([]int, cols) maxArea := 0 for i := 0; i < rows; i++ { for j := 0; j < cols; j++ { if matrix[i][j] == '1' { heights[j]++ } else { heights[j] = 0 } } area := largestRectangleArea(heights) if area > maxArea { maxArea = area } } return maxArea } func largestRectangleArea(heights []int) int { stack := make([]int, 0) maxArea := 0 for i := 0; i <= len(heights); i++ { var h int if i == len(heights) { h = 0 } else { h = heights[i] } for len(stack) > 0 && h < heights[stack[len(stack)-1]] { height := heights[stack[len(stack)-1]] stack = stack[:len(stack)-1] var width int if len(stack) == 0 { width = i } else { width = i - stack[len(stack)-1] - 1 } area := height * width if area > maxArea { maxArea = area } } stack = append(stack, i) } return maxArea } func main() { matrix := [][]byte{{'1', '0', '1', '0', '0'}, {'1', '0', '1', '1', '1'}, {'1', '1', '1', '1', '1'}, {'1', '0', '0', '1', '0'}} fmt.Println(maximalRectangle(matrix)) }
代码3: 暴力枚举
package main import ( "fmt" ) func maximalRectangle(matrix [][]byte) int { if len(matrix) == 0 { return 0 } rows, cols := len(matrix), len(matrix[0]) maxArea := 0 for i := 0; i < rows; i++ { for j := 0; j < cols; j++ { if matrix[i][j] == '1' { for k := i; k < rows; k++ { for l := j; l < cols; l++ { if isRectangle(matrix, i, j, k, l) { area := (k - i + 1) * (l - j + 1) if area > maxArea { maxArea = area } } } } } } } return maxArea } func isRectangle(matrix [][]byte, i, j, k, l int) bool { for m := i; m <= k; m++ { for n := j; n <= l; n++ { if matrix[m][n] == '0' { return false } } } return true } func main() { matrix := [][]byte{{'1', '0', '1', '0', '0'}, {'1', '0', '1', '1', '1'}, {'1', '1', '1', '1', '1'}, {'1', '0', '0', '1', '0'}} fmt.Println(maximalRectangle(matrix)) }
输出:
6
86. 分隔链表 Partition List
给你一个链表的头节点 head
和一个特定值 x
,请你对链表进行分隔,使得所有 小于x
的节点都出现在 大于或等于x
的节点之前。
你应当 保留 两个分区中每个节点的初始相对位置。
示例 1:
输入:head = [1,4,3,2,5,2], x = 3
输出:[1,2,2,4,3,5]
示例 2:
输入:head = [2,1], x = 2
输出:[1,2]
提示:
- 链表中节点的数目在范围
[0, 200]
内 -100 <= Node.val <= 100
-200 <= x <= 200
代码:
package main import ( "fmt" ) type ListNode struct { Val int Next *ListNode } func partition(head *ListNode, x int) *ListNode { beforeHead := &ListNode{Val: 0, Next: nil} before := beforeHead afterHead := &ListNode{Val: 0, Next: nil} after := afterHead for head != nil { if head.Val < x { before.Next = head before = before.Next } else { after.Next = head after = after.Next } head = head.Next } after.Next = nil before.Next = afterHead.Next return beforeHead.Next } func build(list []int) *ListNode { head := &ListNode{Val: 0} for i := len(list) - 1; i >= 0; i-- { p := &ListNode{Val: list[i]} p.Next = head.Next head.Next = p } return head } func (head *ListNode) travel() { for p := head.Next; p != nil; p = p.Next { fmt.Print(p.Val) if p.Next != nil { fmt.Print("->") } } fmt.Println("<nil>") } func main() { nums := []int{1, 4, 3, 2, 5, 2} head := build(nums) head.travel() partition(head, 3).travel() nums = []int{2, 1} head = build(nums) head.travel() partition(head, 2).travel() }
输出:
1->4->3->2->5->2
1->2->2->4->3->5
2->1
1->2
87. 扰乱字符串 Scramble String
使用下面描述的算法可以扰乱字符串 s
得到字符串 t
:
- 如果字符串的长度为 1 ,算法停止
- 如果字符串的长度 > 1 ,执行下述步骤:
- 在一个随机下标处将字符串分割成两个非空的子字符串。即,如果已知字符串
s
,则可以将其分成两个子字符串x
和y
,且满足s = x + y
。 - 随机 决定是要「交换两个子字符串」还是要「保持这两个子字符串的顺序不变」。即,在执行这一步骤之后,
s
可能是s = x + y
或者s = y + x
。 - 在
x
和y
这两个子字符串上继续从步骤 1 开始递归执行此算法。
给你两个 长度相等 的字符串 s1
和 s2
,判断 s2
是否是 s1
的扰乱字符串。如果是,返回 true
;否则,返回 false
。
示例 1:
输入:s1 = "great", s2 = "rgeat"
输出:true
解释:s1 上可能发生的一种情形是:
"great" --> "gr/eat" // 在一个随机下标处分割得到两个子字符串
"gr/eat" --> "gr/eat" // 随机决定:「保持这两个子字符串的顺序不变」
"gr/eat" --> "g/r / e/at" // 在子字符串上递归执行此算法。两个子字符串分别在随机下标处进行一轮分割
"g/r / e/at" --> "r/g / e/at" // 随机决定:第一组「交换两个子字符串」,第二组「保持这两个子字符串的顺序不变」
"r/g / e/at" --> "r/g / e/ a/t" // 继续递归执行此算法,将 "at" 分割得到 "a/t"
"r/g / e/ a/t" --> "r/g / e/ a/t" // 随机决定:「保持这两个子字符串的顺序不变」
算法终止,结果字符串和 s2 相同,都是 "rgeat"
这是一种能够扰乱 s1 得到 s2 的情形,可以认为 s2 是 s1 的扰乱字符串,返回 true
示例 2:
输入:s1 = "abcde", s2 = "caebd"
输出:false
示例 3:
输入:s1 = "a", s2 = "a"
输出:true
提示:
s1.length == s2.length
1 <= s1.length <= 30
s1
和s2
由小写英文字母组成
代码:
package main import ( "fmt" ) func isScramble(s1 string, s2 string) bool { if s1 == s2 { return true } if len(s1) != len(s2) { return false } size := len(s1) dp := make([][][]bool, size) for i := 0; i < size; i++ { dp[i] = make([][]bool, size) for j := 0; j < size; j++ { dp[i][j] = make([]bool, size+1) dp[i][j][1] = s1[i] == s2[j] } } for l := 2; l <= size; l++ { for i := 0; i <= size-l; i++ { for j := 0; j <= size-l; j++ { for k := 1; k < l; k++ { if (dp[i][j][k] && dp[i+k][j+k][l-k]) || (dp[i][j+l-k][k] && dp[i+k][j][l-k]) { dp[i][j][l] = true break } } } } } return dp[0][0][size] } func main() { s1 := "great" s2 := "rgeat" fmt.Println(isScramble(s1, s2)) s1 = "abcde" s2 = "caebd" fmt.Println(isScramble(s1, s2)) }
输出:
true
false
🌟 每日一练刷题专栏 🌟
✨持续,努力奋斗做强刷题搬运工!
👍 点赞,你的认可是我坚持的动力!
🌟 收藏,你的青睐是我努力的方向!
✎ 评论,你的意见是我进步的财富!
☸ 主页:https://hannyang.blog.csdn.net/