Golang每日一练(leetDay0042) 二叉树最大路径和、回文串、单词接龙II

简介: Golang每日一练(leetDay0042) 二叉树最大路径和、回文串、单词接龙II

124. 二叉树中的最大路径和 Binary-tree-maximum-path-sum

路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。

路径和 是路径中各节点值的总和。

给你一个二叉树的根节点 root ,返回其 最大路径和

示例 1:

输入:root = [1,2,3]

输出:6

解释:最优路径是 2 -> 1 -> 3 ,路径和为 2 + 1 + 3 = 6

示例 2:

输入:root = [-10,9,20,null,null,15,7]

输出:42

解释:最优路径是 15 -> 20 -> 7 ,路径和为 15 + 20 + 7 = 42


提示:

  • 树中节点数目范围是 [1, 3 * 104]
  • -1000 <= Node.val <= 1000

代码1: 递归

package main
import (
  "fmt"
)
const null = -1 << 31
type TreeNode struct {
  Val   int
  Left  *TreeNode
  Right *TreeNode
}
func maxPathSum(root *TreeNode) int {
  if root == nil {
    return 0
  }
  res := root.Val
  maxPathSumHelper(root, &res)
  return res
}
func maxPathSumHelper(node *TreeNode, res *int) int {
  if node == nil {
    return 0
  }
  leftMax := max(0, maxPathSumHelper(node.Left, res))
  rightMax := max(0, maxPathSumHelper(node.Right, res))
  *res = max(*res, leftMax+rightMax+node.Val)
  return max(leftMax, rightMax) + node.Val
}
func max(a, b int) int {
  if a > b {
    return a
  }
  return b
}
func buildTree(nums []int) *TreeNode {
  if len(nums) == 0 {
    return nil
  }
  root := &TreeNode{Val: nums[0]}
  Queue := []*TreeNode{root}
  idx := 1
  for idx < len(nums) {
    node := Queue[0]
    Queue = Queue[1:]
    if nums[idx] != null {
      node.Left = &TreeNode{Val: nums[idx]}
      Queue = append(Queue, node.Left)
    }
    idx++
    if idx < len(nums) && nums[idx] != null {
      node.Right = &TreeNode{Val: nums[idx]}
      Queue = append(Queue, node.Right)
    }
    idx++
  }
  return root
}
func main() {
  nums := []int{1, 2, 3}
  root := buildTree(nums)
  fmt.Println(maxPathSum(root))
  nums = []int{-10, 9, 20, null, null, 15, 7}
  root = buildTree(nums)
  fmt.Println(maxPathSum(root))
}

代码2: DFS

package main
import (
  "fmt"
)
const null = -1 << 31
type TreeNode struct {
  Val   int
  Left  *TreeNode
  Right *TreeNode
}
func maxPathSum(root *TreeNode) int {
  if root == nil {
    return 0
  }
  res := root.Val
  stack := []*TreeNode{root}
  visited := make(map[*TreeNode]bool)
  visited[root] = true
  for len(stack) > 0 {
    node := stack[len(stack)-1]
    if node.Left != nil && !visited[node.Left] {
      stack = append(stack, node.Left)
      visited[node.Left] = true
    } else if node.Right != nil && !visited[node.Right] {
      stack = append(stack, node.Right)
      visited[node.Right] = true
    } else {
      stack = stack[:len(stack)-1]
      leftMax := 0
      if node.Left != nil {
        leftMax = max(0, node.Left.Val)
      }
      rightMax := 0
      if node.Right != nil {
        rightMax = max(0, node.Right.Val)
      }
      res = max(res, leftMax+rightMax+node.Val)
      node.Val = max(leftMax, rightMax) + node.Val
      if len(stack) > 0 {
        parent := stack[len(stack)-1]
        if parent.Left == node {
          parent.Left = node
        } else {
          parent.Right = node
        }
      }
    }
  }
  return res
}
func max(a, b int) int {
  if a > b {
    return a
  }
  return b
}
func buildTree(nums []int) *TreeNode {
  if len(nums) == 0 {
    return nil
  }
  root := &TreeNode{Val: nums[0]}
  Queue := []*TreeNode{root}
  idx := 1
  for idx < len(nums) {
    node := Queue[0]
    Queue = Queue[1:]
    if nums[idx] != null {
      node.Left = &TreeNode{Val: nums[idx]}
      Queue = append(Queue, node.Left)
    }
    idx++
    if idx < len(nums) && nums[idx] != null {
      node.Right = &TreeNode{Val: nums[idx]}
      Queue = append(Queue, node.Right)
    }
    idx++
  }
  return root
}
func main() {
  nums := []int{1, 2, 3}
  root := buildTree(nums)
  fmt.Println(maxPathSum(root))
  nums = []int{-10, 9, 20, null, null, 15, 7}
  root = buildTree(nums)
  fmt.Println(maxPathSum(root))
}

