代码随想录算法训练营第二十七天 | 双指针法-栈与队列,两个章节的复习总结

双指针法-栈与队列

  • 双指针法章节
    • 移除元素
    • 删除有序数组中的重复项
    • 移动零
    • 比较含退格的字符串
    • 有序数组的平方
    • 反转字符串
    • 反转字符串II
    • 替换空格
    • 反转字符串中的单词
    • 纯手撕版,需要注意的地方还蛮多的
    • 反转链表
    • 删除链表的倒数第 N 个结点
      • 这道题之前做的时候没有注意,边界处理是需要着重考虑的,就是删除节点是链表尾结点的情况。
      • 为什么会有上述问题?要从本质上去分析!我们要删除倒数第N个节点,那么slow指针最后就应该停在倒数第N+1个节点,假设我们最后fast指针指向None(这个可由while循环的判断条件来控制),那么在结果处,fast和slow指针之间,相隔N个节点,注意是“相隔”,所以在一开始移动时,要让fast移动N+1步,才能达到目标。而移动N+1步可能造成链表越界,所以要加入虚拟头。
      • 不加入虚拟头,会面临:当N等于链表长度时,按照我的错误做法,fast会走到尾结点后的None,那么fast.next就会报错,目前我没想到好的解决方案,同样,当链表只有一个节点时,不加入虚拟头,slow.next=slow.next.next也会报错。
      • 本题告诉我,虚拟头节点多么重要,但是我还没有理解到:必须加入虚拟头的原因,不加的话,有很多边界情况难以处理,但这似乎不是必须加入的理由?
      • 单独处理边界情况:N等于链表长度(换句话说就是:删除头结点)
    • 链表相交
    • 环形链表 II
      • 我上一次写这道题的代码
      • 这一次学习了卡哥的写法后的代码
      • 可以看出,选择 while 循环的判断条件也非常有讲究
    • 三数之和
    • 四数之和
    • 用栈实现队列
    • 用队列实现栈
    • 有效的括号
    • 删除字符串中的所有相邻重复项
    • 滑动窗口最大值
      • 自己写的代码,直接就AC了,证明单调队列这里,我还是有点印象的。
      • 卡哥的代码,可以做对比
      • 我觉得最主要的区别就在于:一些极端错误情况的处理上,在实际工程中可能出现类似问题,但是在力扣的示例中,肯定不会有这种情况的。
    • 前K个高频元素
      • 不会,是涉及大顶堆,小顶堆的内容。

双指针法章节

移除元素

class Solution:def removeElement(self, nums: List[int], val: int) -> int:n = len(nums)slow = 0fast = 0while fast < n :if nums[fast]!=val :nums[slow] = nums[fast]slow += 1fast += 1else :fast += 1return slow

删除有序数组中的重复项

注意本题的判断条件,是 slow-1 , 所以需要先判定 slow > 0

class Solution:def removeDuplicates(self, nums: List[int]) -> int:n = len(nums)slow = 0fast = 0while fast < n :# 注意这个判断条件,是 slow-1 , 所以需要先判定 slow > 0if slow > 0 and nums[fast] == nums[slow-1] :fast += 1else :nums[slow] = nums[fast]fast += 1slow += 1return slow

移动零

注意本题,要最后进行一步赋值0的操作

class Solution:def moveZeroes(self, nums: List[int]) -> None:"""Do not return anything, modify nums in-place instead."""n = len(nums)slow = 0fast = 0while fast < n :if nums[fast] != 0 :nums[slow] = nums[fast]slow += 1fast += 1else :fast += 1while slow < n :nums[slow] = 0slow += 1

比较含退格的字符串

