Golang每日一练(leetDay0039) 二叉树专题(8)

news2025/1/18 10:00:34

目录

115. 不同的子序列 Distinct Subsequences 🌟🌟🌟

116. 填充每个节点的下一个右侧节点指针 Populating-next-right-pointers-in-each-node 🌟🌟

117. 填充每个节点的下一个右侧节点指针 II Populating-next-right-pointers-in-each-node-ii 🌟🌟

🌟 每日一练刷题专栏 🌟

Golang每日一练 专栏

Python每日一练 专栏

C/C++每日一练 专栏

Java每日一练 专栏


二叉树专题(8)第115题除外

115. 不同的子序列 Distinct Subsequences

给定一个字符串 s 和一个字符串 t ,计算在 s 的子序列中 t 出现的个数。

字符串的一个 子序列 是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串。(例如,"ACE" 是 "ABCDE" 的一个子序列,而 "AEC" 不是)

题目数据保证答案符合 32 位带符号整数范围。

示例 1:

输入:s = "rabbbit", t = "rabbit"
输出3
解释:如下图所示, 有 3 种可以从 s 中得到 "rabbit" 的方案。
rabbbit
rabbbit
rabbbit

示例 2:

输入:s = "babgbag", t = "bag"
输出5
解释:如下图所示, 有 5 种可以从 s 中得到 "bag" 的方案。 
babgbag
babgbag
babgbag
babgbag
babgbag

提示:

  • 0 <= s.length, t.length <= 1000
  • s 和 t 由英文字母组成

代码1: 暴力枚举

package main

import (
	"fmt"
)

func numDistinct(s string, t string) int {
	var ans int
	var dfs func(int, int)
	dfs = func(i, j int) {
		if j == len(t) {
			ans++
			return
		}
		if i == len(s) {
			return
		}
		if s[i] == t[j] {
			dfs(i+1, j+1) // 匹配
		}
		dfs(i+1, j) // 不匹配
	}
	dfs(0, 0)
	return ans
}

func main() {
	s := "rabbbit"
	t := "rabbit"
	fmt.Println(numDistinct(s, t))
	s = "babgbag"
	t = "bag"
	fmt.Println(numDistinct(s, t))
}

输出:

3
5

代码2: 记忆化搜索

package main

import (
	"fmt"
)

func numDistinct(s string, t string) int {
	memo := make([][]int, len(s))
	for i := range memo {
		memo[i] = make([]int, len(t))
		for j := range memo[i] {
			memo[i][j] = -1
		}
	}
	var dfs func(int, int) int
	dfs = func(i, j int) int {
		if j == len(t) {
			return 1
		}
		if i == len(s) {
			return 0
		}
		if memo[i][j] != -1 {
			return memo[i][j]
		}
		ans := dfs(i+1, j)
		if s[i] == t[j] {
			ans += dfs(i+1, j+1)
		}
		memo[i][j] = ans
		return ans
	}
	return dfs(0, 0)
}

func main() {
	s := "rabbbit"
	t := "rabbit"
	fmt.Println(numDistinct(s, t))
	s = "babgbag"
	t = "bag"
	fmt.Println(numDistinct(s, t))
}

代码3: 动态规则

package main

import (
	"fmt"
)

func numDistinct(s string, t string) int {
	m, n := len(s), len(t)
	dp := make([][]int, m+1)
	for i := range dp {
		dp[i] = make([]int, n+1)
	}
	for i := 0; i <= m; i++ {
		dp[i][0] = 1
	}
	for i := 1; i <= m; i++ {
		for j := 1; j <= n; j++ {
			dp[i][j] = dp[i-1][j]
			if s[i-1] == t[j-1] {
				dp[i][j] += dp[i-1][j-1]
			}
		}
	}
	return dp[m][n]
}

func main() {
	s := "rabbbit"
	t := "rabbit"
	fmt.Println(numDistinct(s, t))
	s = "babgbag"
	t = "bag"
	fmt.Println(numDistinct(s, t))
}

