力扣练习3.28

2024-03-29 13:52
文章标签 力扣 练习 3.28

本文主要是介绍力扣练习3.28,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

138. 随机链表的复制

浅拷贝和深拷贝:
前者新建一个数据结构,不创建元素副本;
后者不仅新建一个数据结构,而且新建一个数据副本。

深拷贝(Deep Copy)和浅拷贝(Shallow
Copy)是在复制数据结构时常见的两个概念,特别是在涉及复杂对象(如链表、树等)时。这两种拷贝方式的主要区别在于它们对原数据结构中对象的处理方式。

浅拷贝(Shallow Copy)

  • 浅拷贝创建一个新的数据结构(如新的链表或数组)但是不创建数据结构中的元素的副本
  • 在浅拷贝中,新数据结构中的元素仍然指向原有数据结构中的相同元素(即对象的引用被复制,而不是对象本身)。
  • 如果原数据结构中的对象被修改,这些修改也会反映在浅拷贝的数据结构中,因为它们共享相同的对象。

深拷贝(Deep Copy)

  • 深拷贝不仅创建一个新的数据结构,还为原数据结构中的每个元素创建副本
  • 在深拷贝中,新数据结构的元素是原元素的副本,这意味着它们是完全独立的。
  • 对原数据结构或深拷贝数据结构中的对象进行的修改不会影响另一个,因为它们不共享对象。

在链表的上下文中

假设有一个链表,其中每个节点都有一个random指针,可以指向链表中的任何节点或null

  • 深拷贝这个链表意味着创建一个新链表,其中包含原链表每个节点的副本,且每个副本节点的nextrandom指针都指向新链表中的对应节点,而不是原链表中的节点。
  • 浅拷贝这个链表则意味着创建一个新链表,但是不为原链表中的节点创建副本。在这种情况下,复制链表中的节点将直接指向原链表中的节点,这通常不是我们想要的。

深拷贝链表的方法

  1. 遍历原链表,为每个原节点创建一个新节点,这个新节点的值与原节点相同,但是nextrandom指针暂时留空。
  2. 建立一个映射关系,将原节点映射到对应的新节点,以便能够设置random指针。
  3. 再次遍历原链表,这次使用映射来设置每个新节点的nextrandom指针。

这种方法确保了每个新节点都与原链表中对应的节点分离,实现了深拷贝。

"""
# Definition for a Node.
class Node:def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):self.val = int(x)self.next = nextself.random = random
"""class Solution:def copyRandomList(self, head: 'Optional[Node]') -> 'Optional[Node]':if not head: return # 建立映射关系 {原节点:新节点}old_new = dict()cur = head # 当前节点while cur:old_new[cur] = Node(cur.val, None, None) # 指针部分留空,不然就指向原始链表了cur = cur.next # 往后遍历# 设置新节点的指针,也是从原始的头节点开始cur = headwhile cur:# 如果有后序节点,就将其从Null更新为原始链表中的后续节点if cur.next:old_new[cur].next = old_new[cur.next]if cur.random:old_new[cur].random = old_new[cur.random]cur = cur.nextreturn old_new[head]

297. 二叉树的序列化与反序列化

解题思路:
序列化是将二叉树编码成一个字符串
反序列化是将这个字符串解码成一个二叉树。
针对序列化:考虑使用层序遍历的方法,将二叉树的节点自上而下、从左往右地放在字符串里。不能忘了空节点,使用特殊符号占位,并分隔;
针对反序列化:针对字符串根据分隔符转换为list,初始化根节点,另其值等于list的首个元素。然后按照层序遍历的方式,将每层的节点指向列表的对应元素值,使用一个全局的索引变量解决。

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Codec:def serialize(self, root):"""Encodes a tree to a single string.:type root: TreeNode:rtype: str"""# 序列化# 层序遍历,将其结果都存储到一个字符串,用;分隔if not root: return '#;'res = ''queue = [root]while queue: # 因为最后只要一个字符串,所以就省略了node = queue.pop(0)# 如果节点存在,结果字符串加上节点的值if node: res += f'{node.val};'queue.append(node.left) # 加左子节点queue.append(node.right) # 右子节点else: # 如果是空,那就加上空值占位符res += '#;'return resdef deserialize(self, data):"""Decodes your encoded data to tree.:type data: str:rtype: TreeNode"""# 反序列化# 将字符串拆分为listif data == '#;': return Nonenodes = data.split(';')[:-1] # 因为这样分隔最后会出现空格,删除root = TreeNode(int(nodes[0])) # 根节点设置# 类似层序遍历queue = [root] # 层序遍历的起始index = 1 # 记录数组索引,0已经被定义了(根节点)while queue:node = queue.pop(0) # 第一次就是根节点# 如果当前节点不为空,也就是 不是#if nodes[index] != '#': node.left = TreeNode(int(nodes[index])) # 按照层序遍历,是从左到右的queue.append(node.left) # 队列结尾加上下一层的左节点 index += 1 # 左边的经过处理后就索引+1,不管是不是空值# 对右边执行相同操作if nodes[index] != '#':node.right = TreeNode(int(nodes[index]))queue.append(node.right)index += 1# 返回根节点return root# Your Codec object will be instantiated and called as such:
# ser = Codec()
# deser = Codec()
# ans = deser.deserialize(ser.serialize(root))