class Solution:def backspaceCompare(self, s: str, t: str) -> bool:slow = 0fast = 0s = list(s)t = list(t)ns = len(s)nt = len(t)# 先做swhile fast < ns :if s[fast] != '#':s[slow] = s[fast]slow += 1fast += 1else :if slow > 0 :slow -= 1fast += 1slen = slowslow = 0fast = 0# 再做twhile fast < nt :if t[fast] != '#':t[slow] = t[fast]slow += 1fast += 1else :if slow > 0 :slow -= 1fast += 1tlen = slowif slen != tlen :return Falseelse :for i in range(slen):if s[i]!=t[i]:return Falsereturn True

有序数组的平方

class Solution:def sortedSquares(self, nums: List[int]) -> List[int]:n = len(nums)res = [0]*nstart = 0end = n-1# 倒序给结果数组赋值,这样才能保证是非递减顺序index = n-1while start <= end :if nums[start]+nums[end] > 0 :res[index] = nums[end]**2end -= 1index -= 1elif nums[start]+nums[end] < 0 :res[index] = nums[start]**2index -= 1start += 1else :res[index] = nums[start]**2index -= 1start += 1return res

反转字符串

class Solution:def reverseString(self, s: List[str]) -> None:"""Do not return anything, modify s in-place instead."""n = len(s)slow = 0fast = n-1while slow < fast :s[slow],s[fast] = s[fast],s[slow]slow += 1fast -= 1

反转字符串II

class Solution:def reverseStr(self, s: str, k: int) -> str:n = len(s)for i in range(0,n,2*k):temp = s[i:i+k]s = s[:i] + temp[::-1] + s[i+k:]return s

替换空格

class Solution:def replaceSpace(self, s: str) -> str:s = list(s)n = len(s)count = 0for i in s :if i == ' ':count += 1extend = [0]*count*2s = s + extendnewn = n + count*2slow = n-1fast = newn-1while slow > -1 :if s[slow]!=' ' :s[fast] = s[slow]slow -= 1fast -= 1else :s[fast-2:fast+1] = '%20'fast -= 3slow -= 1return ''.join(s)

反转字符串中的单词

使用 split() 函数版

class Solution:def reverseWords(self, s: str) -> str:# 甚至可以不用这个strip# 直接split也会把首尾的空格去掉s = s.strip()s = s[::-1]s = s.split()n = len(s)for i in range(n) :temp = s[i]s[i] = temp[::-1]return ' '.join(s)

纯手撕版,需要注意的地方还蛮多的

class Solution:def reverseWords(self, s: str) -> str:s = list(s)n = len(s)slow = 0fast = 0while fast < n :if slow == 0 and s[fast]==' ':fast += 1elif slow > 0 and s[fast]==' ' and s[slow-1] != ' ':s[slow] = s[fast]slow += 1fast += 1elif slow > 0 and s[fast]==' ' and s[slow-1] == ' ':fast += 1# 上面对 fast 做了加一操作,下面这里的 if 是和上面独立的# 所以在进行一切操作之前,一定要加上最外层while循环的判断条件 fast < nif fast < n and s[fast] != ' ':s[slow] = s[fast]slow += 1fast += 1# 最后一个字符是否是空格,是的话,就去掉# 我上面的逻辑就会导致,最后一位可能是空格if s[slow-1] == ' ':s = s[:slow-1]length = slow-1else :s = s[:slow]lenght = slows = s[::-1]  left = 0right = 0while right < slow :if s[right] != ' ':right += 1else :temp = s[left:right]s[left:right] = temp[::-1]right += 1left = right# 这里也要注意,要单独处理 right 走到最后一个位置的情况,由于前面已经去掉了空格# 所以要单独处理if right == slow-1 :temp = s[left:]s[left:] = temp[::-1]right += 1left = rightreturn ''.join(s)

反转链表

class Solution:def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:pre = Nonecur = headwhile cur :temp = cur.nextcur.next = prepre = curcur = tempreturn pre

删除链表的倒数第 N 个结点

这道题之前做的时候没有注意,边界处理是需要着重考虑的,就是删除节点是链表尾结点的情况。

边界错误情况:

