【leetcode刷题之路】面试经典150题(4)——栈+链表

文章目录

      • 7 栈
        • 7.1 【哈希表】有效的括号
        • 7.2【栈】简化路径
        • 7.3 【栈】最小栈
        • 7.4 【栈】逆波兰表达式求值
        • 7.5 【栈】基本计算器
      • 8 链表
        • 8.1 【双指针】环形链表
        • 8.2 【双指针】两数相加
        • 8.3 【双指针】合并两个有序链表
        • 8.4 【哈希表】随机链表的复制
        • 8.5 【链表】反转链表 II
        • 8.6 【链表】K 个一组翻转链表
        • 8.7 【双指针】删除链表的倒数第 N 个结点
        • 8.8 【双指针】删除排序链表中的重复元素 II
        • 8.9 【双指针】旋转链表
        • 8.10 【双链表】分隔链表
        • 8.11 【双向链表】【哈希表】LRU 缓存

7 栈

7.1 【哈希表】有效的括号

题目地址:https://leetcode.cn/problems/valid-parentheses/description/?envType=study-plan-v2&envId=top-interview-150

  先构建一个括号的哈希表,引入 # \# #是防止只有右括号时无法与栈顶元素进行匹配。

class Solution:def isValid(self, s: str) -> bool:dict = {'(':')','{':'}','[':']','#':'#'}stack = ['#']for c in s:if c in dict:stack.append(c)else:if dict[stack.pop()] != c:return Falsereturn len(stack) == 1
7.2【栈】简化路径

题目地址:https://leetcode.cn/problems/simplify-path/description/?envType=study-plan-v2&envId=top-interview-150

  按照规则构建栈即可,注意遇到 . . .. ..时要把栈顶元素出栈。

class Solution:def simplifyPath(self, path: str) -> str:stack = []items = path.split("/")for item in items:if stack and item == "..":stack.pop()else:if item not in [".","..",""]:stack.append(item)return "/" + "/".join(stack)
7.3 【栈】最小栈

题目地址:https://leetcode.cn/problems/min-stack/description/?envType=study-plan-v2&envId=top-interview-150

  详见代码。

class MinStack:def __init__(self):self.num = []def push(self, val: int) -> None:self.num.append(val)def pop(self) -> None:self.num.pop()def top(self) -> int:return self.num[-1]def getMin(self) -> int:return min(self.num)# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(val)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.getMin()
7.4 【栈】逆波兰表达式求值

题目地址:https://leetcode.cn/problems/evaluate-reverse-polish-notation/description/?envType=study-plan-v2&envId=top-interview-150

  构建数字栈,遇到运算符将栈中最顶上的两个元素进行计算再压栈,最后输出栈顶元素。

class Solution:def evalRPN(self, tokens: List[str]) -> int:num = []for i in range(len(tokens)):if tokens[i] not in ["+","-","*","/"]:num.append(tokens[i])else:x2 = int(float(num.pop()))x1 = int(float(num.pop()))if tokens[i] == "+":x = x1 + x2num.append(str(x))elif tokens[i] == "-":x = x1 - x2num.append(str(x))elif tokens[i] == "*":x = x1 * x2num.append(str(x))elif tokens[i] == "/":x = x1 / x2num.append(str(x))return int(float(num.pop()))
7.5 【栈】基本计算器

题目地址:https://leetcode.cn/problems/basic-calculator/description/?envType=study-plan-v2&envId=top-interview-150

设置当前数字numnumnum和符号判断signsignsign(统一为加法):

  • 如果当前是数字,更新当前数字 n u m num num
  • 如果当前是操作符 + + +或者 − - ,更新当前计算结果 a n s ans ans,并把当前数字 n u m num num设为 0 0 0 s i g n sign sign根据相应的操作符设置为 1 1 1或者 − 1 −1 1,继续循环;
  • 如果当前是 ( ( (,那么说明遇到了左括号,而后面括号里的内容需要先计算,这时把 a n s , s i g n ans,sign ans,sign进栈,更新 a n s ans ans s i g n sign sign为新的循环开始;
  • 如果当前是 ) ) ),那么说明遇到了右括号,即当前括号里的内容已经计算完毕,所以要把之前的结果出栈,然后计算整个表达式的结果;
    最后,当字符串遍历结束的时候,需要把最后的一个 n u m num num也更新到 a n s ans ans中。