116. 填充每个节点的下一个右侧节点指针 Populating-next-right-pointers-in-each-node

给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。

二叉树定义如下:

struct Node {
  int val;
  Node *left;
  Node *right;
  Node *next;
}

填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL

初始状态下,所有 next 指针都被设置为 NULL

示例 1:

输入:root = [1,2,3,4,5,6,7]
输出:[1,#,2,3,#,4,5,6,7,#]
解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。序列化的输出按层序遍历排列,同一层节点由 next 指针连接,'#' 标志着每一层的结束。 

示例 2:

输入:root = []
输出:[]

提示:

  • 树中节点的数量在 [0, 2^12 - 1] 范围内
  • -1000 <= node.val <= 1000

进阶:

  • 你只能使用常量级额外空间。
  • 使用递归解题也符合要求,本题中递归程序占用的栈空间不算做额外的空间复杂度。

代码1: 递归

package main

import (
	"fmt"
	"strconv"
)

const null = -1 << 31

type Node struct {
	Val   int
	Left  *Node
	Right *Node
	Next  *Node
}

func connect(root *Node) *Node {
	if root == nil {
		return nil
	}
	if root.Left != nil {
		root.Left.Next = root.Right
	}
	if root.Right != nil {
		if root.Next != nil {
			root.Right.Next = root.Next.Left
		}
	}
	connect(root.Left)
	connect(root.Right)
	return root
}

func buildTree(nums []int) *Node {
	if len(nums) == 0 {
		return nil
	}
	root := &Node{Val: nums[0]}
	Queue := []*Node{root}
	idx := 1
	for idx < len(nums) {
		node := Queue[0]
		Queue = Queue[1:]
		if nums[idx] != null {
			node.Left = &Node{Val: nums[idx]}
			Queue = append(Queue, node.Left)
		}
		idx++
		if idx < len(nums) && nums[idx] != null {
			node.Right = &Node{Val: nums[idx]}
			Queue = append(Queue, node.Right)
		}
		idx++
	}
	return root
}

func (root *Node) LevelOrder() string {
	if root == nil {
		return "[]"
	}
	var arr []int
	Queue := []*Node{root}
	for len(Queue) > 0 {
		cur := Queue[0]
		Queue = Queue[1:]
		arr = append(arr, cur.Val)
		if cur.Left != nil {
			Queue = append(Queue, cur.Left)
		}
		if cur.Right != nil {
			Queue = append(Queue, cur.Right)
		}
		if cur.Next == nil {
			arr = append(arr, null)
		}
	}
	size := len(arr)
	for size > 0 && arr[size-1] == null {
		arr = arr[:size-1]
		size = len(arr)
	}
	result := "["
	for i, n := range arr {
		if n == null {
			result += "#"
		} else {
			result += strconv.FormatInt(int64(n), 10)
		}
		if i < size-1 {
			result += ","
		} else {
			result += ",#]"
		}
	}
	return result
}

func main() {
	nums := []int{1, 2, 3, 4, 5, 6, 7}
	root := buildTree(nums)
	fmt.Println(connect(root).LevelOrder())
}

输出:  

[1,#,2,3,#,4,5,6,7,#]

代码2: 迭代

package main

import (
	"fmt"
	"strconv"
)

const null = -1 << 31

type Node struct {
	Val   int
	Left  *Node
	Right *Node
	Next  *Node
}

func connect(root *Node) *Node {
	if root == nil {
		return nil
	}
	queue := []*Node{root}
	for len(queue) > 0 {
		n := len(queue)
		for i := 0; i < n; i++ {
			node := queue[0]
			queue = queue[1:]
			if i < n-1 {
				node.Next = queue[0]
			}
			if node.Left != nil {
				queue = append(queue, node.Left)
			}
			if node.Right != nil {
				queue = append(queue, node.Right)
			}
		}
	}
	return root
}

func buildTree(nums []int) *Node {
	if len(nums) == 0 {
		return nil
	}
	root := &Node{Val: nums[0]}
	Queue := []*Node{root}
	idx := 1
	for idx < len(nums) {
		node := Queue[0]
		Queue = Queue[1:]
		if nums[idx] != null {
			node.Left = &Node{Val: nums[idx]}
			Queue = append(Queue, node.Left)
		}
		idx++
		if idx < len(nums) && nums[idx] != null {
			node.Right = &Node{Val: nums[idx]}
			Queue = append(Queue, node.Right)
		}
		idx++
	}
	return root
}

func (root *Node) LevelOrder() string {
	if root == nil {
		return "[]"
	}
	var arr []int
	Queue := []*Node{root}
	for len(Queue) > 0 {
		cur := Queue[0]
		Queue = Queue[1:]
		arr = append(arr, cur.Val)
		if cur.Left != nil {
			Queue = append(Queue, cur.Left)
		}
		if cur.Right != nil {
			Queue = append(Queue, cur.Right)
		}
		if cur.Next == nil {
			arr = append(arr, null)
		}
	}
	size := len(arr)
	for size > 0 && arr[size-1] == null {
		arr = arr[:size-1]
		size = len(arr)
	}
	result := "["
	for i, n := range arr {
		if n == null {
			result += "#"
		} else {
			result += strconv.FormatInt(int64(n), 10)
		}
		if i < size-1 {
			result += ","
		} else {
			result += ",#]"
		}
	}
	return result
}

func main() {
	nums := []int{1, 2, 3, 4, 5, 6, 7}
	root := buildTree(nums)
	fmt.Println(connect(root).LevelOrder())
}

117. 填充每个节点的下一个右侧节点指针 II Populating-next-right-pointers-in-each-node-ii

给定一个二叉树

struct Node {
  int val;
  Node *left;
  Node *right;
  Node *next;
}

填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL

初始状态下,所有 next 指针都被设置为 NULL

进阶:

  • 你只能使用常量级额外空间。
  • 使用递归解题也符合要求,本题中递归程序占用的栈空间不算做额外的空间复杂度。

示例:

输入:root = [1,2,3,4,5,null,7]
输出:[1,#,2,3,#,4,5,7,#]
解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。序列化输出按层序遍历顺序(由 next 指针连接),'#' 表示每层的末尾。

提示:

  • 树中的节点数小于 6000
  • -100 <= node.val <= 100

代码1: 递归

package main

import (
	"fmt"
	"strconv"
)

const null = -1 << 31

type Node struct {
	Val   int
	Left  *Node
	Right *Node
	Next  *Node
}

func connect(root *Node) *Node {
	if root == nil {
		return nil
	}
	if root.Left != nil {
		if root.Right != nil {
			root.Left.Next = root.Right
		} else {
			root.Left.Next = getNext(root.Next)
		}
	}
	if root.Right != nil {
		root.Right.Next = getNext(root.Next)
	}
	connect(root.Right)
	connect(root.Left)
	return root
}

func getNext(root *Node) *Node {
	if root == nil {
		return nil
	}
	if root.Left != nil {
		return root.Left
	}
	if root.Right != nil {
		return root.Right
	}
	return getNext(root.Next)
}

func buildTree(nums []int) *Node {
	if len(nums) == 0 {
		return nil
	}
	root := &Node{Val: nums[0]}
	Queue := []*Node{root}
	idx := 1
	for idx < len(nums) {
		node := Queue[0]
		Queue = Queue[1:]
		if nums[idx] != null {
			node.Left = &Node{Val: nums[idx]}
			Queue = append(Queue, node.Left)
		}
		idx++
		if idx < len(nums) && nums[idx] != null {
			node.Right = &Node{Val: nums[idx]}
			Queue = append(Queue, node.Right)
		}
		idx++
	}
	return root
}

func (root *Node) LevelOrder() string {
	if root == nil {
		return "[]"
	}
	var arr []int
	Queue := []*Node{root}
	for len(Queue) > 0 {
		cur := Queue[0]
		Queue = Queue[1:]
		arr = append(arr, cur.Val)
		if cur.Left != nil {
			Queue = append(Queue, cur.Left)
		}
		if cur.Right != nil {
			Queue = append(Queue, cur.Right)
		}
		if cur.Next == nil {
			arr = append(arr, null)
		}
	}
	size := len(arr)
	for size > 0 && arr[size-1] == null {
		arr = arr[:size-1]
		size = len(arr)
	}
	result := "["
	for i, n := range arr {
		if n == null {
			result += "#"
		} else {
			result += strconv.FormatInt(int64(n), 10)
		}
		if i < size-1 {
			result += ","
		} else {
			result += ",#]"
		}
	}
	return result
}

func main() {
	nums := []int{1, 2, 3, 4, 5, 6, 7}
	root := buildTree(nums)
	fmt.Println(connect(root).LevelOrder())
}

输出:

[1,#,2,3,#,4,5,6,7,#]

代码2: 迭代

package main

import (
	"fmt"
	"strconv"
)

const null = -1 << 31

type Node struct {
	Val   int
	Left  *Node
	Right *Node
	Next  *Node
}

func connect(root *Node) *Node {
	if root == nil {
		return nil
	}
	queue := []*Node{root}
	for len(queue) > 0 {
		n := len(queue)
		for i := 0; i < n; i++ {
			node := queue[0]
			queue = queue[1:]
			if i < n-1 {
				node.Next = queue[0]
			}
			if node.Left != nil {
				queue = append(queue, node.Left)
			}
			if node.Right != nil {
				queue = append(queue, node.Right)
			}
		}
	}
	return root
}

func buildTree(nums []int) *Node {
	if len(nums) == 0 {
		return nil
	}
	root := &Node{Val: nums[0]}
	Queue := []*Node{root}
	idx := 1
	for idx < len(nums) {
		node := Queue[0]
		Queue = Queue[1:]
		if nums[idx] != null {
			node.Left = &Node{Val: nums[idx]}
			Queue = append(Queue, node.Left)
		}
		idx++
		if idx < len(nums) && nums[idx] != null {
			node.Right = &Node{Val: nums[idx]}
			Queue = append(Queue, node.Right)
		}
		idx++
	}
	return root
}

func (root *Node) LevelOrder() string {
	if root == nil {
		return "[]"
	}
	var arr []int
	Queue := []*Node{root}
	for len(Queue) > 0 {
		cur := Queue[0]
		Queue = Queue[1:]
		arr = append(arr, cur.Val)
		if cur.Left != nil {
			Queue = append(Queue, cur.Left)
		}
		if cur.Right != nil {
			Queue = append(Queue, cur.Right)
		}
		if cur.Next == nil {
			arr = append(arr, null)
		}
	}
	size := len(arr)
	for size > 0 && arr[size-1] == null {
		arr = arr[:size-1]
		size = len(arr)
	}
	result := "["
	for i, n := range arr {
		if n == null {
			result += "#"
		} else {
			result += strconv.FormatInt(int64(n), 10)
		}
		if i < size-1 {
			result += ","
		} else {
			result += ",#]"
		}
	}
	return result
}

func main() {
	nums := []int{1, 2, 3, 4, 5, 6, 7}
	root := buildTree(nums)
	fmt.Println(connect(root).LevelOrder())
}

🌟 每日一练刷题专栏 🌟

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

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

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

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

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

Golang每日一练 专栏

Python每日一练 专栏

C/C++每日一练 专栏

Java每日一练 专栏

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/428112.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

模拟信号放大转换器 非隔离 线性对应输入输出 大功率负载

概述&#xff1a; 导轨安装DIN11 NIPO 系列模拟信号放大器是一种将输入信号放大、转换成按比例输出的直流信号放大器。产品广泛应用在电力、远程监控、仪器仪表、医疗设备、工业自控等需要直流信号测控的行业。此系列产品内部采用稳压电路&#xff0c;通过等比例控制线性放大输…

Threshold ECDSA——web3.0开发中的门限签名

多重签名 1.联名账户&#xff0c;任何一个密钥都能打开账户。 2.储蓄账户&#xff0c;需要所有密钥才能打开账户。 3.级联账户&#xff0c;可以使用部分密钥做部分功能&#xff0c;需要所有密钥才能执行全部功能。 4.在加密货币中&#xff0c;多重签名通过创建一个多重签名…

超详细从入门到精通,pytest自动化测试框架实战-fixture多样玩法(九)

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 在编写测试用例&…

uniapp开发小程序:使用webview 跳转外部链接

一、使用uniapp开发小程序时&#xff0c;要跳转外部链接&#xff0c;实现的效果如下&#xff1a; 二、实现的步骤&#xff1a; ①先在自己uniapp项目pages.json中建一个页面webview.vue {"path" : "pages/webview/webview","style" : …

(详细)带你运行ShanghaiTech数据集预训练模型——人群计数算法

写在前面 ShanghaiTech数据集是现有的人群计数领域比较常用的训练测试数据集&#xff0c;该博客将详细讲述如何跑通ShanghaiTech官方提供的预训练版本。 由于全部跑完ShanghaiTech数据集需要一定的时间&#xff0c;今天只以其中的ped2数据集&#xff08;体量最小&#xff09;…

linux_回收子进程(何为孤儿进程、僵尸进程、wait函数、waitpid函数)

接上一篇&#xff1a;linux_exec函数族-execl函数-execlp函数-execle函数-execv函数-execvp函数-execve函数 今天来向大家分享几个有趣的知识点&#xff0c;一个是孤儿进程&#xff0c;一个是僵尸进程&#xff0c;hhh&#xff0c;是不是很有趣&#xff0c;另外再来看看怎么去回…

Kubernetes集群调度增强之超容量扩容

作者&#xff1a;京东科技 徐宪章 1 什么是超容量扩容 超容量扩容功能&#xff0c;是指预先调度一定数量的工作节点&#xff0c;当业务高峰期或者集群整体负载较高时&#xff0c;可以使应用不必等待集群工作节点扩容&#xff0c;从而迅速完成应用横向扩容。通常情况下HPA、Cl…

链表与邻接表|栈与队列|kmp

目录 单链表&#xff08;邻接表&#xff09; 双链表 数组模拟栈、队列 单调栈 单调队列&#xff08;滑动窗口&#xff09; KMP 一、KMP算法基本概念与核心思想 二、next数组的含义 三、匹配的思路 四、求next数组 单链表&#xff08;邻接表&#xff09; #include &…

Linux操作基础(系统安全及应用)

文章目录一 、账号安全基本措施1.1 系统账号清理1.2 密码安全控制1.21 设置密码有效期1.3 命令历史限制1.31 修改history命令条数1.32 清空history的方式1.33 设置终端自动注销二 、使用su命令切换用户2.1 限制使用su命令切换用户2.2 sudo命令—提升执行权限三 、系统引导和登录…

OpenCV:介绍 SURF(加速稳健特征)以及其使用

我们将了解 SURF 的基础知识 我们将了解 OpenCV 中的 SURF 功能 理论 在上一章中,我们学习了 SIFT 用于关键点检测和描述的方法。但它相对较慢,人们需要更快速的版本。2006年,Bay, H., Tuytelaars, T. 和 Van Gool, L 发表了另一篇论文 "SURF: 加速稳健特征",介…

机器学习:多项式拟合分析中国温度变化与温室气体排放量的时序数据

文章目录1、前言2、定义及公式3、案例代码1、数据解析2、绘制散点图3、多项式回归、拟合4、注意事项1、前言 ​ 当分析数据时&#xff0c;如果我们找的不是直线或者超平面&#xff0c;而是一条曲线&#xff0c;那么就可以用多项式回归来分析和预测。 2、定义及公式 ​ 多项式…

《花雕学AI》哪种技能5年10年后还会被市场需要? 该如何提高这些能力?

随着AI人工智能、ChatGPT等新的技术革新的发展&#xff0c;未来职业场景确实会发生变化&#xff0c;一些传统的职业可能会被取代&#xff0c;而一些新的职业可能会出现。根据世界经济论坛所发布的《未来就业报告》&#xff0c;一半的劳动力需要在2025年之前完成技能重塑。那么&…

Harmony OS 开发指南——DevEco Device Tool 安装配置

本文介绍如何在Windows主机上安装DevEco Device Tool工具。 坑点总结&#xff1a; 国内部分网络环境下&#xff0c;安装npm包可能会很慢或者超时&#xff0c;推荐使用国内npm源&#xff08;如淘宝源、华为源等&#xff09;&#xff1b;serialport这个npm包安装的过程中需要编…

C/C++笔记-记录一次对qmake生成的Makefile的分析(2023-02-07)

如下Qt代码&#xff1a; ConsoleDemo.pro QT core QT - guiTARGET ConsoleDemo CONFIG console CONFIG - app_bundleTEMPLATE appSOURCES main.cpp main.cpp #include <QCoreApplication> #include <QDebug>int main(int argc, char *argv[]) {QCoreApplic…

安装Kafka 基础命令

目录 解压 改名 修改配置文件 创建目录用于存放日志 创建修改myid 添加环境变量 刷新环境变量 测试 启动zookeeper 启动kafka 关闭kafka kafka基础命令 查看消息队列 创建消息队列 查看队列详情 查询指定队列消息数量 生产者消费者 生产消息 消费消息 解压 …

简单分享婚庆小程序开发怎么做

婚庆行业的服务范围不再仅限于婚纱照、婚礼主持等服务&#xff0c;消费者希望在婚庆服务商获得更多的服务&#xff0c;导致行业服务范围不断扩大、服务类目越发丰富&#xff0c;而商家在此基础上&#xff0c;更需要考虑提高服务质量与效率&#xff0c;合理利用资源提供服务。小…

Jmeter5.1的安装

1.由于&#xff0c;jmeter 是用纯java开发的一个可跨平台的绿色软件&#xff0c;所以&#xff0c;我们在使用jmeter之前&#xff0c;必须要安装基于Windows下的jdk环境。下面安装jdk,检查是否安装jdk方法&#xff08;cmd运行输入java -version&#xff09;&#xff0c;如下图显…

81.qt qml-Canvas深入学习之好看的水纹波自定义控件V2

界面如下所示(外观参考ECharts 源码通过QML控件实现): 效果如下所示: 支持自定义颜色、自定义波峰数量、增幅、速度、水平偏移等 1.介绍 在我们之前38章38.qt quick-QML水纹波进度条_诺谦的博客-CSDN博客 写过一个简单的水纹波: 所以本质差不多. 2.QianRippleChartPage代码 该…

webgl-矩阵、旋转、平移、缩放

关键代码 旋转 /* * [ * cosB, -sinB, 0, 0, * sinB, cosB, 0, 0, * 0, 0, 1, 0, * 0, 0, 0, 1 * ] * * 矩阵本该是这个但是由于webgl的矩阵行和列是颠倒的所以我们传入的矩阵也需要倒置 */ rotationMatrix [ cosB, sinB, 0, 0, -sinB, cos…

[Python工匠]输出③容器类型

在Python中&#xff0c;最常见的内置容器类型有四种&#xff1a;列表、元组、字典、集合。 列表&#xff08;list&#xff09;是一种非常经典的容器类型&#xff0c;通常用来存放多个同类对象&#xff0c;比如从1到10的所有整数&#xff1a; 元组&#xff08;tuple&#xff09;…