class Solution:def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:slow = headfast = head       while n > 0:fast = fast.nextn -= 1while fast and fast.next :fast = fast.nextslow = slow.nextslow.next = slow.next.nextreturn head

歪打正着+虚拟头节点:

class Solution:def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:virtual = ListNode(0,head)slow = virtualfast = virtualwhile n > 0 :fast = fast.nextn -= 1while fast.next :fast = fast.nextslow = slow.nextslow.next = slow.next.nextreturn virtual.next

卡哥的代码

class Solution:def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:# 创建一个虚拟节点,并将其下一个指针设置为链表的头部dummy_head = ListNode(0, head)# 创建两个指针,慢指针和快指针,并将它们初始化为虚拟节点slow = fast = dummy_head# 快指针比慢指针快 n+1 步for i in range(n+1):fast = fast.next# 移动两个指针,直到快速指针到达链表的末尾while fast:slow = slow.nextfast = fast.next# 通过更新第 (n-1) 个节点的 next 指针删除第 n 个节点slow.next = slow.next.nextreturn dummy_head.next

为什么会有上述问题?要从本质上去分析!我们要删除倒数第N个节点,那么slow指针最后就应该停在倒数第N+1个节点,假设我们最后fast指针指向None(这个可由while循环的判断条件来控制),那么在结果处,fast和slow指针之间,相隔N个节点,注意是“相隔”,所以在一开始移动时,要让fast移动N+1步,才能达到目标。而移动N+1步可能造成链表越界,所以要加入虚拟头。

不加入虚拟头,会面临:当N等于链表长度时,按照我的错误做法,fast会走到尾结点后的None,那么fast.next就会报错,目前我没想到好的解决方案,同样,当链表只有一个节点时,不加入虚拟头,slow.next=slow.next.next也会报错。

本题告诉我,虚拟头节点多么重要,但是我还没有理解到:必须加入虚拟头的原因,不加的话,有很多边界情况难以处理,但这似乎不是必须加入的理由?

单独处理边界情况:N等于链表长度(换句话说就是:删除头结点)

class Solution:def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:slow = headfast = head       while n > 0 :fast = fast.nextn -= 1# 单独处理,当链表长度等于N的情况,即:删除头结点if fast == None :head = head.nextelse :while fast.next :fast = fast.nextslow = slow.nextslow.next = slow.next.nextreturn head

链表相交

class Solution:def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:curA = headAcurB = headBcountA = 0countB = 0while curA :curA = curA.nextcountA += 1while curB :curB = curB.nextcountB += 1# 在下面这个判断之后,只需要考虑 countA >= countB 的情况了if countA < countB :headA,headB = headB,headAcountA,countB = countB,countAdiff = countA - countBwhile diff > 0 :headA = headA.nextdiff -= 1while headA :if headA == headB :return headAheadA = headA.nextheadB = headB.nextreturn None

环形链表 II

这里列出一个代码对比:

我上一次写这道题的代码

class Solution:def detectCycle(self, head: ListNode) -> ListNode:slow = headfast = headwhile fast and fast.next:slow = slow.nextfast = fast.next.next# If there is a cycle, the slow and fast pointers will eventually meetif slow == fast:# Move one of the pointers back to the start of the listslow = headwhile slow != fast:slow = slow.nextfast = fast.nextreturn slow# If there is no cycle, return Nonereturn None

这一次学习了卡哥的写法后的代码

class Solution:def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:slow = headfast = headwhile fast and fast.next :slow = slow.nextfast = fast.next.nextif slow == fast :fast = headwhile fast != slow :slow = slow.nextfast = fast.nextreturn slowreturn None

可以看出,选择 while 循环的判断条件也非常有讲究

三数之和