class Solution:def calculate(self, s: str) -> int:ans,num,sign = 0,0,1stack = []for c in s:if c >= "0" and c <= "9":num = num*10 + int(c)elif c == "+" or c == "-":ans += num*signnum = 0sign = 1 if c == "+" else -1elif c == "(":stack.append(ans)stack.append(sign)ans = 0sign = 1elif c == ")":ans += num*signnum = 0ans = ans * stack.pop()ans = ans + stack.pop()ans += num*signreturn ans        

8 链表

8.1 【双指针】环形链表

题目地址:https://leetcode.cn/problems/linked-list-cycle/description/?envType=study-plan-v2&envId=top-interview-150

  设置快慢指针,快指针一次走两步,慢指针一次走一步,如果快慢指针相遇,则说明遇到了环。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution:def hasCycle(self, head: Optional[ListNode]) -> bool:fp,sp = head,headwhile fp and fp.next:fp = fp.next.nextsp = sp.nextif sp == fp:return Truereturn False
8.2 【双指针】两数相加

题目地址:https://leetcode.cn/problems/add-two-numbers/description/?envType=study-plan-v2&envId=top-interview-150

  方法一:将两个链表的数字分别计算出来,相加,然后按照结果构造链表。

  方法二:直接计算两个链表各自位的和,设置进位标志,然后诸位构造链表。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next# 方法一
class Solution:def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:x1,x2 = 0,0l1p,l2p = l1,l2i,j = 1,1while l1p:x1 += i*l1p.vall1p = l1p.nexti *= 10while l2p:x2 += j*l2p.vall2p = l2p.nextj *= 10x = x1 + x2ans = l = ListNode()if x == 0:l.next = ListNode(0)else:while x:l.next = ListNode(x%10)x = x // 10l = l.nextreturn ans.next
# 方法二
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:ans = l = ListNode()sign = 0while l1 or l2:l1_num = l1.val if l1 else 0l2_num = l2.val if l2 else 0num = l1_num + l2_num + signl.next = ListNode(num%10)sign = num//10l = l.nextif l1:l1 = l1.nextif l2:l2 = l2.nextif sign:l.next = ListNode(sign)return ans.next
8.3 【双指针】合并两个有序链表

题目地址:https://leetcode.cn/problems/merge-two-sorted-lists/description/?envType=study-plan-v2&envId=top-interview-150

  详见代码。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:l1p,l2p = list1,list2ans = l = ListNode()while l1p and l2p:if l1p.val <= l2p.val:l.next = ListNode(l1p.val)l1p = l1p.nextl = l.nextelse:l.next = ListNode(l2p.val)l2p = l2p.nextl = l.nextwhile l1p:l.next = ListNode(l1p.val)l1p = l1p.nextl = l.nextwhile l2p:l.next = ListNode(l2p.val)l2p = l2p.nextl = l.nextreturn ans.next
8.4 【哈希表】随机链表的复制

题目地址:https://leetcode.cn/problems/copy-list-with-random-pointer/description/?envType=study-plan-v2&envId=top-interview-150

  利用哈希表,首先构建链表中的每个结点,再根据哈希表中的结点分别构造 n e x t next next r a n d o m random random引用,相当于对原始链表遍历两次。

