Golang每日一练(leetDay0029) 最大矩形、分隔链表、扰乱字符串

简介: Golang每日一练(leetDay0029) 最大矩形、分隔链表、扰乱字符串

85. 最大矩形 Maximal Rectangle

给定一个仅包含 01 、大小为 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 ,算法停止
  2. 如果字符串的长度 > 1 ,执行下述步骤:
  • 在一个随机下标处将字符串分割成两个非空的子字符串。即,如果已知字符串 s ,则可以将其分成两个子字符串 xy ,且满足 s = x + y
  • 随机 决定是要「交换两个子字符串」还是要「保持这两个子字符串的顺序不变」。即,在执行这一步骤之后,s 可能是 s = x + y 或者 s = y + x
  • xy 这两个子字符串上继续从步骤 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
  • s1s2 由小写英文字母组成

代码:

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/


目录
相关文章
|
5月前
|
存储 算法
LeetCode第86题分隔链表
文章介绍了LeetCode第86题"分隔链表"的解法,通过创建两个新链表分别存储小于和大于等于给定值x的节点,然后合并这两个链表来解决问题,提供了一种简单易懂且操作原链表的解决方案。
LeetCode第86题分隔链表
|
5月前
|
存储 Python
【Leetcode刷题Python】86.分隔链表
通过使用两个虚拟节点(dummy nodes)来分别收集小于特定值 x 的节点和大于等于 x 的节点,最终将这两部分链表合并起来形成结果链表。
36 0
|
7月前
|
存储 SQL 算法
LeetCode 题目 86:分隔链表
LeetCode 题目 86:分隔链表
|
8月前
|
Rust 索引
Rust 编程小技巧摘选(6)
Rust 编程小技巧摘选(6)
89 1
Rust 编程小技巧摘选(6)
|
8月前
|
Shell Linux 算法
Shell编程——弱数据类型的脚本语言快速入门指南
Shell编程——弱数据类型的脚本语言快速入门指南
97 0
Shell编程——弱数据类型的脚本语言快速入门指南
|
8月前
|
Go Linux Shell
Linux 终端命令之文件浏览(2) more
Linux 终端命令之文件浏览(2) more
68 0
Linux 终端命令之文件浏览(2) more
|
8月前
|
Go Python Rust
Rust 编程小技巧摘选(7)
Rust 编程小技巧摘选(7)
131 0
Rust 编程小技巧摘选(7)
|
8月前
|
Python Linux Ubuntu
Linux系统部署Python语言开发运行环境
Linux系统部署Python语言开发运行环境
238 0
Linux系统部署Python语言开发运行环境
|
7月前
|
存储 SQL 算法
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
|
7月前
|
存储 算法 Java
【经典算法】Leetcode 141. 环形链表(Java/C/Python3实现含注释说明,Easy)
【经典算法】Leetcode 141. 环形链表(Java/C/Python3实现含注释说明,Easy)
66 2