class Solution:def threeSum(self, nums: List[int]) -> List[List[int]]:nums.sort()n = len(nums)res = []for i in range(0,n-2):if nums[i] > 0 :breakif i > 0 and nums[i] == nums[i-1] :continueleft = i+1right = n-1while left < right :if nums[i] + nums[left] + nums[right] > 0 :right -= 1elif nums[i] + nums[left] + nums[right] < 0 :left += 1else :path = [nums[i] , nums[left] , nums[right]]   res.append(path)while left < right and nums[right] == nums[right-1]:right -= 1while left < right and nums[left] == nums[left+1]:left += 1left += 1right -= 1return res

四数之和

class Solution:def fourSum(self, nums: List[int], target: int) -> List[List[int]]:nums = sorted(nums)n = len(nums)res = []for i in range(0,n-3):if i > 0 and nums[i]==nums[i-1]:continue# 剪枝细节,一定注意,要考虑target是负数的情况if nums[i] > 0 and nums[i] > target:# 这里因为是最外层循环,所以break还是return 无所谓breakfor j in range(i+1,n-2):if j > i+1 and nums[j]==nums[j-1]:continue# 剪枝细节,一定注意,要考虑target是负数的情况,同时要留意到:# 多个负数相加是更小的负数,所以(nums[i]+nums[j]) > 0是必须的# 比如 target=-8,解是[-1,-2,-2,-3],前两个的加和是大于target的!if (nums[i]+nums[j]) > 0 and (nums[i]+nums[j]) > target:# 注意这里,不能是return ,而是breakbreakleft = j+1right = n-1temp = target - (nums[i]+nums[j])while left < right :if nums[left]+nums[right] > temp :right -= 1elif nums[left]+nums[right] < temp :left += 1else :path = [nums[i],nums[j],nums[left],nums[right]]res.append(path)while left < right and nums[left]==nums[left+1]:left += 1while left < right and nums[right]==nums[right-1]:right -= 1left += 1right -= 1return res

用栈实现队列

class MyQueue:def __init__(self):self.pushin = []self.pushout = []def push(self, x: int) -> None:self.pushin.append(x)def pop(self) -> int:if self.pushout != [] :return self.pushout.pop()else :self.pushout = self.pushin[::-1]self.pushin = []return self.pushout.pop()def peek(self) -> int:# 我觉得这里是唯一的难点,搞清楚代码复用的逻辑# pop出来后,在对pushout,append进去就好了# 这样下次再pop,还是这个值,是正确的!# 因为pushout已经可以看做是一个队列了num = self.pop()self.pushout.append(num)return numdef empty(self) -> bool:if self.pushin == [] and self.pushout == []:return Trueelse :return False

用队列实现栈

两个队列实现:

from collections import deque
class MyStack:def __init__(self):self.dq1 = deque()self.dq2 = deque()self.number = 0def push(self, x: int) -> None:self.dq1.append(x)self.number += 1def pop(self) -> int:if self.empty():return Nonefor i in range(0,self.number-1):self.dq2.append(self.dq1.popleft())num = self.dq1.popleft()self.dq1 , self.dq2 = self.dq2 , self.dq1self.number -= 1return numdef top(self) -> int:return self.dq1[-1]def empty(self) -> bool:if len(self.dq1) == 0:return Trueelse :return False

一个队列实现:

from collections import deque
class MyStack:def __init__(self):self.dq1 = deque()self.number = 0def push(self, x: int) -> None:self.dq1.append(x)self.number += 1def pop(self) -> int:if self.empty():return Nonefor i in range(0,self.number-1):self.dq1.append(self.dq1.popleft())num = self.dq1.popleft()  self.number -= 1return numdef top(self) -> int:return self.dq1[-1]def empty(self) -> bool:if len(self.dq1) == 0:return Trueelse :return False

有效的括号

class Solution:def isValid(self, s: str) -> bool:stack = []n = len(s)i = 0while i < n :if s[i]=='(' :stack.append(')')elif s[i]=='[' :stack.append(']')elif s[i]=='{' :stack.append('}')else :if stack == [] or stack.pop() != s[i]:return Falsei += 1if len(stack)!=0 :return Falseelse :return True