209. 长度最小的子数组

解题思路:双指针,滑动窗口。
从开始,逐步扩展窗口,检测是否满足求和条件;一旦满足,就缩减窗口,满足的时候也要比较最小的窗口长度。
可以使用for循环或者两层while。要注意的是for循环默认在执行完循环主体后进入下一个遍历。while循环需要手动在最后加,如果在前面加那么最小长度就不能+1,因为此时右指针正好跑过满足条件的窗口了。

class Solution:def minSubArrayLen(self, target: int, nums: List[int]) -> int:# 双指针,滑动窗口# 先不断扩展窗口,等满足条件就逐步缩小窗口# 左指针left = 0temp = 0 # 窗口内的和min_len = float('inf') # 最小长度# 循环for right in range(len(nums)):# 窗口内总和temp += nums[right]# 满足条件,开始缩减窗口while temp >= target:min_len = min(min_len, right-left+1)temp -= nums[left]left += 1# 检测最终是否有最短的存在if min_len != float('inf'):return min_lenelse:return 0

使用两层while循环

def minSubArrayLen(target, nums):n = len(nums)min_len = float('inf')  # 初始化为无穷大,用以比较找到最小长度sum = 0  # 窗口内元素的总和left, right = 0, 0  # 双指针,都初始化为0while right < n:# 扩大窗口sum += nums[right]right += 1# 当窗口内的总和大于等于target时,尝试缩小窗口以找到最小长度while sum >= target:min_len = min(min_len, right - left)sum -= nums[left]left += 1return min_len if min_len != float('inf') else 0

139. 单词拆分

这个问题可以通过动态规划来解决。动态规划是一种解决复杂问题的方法,它将问题分解成更小的子问题,通过解决子问题来解决整个问题。

动态规划思路

定义状态:定义一个布尔类型的动态规划数组dp,其中dp[i]表示字符串s的前i个字符(s[0..i-1])能否被字典wordDict中的一个或多个单词拼接得出。

状态转移:为了确定dp[i]的值,我们需要遍历[0, i)的所有可能的分割点j,检查两个条件:

  1. 字符串s[j..i-1](即从ji-1的子串)是否存在于字典wordDict中。
  2. dp[j]是否为true,表示s[0..j-1]可以被拼接得出。

如果上述两个条件中的任何一个为true,则dp[i]也为true

初始化dp[0] = true,表示空字符串总是可以被表示。

目标:检查dp[s.length()]的值,如果为true,表示整个字符串s可以用字典中的一个或多个单词拼接得出。

示例代码

def wordBreak(s, wordDict):word_set = set(wordDict)  # 将字典转换为集合,便于查找dp = [False] * (len(s) + 1)dp[0] = True  # 空字符串总是可以被表示for i in range(1, len(s) + 1):for j in range(i):if dp[j] and s[j:i] in word_set:dp[i] = Truebreak  # 一旦找到一个有效的分割点,就可以停止查找return dp[-1]

解释

  • 循环遍历字符串s的所有子串。
  • 对于每个子串s[j:i],如果dp[j]true且子串在wordDict中,说明找到了一个有效的分割点j,将dp[i]设置为true
  • 最终,dp[-1](或dp[len(s)])的值会告诉我们是否可以用字典中的单词拼接出整个字符串s

这种方法通过动态规划避免了重复计算和不必要的搜索,有效地解决了问题。

这篇关于力扣练习3.28的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/858770

相关文章

RabbitMQ练习(AMQP 0-9-1 Overview)