输出:

6

42


125. 验证回文串 Valid Palindrome

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。

说明:本题中,我们将空字符串定义为有效的回文串。

示例 1:

输入: "A man, a plan, a canal: Panama"

输出: true

解释:"amanaplanacanalpanama" 是回文串


示例 2:

输入: "race a car"

输出: false

解释:"raceacar" 不是回文串


提示:

  • 1 <= s.length <= 2 * 10^5
  • 字符串 s 由 ASCII 字符组成

代码1: 双指针

package main
import (
  "fmt"
  "strings"
)
func isPalindrome(s string) bool {
  if len(s) == 0 {
    return true
  }
  s = strings.ToLower(s)
  left, right := 0, len(s)-1
  for left < right {
    if !isAlphanumeric(s[left]) {
      left++
      continue
    }
    if !isAlphanumeric(s[right]) {
      right--
      continue
    }
    if s[left] != s[right] {
      return false
    }
    left++
    right--
  }
  return true
}
func isAlphanumeric(c byte) bool {
  return ('a' <= c && c <= 'z') || ('0' <= c && c <= '9')
}
func main() {
  s := "A man, a plan, a canal: Panama"
  fmt.Println(isPalindrome(s))
  s = "race a car"
  fmt.Println(isPalindrome(s))
}

输出:

true

false

代码2: 正则表达式

package main
import (
  "fmt"
  "regexp"
  "strings"
)
func isPalindrome(s string) bool {
  if len(s) == 0 {
    return true
  }
  s = strings.ToLower(s)
  reg, _ := regexp.Compile("[^a-z0-9]+")
  s = reg.ReplaceAllString(s, "")
  return isPalindromeHelper(s)
}
func isPalindromeHelper(s string) bool {
  left, right := 0, len(s)-1
  for left < right {
    if s[left] != s[right] {
      return false
    }
    left++
    right--
  }
  return true
}
func main() {
  s := "A man, a plan, a canal: Panama"
  fmt.Println(isPalindrome(s))
  s = "race a car"
  fmt.Println(isPalindrome(s))
}

126. 单词接龙 II Word Ladder II

按字典 wordList 完成从单词 beginWord 到单词 endWord 转化,一个表示此过程的 转换序列 是形式上像 beginWord -> s1 -> s2 -> ... -> sk 这样的单词序列,并满足:

  • 每对相邻的单词之间仅有单个字母不同。
  • 转换过程中的每个单词 si1 <= i <= k)必须是字典 wordList 中的单词。注意,beginWord 不必是字典 wordList 中的单词。
  • sk == endWord

给你两个单词 beginWordendWord ,以及一个字典 wordList 。请你找出并返回所有从 beginWordendWord最短转换序列 ,如果不存在这样的转换序列,返回一个空列表。每个序列都应该以单词列表 [beginWord, s1, s2, ..., sk] 的形式返回。

示例 1:

输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]

输出:[["hit","hot","dot","dog","cog"],["hit","hot","lot","log","cog"]]

解释:存在 2 种最短的转换序列:

"hit" -> "hot" -> "dot" -> "dog" -> "cog"

"hit" -> "hot" -> "lot" -> "log" -> "cog"


示例 2:

输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"]

输出:[]

解释:endWord "cog" 不在字典 wordList 中,所以不存在符合要求的转换序列。


提示:

  • 1 <= beginWord.length <= 5
  • endWord.length == beginWord.length
  • 1 <= wordList.length <= 5000
  • wordList[i].length == beginWord.length
  • beginWordendWordwordList[i] 由小写英文字母组成
  • beginWord != endWord
  • wordList 中的所有单词 互不相同

代码:

package main
import (
  "fmt"
)
func findLadders(beginWord string, endWord string, wordList []string) [][]string {
  result, wordMap := make([][]string, 0), make(map[string]bool)
  for _, w := range wordList {
    wordMap[w] = true
  }
  if !wordMap[endWord] {
    return result
  }
  queue := make([][]string, 0)
  queue = append(queue, []string{beginWord})
  queueLen := 1
  levelMap := make(map[string]bool)
  for len(queue) > 0 {
    path := queue[0]
    queue = queue[1:]
    lastWord := path[len(path)-1]
    for i := 0; i < len(lastWord); i++ {
      for c := 'a'; c <= 'z'; c++ {
        nextWord := lastWord[:i] + string(c) + lastWord[i+1:]
        if nextWord == endWord {
          path = append(path, endWord)
          result = append(result, path)
          continue
        }
        if wordMap[nextWord] {
          levelMap[nextWord] = true
          newPath := make([]string, len(path))
          copy(newPath, path)
          newPath = append(newPath, nextWord)
          queue = append(queue, newPath)
        }
      }
    }
    queueLen--
    if queueLen == 0 {
      if len(result) > 0 {
        break
      }
      for k := range levelMap {
        delete(wordMap, k)
      }
      levelMap = make(map[string]bool)
      queueLen = len(queue)
    }
  }
  return result
}
func main() {
  beginWord, endWord := "hit", "cog"
  wordList := []string{"hot", "dot", "dog", "lot", "log", "cog"}
  fmt.Println(findLadders(beginWord, endWord, wordList))
  wordList = []string{"hot", "dot", "dog", "lot", "log"}
  fmt.Println(findLadders(beginWord, endWord, wordList))
}

输出:

[[hit hot dot dog cog] [hit hot lot log cog]]

[]


🌟 每日一练刷题专栏 🌟

持续,努力奋斗做强刷题搬运工!

👍 点赞,你的认可是我坚持的动力!

🌟 收藏,你的青睐是我努力的方向!

评论,你的意见是我进步的财富!  

主页:https://hannyang.blog.csdn.net/


目录
相关文章
|
1月前
|
测试技术 Python
Python接口自动化测试框架(基础篇)-- 流程控制之循环语句for&while
本文介绍了Python中的循环语句,包括while和for循环的使用,range()函数的运用,以及continue、break和pass关键字的说明,同时提出了关于while循环是否能与成员运算符结合使用的思考。
36 1
Python接口自动化测试框架(基础篇)-- 流程控制之循环语句for&while
|
1月前
|
Python
揭秘Python编程核心:一篇文章带你深入掌握for循环与while循环的奥秘!
【8月更文挑战第21天】Python中的循环结构——for循环与while循环,是编程的基础。for循环擅长遍历序列或集合中的元素,如列表或字符串;而while循环则在未知循环次数时特别有用,基于某个条件持续执行。本文通过实例展示两种循环的应用场景,比如用for循环计算数字平方和用while循环计算阶乘。此外,还通过案例分析比较了两者在处理用户输入任务时的不同优势,强调了根据实际需求选择合适循环的重要性。
39 0
|
1月前
|
索引 Python
【Leetcode刷题Python】328. 奇偶链表
在不使用额外空间的情况下,将链表中的奇数和偶数索引节点重新排序的方法,并提供了相应的Python实现代码。
30 0
|
1月前
|
Python
【Leetcode刷题Python】25.K 个一组翻转链表
解决LeetCode "K 个一组翻转链表" 问题的三种方法:使用栈、尾插法和虚拟节点顺序法,并提供了每种方法的Python实现代码。
27 0
|
1天前
|
Python
Python 中如何循环某一特定列的所有行数据
Python 中如何循环某一特定列的所有行数据
|
15天前
|
存储 前端开发 索引
11个Python循环技巧
本文介绍了在Python中使用循环创建多个列表的方法,并提供了丰富的代码示例。内容涵盖根据固定数量、条件、数据类型、属性、索引范围、哈希值等不同条件创建列表的技巧,展示了如何灵活运用循环和列表推导式,提高代码的灵活性与可维护性,加速开发流程并提升程序性能。
|
1月前
|
搜索推荐 Python
Python基础编程:冒泡排序和选择排序的另一种while循环实现
这篇文章介绍了Python中冒泡排序和选择排序的实现,提供了使用while循环的替代方法,并展示了排序算法的运行结果。
20 2
Python基础编程:冒泡排序和选择排序的另一种while循环实现
|
18天前
|
存储 算法 C语言
C语言手撕实战代码_循环单链表和循环双链表
本文档详细介绍了用C语言实现循环单链表和循环双链表的相关算法。包括循环单链表的建立、逆转、左移、拆分及合并等操作;以及双链表的建立、遍历、排序和循环双链表的重组。通过具体示例和代码片段,展示了每种算法的实现思路与步骤,帮助读者深入理解并掌握这些数据结构的基本操作方法。
|
1天前
|
Python
python如何循环某一特定列的所有行数据
python如何循环某一特定列的所有行数据
|
1月前
|
Python
【Leetcode刷题Python】114. 二叉树展开为链表
LeetCode上114号问题"二叉树展开为链表"的Python实现,通过先序遍历二叉树并调整节点的左右指针,将二叉树转换为先序遍历顺序的单链表。
22 3
【Leetcode刷题Python】114. 二叉树展开为链表