删除字符串中的所有相邻重复项

class Solution:def removeDuplicates(self, s: str) -> str:stack = []n = len(s)i = 0while i < n :if stack == [] :stack.append(s[i])else :if s[i] == stack[-1]:stack.pop()else :stack.append(s[i])i += 1return ''.join(stack)

滑动窗口最大值

自己写的代码,直接就AC了,证明单调队列这里,我还是有点印象的。

from collections import deque
class DQ:def __init__(self):self.dq = deque()def push(self,val):if len(self.dq) == 0 :self.dq.append(val)else :while len(self.dq) != 0 and val > self.dq[-1] :self.dq.pop()self.dq.append(val)def top(self):return self.dq[0]def popleft(self):self.dq.popleft()class Solution:def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:res = []dq = DQ()n = len(nums)for i in range(k):dq.push(nums[i])res.append(dq.top())for i in range(k,n):if nums[i-k] == dq.top() :dq.popleft()dq.push(nums[i])res.append(dq.top())return res

卡哥的代码,可以做对比

from collections import dequeclass MyQueue: #单调队列(从大到小def __init__(self):self.queue = deque() #这里需要使用deque实现单调队列,直接使用list会超时#每次弹出的时候,比较当前要弹出的数值是否等于队列出口元素的数值,如果相等则弹出。#同时pop之前判断队列当前是否为空。def pop(self, value):if self.queue and value == self.queue[0]:self.queue.popleft()#list.pop()时间复杂度为O(n),这里需要使用collections.deque()#如果push的数值大于入口元素的数值,那么就将队列后端的数值弹出,直到push的数值小于等于队列入口元素的数值为止。#这样就保持了队列里的数值是单调从大到小的了。def push(self, value):while self.queue and value > self.queue[-1]:self.queue.pop()self.queue.append(value)#查询当前队列里的最大值 直接返回队列前端也就是front就可以了。def front(self):return self.queue[0]class Solution:def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:que = MyQueue()result = []for i in range(k): #先将前k的元素放进队列que.push(nums[i])result.append(que.front()) #result 记录前k的元素的最大值for i in range(k, len(nums)):que.pop(nums[i - k]) #滑动窗口移除最前面元素que.push(nums[i]) #滑动窗口前加入最后面的元素result.append(que.front()) #记录对应的最大值return result

我觉得最主要的区别就在于:一些极端错误情况的处理上,在实际工程中可能出现类似问题,但是在力扣的示例中,肯定不会有这种情况的。

前K个高频元素

不会,是涉及大顶堆,小顶堆的内容。

卡哥的代码:

#时间复杂度:O(nlogk)
#空间复杂度:O(n)
import heapq
class Solution:def topKFrequent(self, nums: List[int], k: int) -> List[int]:#要统计元素出现频率map_ = {} #nums[i]:对应出现的次数for i in range(len(nums)):map_[nums[i]] = map_.get(nums[i], 0) + 1#对频率排序#定义一个小顶堆,大小为kpri_que = [] #小顶堆#用固定大小为k的小顶堆,扫描所有频率的数值for key, freq in map_.items():heapq.heappush(pri_que, (freq, key))if len(pri_que) > k: #如果堆的大小大于了K,则队列弹出,保证堆的大小一直为kheapq.heappop(pri_que)#找出前K个高频元素,因为小顶堆先弹出的是最小的,所以倒序来输出到数组result = [0] * kfor i in range(k-1, -1, -1):result[i] = heapq.heappop(pri_que)[1]return result

前K个高频元素–大顶堆小顶堆

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

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

相关文章

Spring 6【数据校验Validation、JSR 303 和 Hibernate 实现】(十三)-全面详解(学习总结---从入门到深化)