1、What is AMQP 0-9-1 AMQP 0-9-1(高级消息队列协议)是一种网络协议,它允许遵从该协议的客户端(Publisher或者Consumer)应用程序与遵从该协议的消息中间件代理(Broker,如RabbitMQ)进行通信。 AMQP 0-9-1模型的核心概念包括消息发布者(producers/publisher)、消息(messages)、交换机(exchanges)、

【Rust练习】12.枚举

练习题来自:https://practice-zh.course.rs/compound-types/enum.html 1 // 修复错误enum Number {Zero,One,Two,}enum Number1 {Zero = 0,One,Two,}// C语言风格的枚举定义enum Number2 {Zero = 0.0,One = 1.0,Two = 2.0,}fn m

MySql 事务练习

事务(transaction) -- 事务 transaction-- 事务是一组操作的集合,是一个不可分割的工作单位,事务会将所有的操作作为一个整体一起向系统提交或撤销请求-- 事务的操作要么同时成功,要么同时失败-- MySql的事务默认是自动提交的,当执行一个DML语句,MySql会立即自动隐式提交事务-- 常见案例:银行转账-- 逻辑:A给B转账1000:1.查询

html css jquery选项卡 代码练习小项目

在学习 html 和 css jquery 结合使用的时候 做好是能尝试做一些简单的小功能,来提高自己的 逻辑能力,熟悉代码的编写语法 下面分享一段代码 使用html css jquery选项卡 代码练习 <div class="box"><dl class="tab"><dd class="active">手机</dd><dd>家电</dd><dd>服装</dd><dd>数码</dd><dd

两数之和--力扣1

两数之和 题目思路C++代码 题目 思路 根据题目要求,元素不能重复且不需要排序,我们这里使用哈希表unordered_map。注意题目说了只对应一种答案。 所以我们在循环中,使用目标值减去当前循环的nums[i],得到差值,如果我们在map中能够找到这个差值,就说明存在两个整数的和为目标值。 如果没有找到,就将当前循环的nums[i]以及下标i放入map中,以便后续查

力扣第347题 前K个高频元素

前言 记录一下刷题历程 力扣第347题 前K个高频元素 前K个高频元素 原题目: 分析 我们首先使用哈希表来统计数字出现的频率,然后我们使用一个桶排序。我们首先定义一个长度为n+1的数组,对于下图这个示例就是长度为7的数组。为什么需要一个长度为n+1的数组呢?假如说总共有三个数字都为1,那么我们需要把这个1放在数组下标为3的位置,假如说数组长度为n,对于这个例子就是长度为3,那么它的

014.Python爬虫系列_解析练习

我 的 个 人 主 页:👉👉 失心疯的个人主页 👈👈 入 门 教 程 推 荐 :👉👉 Python零基础入门教程合集 👈👈 虚 拟 环 境 搭 建 :👉👉 Python项目虚拟环境(超详细讲解) 👈👈 PyQt5 系 列 教 程:👉👉 Python GUI(PyQt5)文章合集 👈👈 Oracle数据库教程:👉👉 Oracle数据库文章合集 👈👈 优

如何快速练习键盘盲打

盲打是指在不看键盘的情况下进行打字,这样可以显著提高打字速度和效率。以下是一些练习盲打的方法: 熟悉键盘布局:首先,你需要熟悉键盘上的字母和符号的位置。可以通过键盘图或者键盘贴纸来帮助记忆。 使用在线打字练习工具:有许多在线的打字练习网站,如Typing.com、10FastFingers等,它们提供了不同难度的练习和测试。 练习基本键位:先从学习手指放在键盘上的“家位”开始,通常是左手的

anaconda3下的python编程练习-csv翻译器

相关理解和命令 一、环境配置1、conda命令2、pip命令3、python命令 二、开发思路三、开发步骤 一、环境配置 1、conda命令 镜像源配置 conda config --show channels //查看镜像源conda config --remove-key channels //删除添加源,恢复默认源#添加镜像源conda config --ad

推荐练习键盘盲打的网站

对于初学者来说,以下是一些推荐的在线打字练习网站: 打字侠:这是一个专业的在线打字练习平台,提供科学合理的课程设置和个性化学习计划,适合各个水平的用户。它还提供实时反馈和数据分析,帮助你提升打字速度和准确度。 dazidazi.com:这个网站提供了基础的打字练习,适合初学者从零开始学习打字。 Type.fun打字星球:提供了丰富的盲打课程和科学的打字课程设计,还有诗词歌赋、经典名著等多样