"""
# 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]':dict = {}cur = headwhile cur:dict[cur] = Node(cur.val)cur = cur.nextcur = headwhile cur:dict[cur].next = dict.get(cur.next)dict[cur].random = dict.get(cur.random)cur = cur.nextif not head:return headelse:return dict[head]
8.5 【链表】反转链表 II

题目地址:https://leetcode.cn/problems/reverse-linked-list-ii/description/?envType=study-plan-v2&envId=top-interview-150

  超赞题解+配图:点击查看

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:ans = pre = ListNode()ans.next = headcnt = 1while pre.next and cnt < left:pre = pre.nextcnt += 1cur = pre.nexttail = curwhile cur and cnt <= right:nxt = cur.nextcur.next = pre.nextpre.next = curtail.next = nxtcur = nxtcnt += 1return ans.next
8.6 【链表】K 个一组翻转链表

题目地址:https://leetcode.cn/problems/reverse-nodes-in-k-group/description/?envType=study-plan-v2&envId=top-interview-150

  在上一题的基础上,先计算链表长度,然后按照 k k k进行分组,每一组进行翻转。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:# singly-linked lengthlength = 0tmp = headwhile tmp:length += 1tmp = tmp.next# reverseans = pre = ListNode()ans.next = headleft,right = 1,kwhile right <= length:pre = anscnt = 1while pre.next and cnt < left:pre = pre.nextcnt += 1cur = pre.nexttail = curwhile cur and cnt <= right:nxt = cur.nextcur.next = pre.nextpre.next = curtail.next = nxtcur = nxtcnt += 1left += kright += kreturn ans.next
8.7 【双指针】删除链表的倒数第 N 个结点

题目地址:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/description/?envType=study-plan-v2&envId=top-interview-150

  设置双指针,先让一个指针往前走 n n n步,再让两个指针一起走, r i g h t right right指针走到头就是要删除的结点。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:left = right = headcnt = 0while cnt < n:right = right.nextcnt += 1if not right:return head.nextwhile right.next:left = left.nextright = right.nextleft.next = left.next.nextreturn head
8.8 【双指针】删除排序链表中的重复元素 II

题目地址:https://leetcode.cn/problems/remove-duplicates-from-sorted-list-ii/description/?envType=study-plan-v2&envId=top-interview-150

  设置快慢指针,记录重复的数字,然后删除相应结点,但是要注意链表要多设置一个头结点,防止出现链表中元素都一样的情况。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = nextclass Solution:def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:ans = ListNode()ans.next = headslow,fast = ans,ans.nextwhile fast:while fast and fast.next and fast.val == fast.next.val:repute_num = fast.valwhile fast and fast.val == repute_num:fast = fast.nextslow.next = fastif fast:slow = fastfast = fast.nextreturn ans.next
8.9 【双指针】旋转链表

题目地址:https://leetcode.cn/problems/rotate-list/description/?envType=study-plan-v2&envId=top-interview-150

  先计算链表长度,找出右移的相对最小数,然后根据这个最小数设置双指针,找到倒数第 k k k个元素,将链表一分两半重新拼接。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:# lengthlength = 0tmp = headwhile tmp:length += 1tmp = tmp.nextif length != 0:k %= length# particular situationif not head or not head.next or k == 0:return head# rotate listslow,fast = head,headwhile k:fast = fast.nextk -= 1while fast.next:slow = slow.nextfast = fast.nextans = slow.nextslow.next = Nonefast.next = headreturn ans
8.10 【双链表】分隔链表

题目地址:https://leetcode.cn/problems/partition-list/description/?envType=study-plan-v2&envId=top-interview-150

  设置两个链表,一个链表存放比 x x x小的元素,另一个链表存放大于等于 x x x的元素,然后将两个链表合并即可,最后注意要让 b i g big big的下一个结点为空,否则容易成环。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:def partition(self, head: Optional[ListNode], x: int) -> Optional[ListNode]:if not head or not head.next:return headsml = sml_list = ListNode()big = big_list = ListNode()while head:if head.val < x:sml.next = headsml = sml.nextelse:big.next = headbig = big.nexthead = head.nextsml.next = big_list.nextbig.next = Nonereturn sml_list.next
8.11 【双向链表】【哈希表】LRU 缓存

题目地址:https://leetcode.cn/problems/lru-cache/description/?envType=study-plan-v2&envId=top-interview-150

  详见代码,通过构造双向链表和哈希表来模拟LRU缓存,要注意及时将最久未使用的结点移动到链表末尾,便于删除,这里采取的措施是定义一个函数,将链表中的某个结点移动到链表末尾,在 g e t get get p u t put put方法中都会遇到这种情况。

class ListNode:# 双向链表构建def __init__(self, key=None, value=None):self.key = keyself.value = valueself.prev = Noneself.next = Noneclass LRUCache:def __init__(self, capacity: int):self.capacity = capacityself.hashmap = {}# 头结点head和尾结点tailself.head = ListNode()self.tail = ListNode()# 初始化双向链表self.head.next = self.tailself.tail.prev = self.head# 将链表中的某个结点移到链表末尾taildef move_to_tail(self, key):node = self.hashmap[key]# 取出node结点node.next.prev = node.prevnode.prev.next = node.next# 移到末尾node.next = self.tailnode.prev = self.tail.prevself.tail.prev.next = nodeself.tail.prev = nodedef get(self, key: int) -> int:if key in self.hashmap:self.move_to_tail(key)res = self.hashmap.get(key)if res == None:return -1else:return res.valuedef put(self, key: int, value: int) -> None:if key in self.hashmap:self.hashmap[key].value = valueself.move_to_tail(key)else:if len(self.hashmap) == self.capacity:# 删除最久未访问结点self.hashmap.pop(self.head.next.key)self.head.next = self.head.next.nextself.head.next.prev = self.headnewNode = ListNode(key, value)self.hashmap[key] = newNodenewNode.prev = self.tail.prevnewNode.next = self.tailself.tail.prev.next = newNodeself.tail.prev = newNode# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)

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

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

相关文章

第二部分:准备工作

在开始AI视频生成项目之前&#xff0c;有两项关键的准备工作需要完成&#xff1a;数据收集与处理以及环境搭建与配置。这些步骤为成功运行和实施AI视频生成模型打下基础。 数据收集与处理 如何收集视频数据 AI模型的训练质量在很大程度上依赖于所用数据的质量和多样性。视频…

65-JQuery操作节点

1.JQuery创建节点$("标签") <script>//JQuery创建节点//$("标签")$("<p></p>");$("<p>这是p的内容</p>");</script> 2.父元素内部的末尾添加父.append(子元素),子.appendTo(父元素) <button…

LLM (Large language model)的指标参数

1. 背景介绍 我们训练大模型的时候&#xff0c;或者我们用RAG的时候&#xff0c;不知道我们的算法&#xff0c;或者我们的提示&#xff0c;或者我们的本地知识库是否已经整理得符合要求了。又或我们需要一个指标去评估我们目前的所有围绕大模型&#xff0c;向量数据库或外挂知…

git中将所有修改的文件上传到暂存区

案例&#xff1a; 我将本地的多个文件进行了修改&#xff0c;导致文件发生了变化。使用git status命令&#xff0c;查看文件的状态&#xff0c;发现有多个文件是modified&#xff0c;即被修改了。 本地文件发生了变化&#xff0c;需要将modified的文件添加到暂存区&#xff0c…

【计算机毕业设计】541鲜花商城系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

腾讯云宝塔Linux安装Mysql5.7

一、下载官方mysql包 wget http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm二、安装mysql包 rpm -ivh mysql-community-release-el7-5.noarch.rpm三、安装mysql yum install mysql-community-server -y四、启动数据库 systemctl start mysqld.service…

VUE为什么有的属性要加冒号

<el-menu-item :index "/item.menuClick" v-for"(item,i) in menu"><i class"item.menuIcon" ></i><span slot"title">{{item.menuName}}</span></el-menu-item>不加不行 加了好像是吧整体作为…

华清远见作业第四十一天——Qt(第三天)

思维导图&#xff1a; 编程 完善对话框&#xff0c;点击登录对话框&#xff0c;如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出提示”登录成功“&#xff0c;提供一个Ok按钮&#xff0c;用户点击Ok后&#xff0c;关闭登录界面&#xff0c;跳转到其他界面 如…

【Android 协程常见用法】

我们这里只讲解一下&#xff0c;协程在Android项目中常见用法&#xff0c;原理知识不在进行说明了。 依赖 lifecycleScope只能在Activity、Fragment中使用&#xff0c;会绑定Activity和Fragment的生命周期。依赖库&#xff1a; implementation androidx.lifecycle:lifecycle…

开源免费大模型框架自己训练可根据关键词提示绘图的软件

开源免费大模型框架自己训练可根据关键词提示绘图的软件!大家都知道&#xff0c;市面上那些可以支持这种业务的大模型都是收费的&#xff0c;如果你是一个资深的大模型爱好者&#xff0c;并且有自己的打算和预算&#xff0c;想自己训练一套属于自己的大模型软件来完成日常的绘图…

C语言——指针——第1篇——(第19篇)

坚持就是胜利 文章目录 1.指针是什么2.指针和指针类型&#xff08;1&#xff09;指针 - 整数&#xff08;2&#xff09;指针 的 解引用 3.野指针(1)野指针成因1.指针未初始化2.指针越界访问3.指针指向的空间释放 (2)如何规避野指针1.指针初始化2.小心指针越界3.指针指向的空间…

四川尚熠电子商务有限公司专注抖店开店服务

在数字化浪潮席卷全球的今天&#xff0c;电子商务成为了企业发展的重要引擎。四川尚熠电子商务有限公司凭借其专业的抖店开店服务&#xff0c;成为了众多商家进军电商市场的得力助手。本文将深入探讨四川尚熠电子商务有限公司抖店开店服务的优势与特点&#xff0c;为商家们提供…

全球游戏市场回暖,Flat Ads推动海外获客增长

摘要:热门游戏品类分析,解读新兴市场与赛道 近日,中国音数协游戏工委发布了《2023年中国游戏出海研究报告》,据报告数据显示,2023年,全球游戏市场规模11773.79亿元,同比增长6.00%,呈现增长回暖趋势。 图源:伽马数据 1.SLG和RPG游戏热度居高不下,休闲游戏增长势头强劲 目前,S…

第四十天| 343. 整数拆分、96.不同的二叉搜索树

Leetcode 343. 整数拆分 题目链接&#xff1a;343 整数拆分 题干&#xff1a;给定一个正整数 n &#xff0c;将其拆分为 k 个 正整数 的和&#xff08; k > 2 &#xff09;&#xff0c;并使这些整数的乘积最大化。返回 你可以获得的最大乘积 。 思考&#xff1a;动态规划。…

状态模式:灵活应对对象行为变化,实现状态驱动的智能设计

文章目录 **一、技术背景与应用场景****为何使用状态模式&#xff1f;****典型应用场景包括但不限于&#xff1a;** **二、状态模式定义与结构****三、使用步骤举例****四、优缺点分析****总结** 一、技术背景与应用场景 状态模式是一种行为设计模式&#xff0c;用于处理一个对…

loop_list单向循环列表

#include "loop_list.h" //创建单向循环链表 loop_p create_head() { loop_p L(loop_p)malloc(sizeof(loop_list)); if(LNULL) { printf("create fail\n"); return NULL; } L->len 0; L->nextL; retur…

mybatis 集成neo4j实现

文章目录 前言一、引入jar包依赖二、配置 application.properties三、Mybatis Neo4j分页插件四、Mybatis Neo4j自定义转换器handler五、MybatisNeo4j代码示例总结 前言 MyBatis是一个基于Java语言的持久层框架&#xff0c;它通过XML描述符或注解将对象与存储过程或SQL语句进行…

Qt+VTK鼠标拾取点生成拉伸闭合三维体

程序示例精选 QtVTK鼠标拾取点生成拉伸闭合三维体 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对《QtVTK鼠标拾取点生成拉伸闭合三维体》编写代码&#xff0c;代码整洁&#xff0c;规则&…

java——特殊文件日志技术

目录 特殊文件Properties文件XML文件XML文件有如下的特点XML的作用和应用场景解析XML文件 日志技术概述日志技术的体系结构Logback日志框架概述快速入门核心配置文件logback.xml日志级别项目中使用日志框架 特殊文件 Properties文件 后缀为.properties的文件&#xff0c;称之…

k8s(2)

目录 一.二进制部署k8s 常见的K8S安装部署方式&#xff1a; k8s部署 二进制与高可用的区别 二.部署k8s 初始化操作&#xff1a; 每台node安装docker&#xff1a; 在 master01 节点上操作; 准备cfssl证书生成工具:&#xff1a; 执行脚本文件&#xff1a; 拉入etcd压缩包…