目录 数据校验Validation 2.JSR 303 和 Hibernate 实现 数据校验Validation 1.数据校验介绍 数据校验分为客户端数据校验和服务端数据校验。都是为了保证数据完整性的。 客户端数据校验直接使用客户端脚本校验即可。例如在B/S模型项目中&#xff0c;可以选择使用JavaScript…

CS144学习笔记(1):Internet and IP

1.网络应用 网络应用可以在世界范围内交换数据&#xff0c;例如你可以通过浏览器读取出版社服务器提供的文章。网络应用的基本模型&#xff1a;两台主机各自在本地运行一个程序&#xff0c;程序通过网络来通信。 最常用的通信模型使用双向可靠字节流&#xff0c;通信的两台主机…

集合操作,CollectionUtils工具类

集合操作,CollectionUtils工具类 这篇讲的是在apache下的CollectionUtils, 而不是springframework下的CollectionUtils。 首先需要引入相关jar包: <dependency><groupId>org.apache.commons</groupId><artifactId>commons-collections4</artifac…

HDU - 4546 比赛难度(Java JS Python)

题目来源 Problem - 4546 (hdu.edu.cn) 题目描述 最近&#xff0c;小明出了一些ACM编程题&#xff0c;决定在HDOJ举行一场公开赛。 假设题目的数量一共是n道&#xff0c;这些题目的难度被评级为一个不超过1000的非负整数&#xff0c;并且一场比赛至少需要一个题&#xff0c;…

实战:Docker+Jenkins+Gitee构建CICD流水线

文章目录 前言Jenkins部署创建Jenkins docker-compose配置maven源启动Jenkins容器安装插件Gitee ssh公匙配置与测试项目提交 Jenkins创建流水线写在最后 前言 持续集成和持续交付一直是当下流行的开发运维方式&#xff0c;CICD省去了大量的运维时间&#xff0c;也能够提高开发…

ElasticSearch基本使用--ElasticSearch文章一

文章目录 官网学习必要性elasticsearch/kibana安装版本数据结构说明7.x版本说明ElasticSearch kibana工具测试后续我们会一起分析 官网 https://www.elastic.co/cn/ 学习必要性 1、在当前软件行业中&#xff0c;搜索是一个软件系统或平台的基本功能&#xff0c; 学习Elastic…

Git克隆文件不显示绿色勾、红色感叹号等图标

1、问题 Git和TorToiseGit安装后&#xff0c;Git克隆的文件不会显示绿色勾、红色感叹号等图标。 2、检查注册表 2.1、打开注册表 (1)WinR打开运行窗口&#xff0c;输入regedit&#xff0c;点击确定&#xff0c;打开注册表编辑器。 2.2、找如下路径 (1)找到路径 计算机\HKEY_…

linux----vim的使用

vi和vim是Linux下的一个文本编辑工具&#xff0c;最小化安装只有vi vim&#xff0c;需要额外安装&#xff0c;比vi更强大一些 # vim 操作文件&#xff0c;有三种模式&#xff1a;普通模式&#xff0c;编辑模式&#xff0c;命令模式 -vim 文件名刚进来----》普通模式--》只…

VBA技术资料MF34:检查Excel自动筛选是否打开

【分享成果&#xff0c;随喜正能量】聪明人&#xff0c;抬人不抬杠&#xff1b;傻子&#xff0c;抬杠不抬人。聪明人&#xff0c;把别人抬得很高&#xff0c;别人高兴、舒服了&#xff0c;看你顺眼了&#xff0c;自然就愿意帮你&#xff01;而傻人呢&#xff1f;不分青红皂白&a…

golang sync.singleflight 解决热点缓存穿透问题

在 go 的 sync 包中&#xff0c;有一个 singleflight 包&#xff0c;里面有一个 singleflight.go 文件&#xff0c;代码加注释&#xff0c;一共 200 行出头。内容包括以下几块儿&#xff1a; Group 结构体管理一组相关的函数调用工作,它包含一个互斥锁和一个 map,map 的 key 是…

Golang之路---01 Golang的安装与配置

Golang之路—01 Golang语言安装与配置 官网上下载Windows环境下的安装包 官网下载地址 双击下载后的文件进行安装&#xff0c;可根据需要自定义选择解压后的文件位置。 接着新创建一个文件夹&#xff0c;保存Golang语言项目。 在里面新建bin,pkg,src三个文件夹。 环境变量…

Verilog语法学习——LV4_移位运算与乘法

LV4_移位运算与乘法 题目来源于牛客网 [牛客网在线编程_Verilog篇_Verilog快速入门 (nowcoder.com)](https://www.nowcoder.com/exam/oj?page1&tabVerilog篇&topicId301) 题目 题目描述&#xff1a; 已知d为一个8位数&#xff0c;请在每个时钟周期分别输出该数乘1/…

Linux:Linux的发展史和作用有哪些?

文章目录 Linux是什么&#xff1f;Linux的开源特征为什么要学习Linux&#xff1f;Linux的应用场景有哪些&#xff1f; Linux是什么&#xff1f; 简单来说&#xff0c;Linux就是操作系统&#xff0c;它和Windows等软件一样&#xff0c;都只是操作系统&#xff0c;并无区别 Linu…

CSS的一些基础知识

选择器&#xff1a; 选择器用于选择要应用样式的HTML元素。常见的选择器包括标签选择器&#xff08;如 div、p&#xff09;、类选择器&#xff08;如 .class&#xff09;、ID选择器&#xff08;如 #id&#xff09;和伪类选择器&#xff08;如 :hover&#xff09;。选择器可以根…

webpack优化前端框架性能

webpack优化目的 webpack优化目的1. 提升开发体验提升开发体验使用 SourceMap 2. 提升打包构建速度提升打包构建速度&#xff08;开发模式&#xff09;提升打包速度 oneOf提升打包速度 include&#xff08;包含&#xff09;/exclude&#xff08;排除&#xff09;提升第二次打包…

爬虫-requests-cookie登录古诗文网

一、前言 1、requests简介 requests是一个很实用的Python HTTP客户端库&#xff0c;爬虫和测试服务器响应数据时经常会用到&#xff0c;它是python语言的第三方的库&#xff0c;专门用于发送HTTP请求&#xff0c;使用起来比urllib更简洁也更强大。 2、requests的安装 pip i…

电脑选睡眠、休眠还是关机?

关机 这是大家最熟悉的。关机时&#xff0c;系统首先关闭所有运行中的程序&#xff0c;然后关闭系统后台服务。随后&#xff0c;系统向主板请求关机&#xff0c;主板断开电源的供电使能&#xff0c;让电源切断对绝大多数设备的供电&#xff08;只剩一些内部零件仍会维持电源供应…

华为刷题:HJ3明明随机数

import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main {public static void main(String[] args) {Scanner scan new Scanner(System.in);int N scan.nextInt();int[] arr new int[N];for (int i 0; i < N; i) {int n sca…

Materials - UE5中的PivotPainter

个人学习笔记的归档和发表&#xff1b;文中所有案例都来自官方的ContentExample中的PivotPainter相关关卡&#xff1b; 可以使用3DS Max Script中的脚本&#xff08;Pivot Painter&#xff09;对模型进行处理&#xff0c;让每个Element都有自己的Pivot Point&#xff0c;来方便…

PostgreSQL 简洁、使用、正排索引与倒排索引、空间搜索、用户与角色

PostgreSQL使用 PostgreSQL 是一个免费的对象-关系数据库服务器(ORDBMS)&#xff0c;在灵活的BSD许可证下发行。PostgreSQL 9.0 &#xff1a;支持64位windows系统&#xff0c;异步流数据复制、Hot Standby&#xff1b;生产环境主流的版本是PostgreSQL 12 BSD协议 与 GPL协议 …