链表基础概念与经典题目(Leetcode题解-Python语言)

所谓链表,就是由链节点元素组成的表,那什么是链节点呢?直接上定义:

class ListNode:def __init__(self, val=0, next=None):self.val = valself.next = next

很简单,链节点就是只记录自身的值 val,还有其指向的下一个链节点的位置 next

707. 设计链表

class ListNode:def __init__(self, val=0, next=None):self.val = valself.next = nextclass MyLinkedList:def __init__(self):self.size = 0self.head = ListNode(0)def get(self, index: int) -> int:if index < 0 or index >= self.size:return -1curr = self.head# 找到查找的位置for _ in range(index + 1):  # 注意是 index + 1curr = curr.nextreturn curr.val def addAtHead(self, val: int) -> None:self.addAtIndex(0, val)def addAtTail(self, val: int) -> None:self.addAtIndex(self.size, val)def addAtIndex(self, index: int, val: int) -> None:if index > self.size:returnif index < 0:index = 0# size加一,并且找到插入位置self.size += 1pred = self.headfor _ in range(index):pred = pred.next# 插入节点三步走:新建节点,新节点指向下一个节点,新节点被上一个节点指向to_add = ListNode(val)to_add.next = pred.nextpred.next = to_adddef deleteAtIndex(self, index: int) -> None:if index < 0 or index >= self.size:return# size减一,并且找到删除位置self.size -= 1pred = self.headfor _ in range(index):pred = pred.next# 直接跳过节点即为删除pred.next = pred.next.next

由链节点出发,设计单链表的思路如下:初始化的时候,要新建一个头节点 head(即第一个节点),同时为了方便要记录链表的大小 size。然后就是三种操作:查找、插入和删除

查找:首先判断索引是否越界,越界就返回 -1,不越界才继续。从头节点开始,根据链节点 的 next 找到其下一个节点,循环 index 次找到目标节点,返回其值。注意是写成 range(index + 1) !!

插入:同样先判断是否越界。不越界则可以插入,此时链表的大小 size 会 +1,接着循环 index 次找到目标节点(插入位置),然后是插入三步走:新建节点,新节点指向下一个节点,新节点被上一个节点指向。对于从头部、中间、尾部插入都一样,只是位置不同而已。

删除:同样先判断是否越界。不越界则可以删除,此时链表的大小 size 会 -1,接着循环 index 次找到目标节点(删除位置),然后直接跳过此节点 next = next.next,即为删除。

剑指 Offer 22. 链表中倒数第k个节点(面试题 02.02. 返回倒数第 k 个节点)

class Solution:def getKthFromEnd(self, head: ListNode, k: int) -> ListNode:nums = []while head:nums.append(head)head = head.nextreturn nums[-k]

遍历链表,返回倒数第k个节点的值。当然也可以用双指针,一个指针先走 k 步,然后再一起走,那先出发的指针到最后时,后出发的指针正好在倒数第 k 个节点处,代码如下:

class Solution:def getKthFromEnd(self, head: ListNode, k: int) -> ListNode:fast = headslow = headfor i in range(k):if not fast:return Nonefast = fast.nextwhile fast:fast = fast.nextslow = slow.nextreturn slow

剑指 Offer 06. 从尾到头打印链表

class Solution:def reversePrint(self, head: ListNode) -> List[int]:nums = []while head:nums.append(head.val)head = head.nextreturn nums[::-1]

遍历链表,倒序返回链表所有的值。

876. 链表的中间结点

class Solution:def middleNode(self, head: ListNode) -> ListNode:all_nodes = []while head:all_nodes.append(head)head = head.nextreturn all_nodes[len(all_nodes) // 2]

遍历链表,记录链节点,然后返回中间那个。当然,更好地是用快慢指针,慢指针每次移到next,快指针每次移到 next 的 next,循环结束返回慢指针即为中间节点。如下代码所示:

class Solution:def middleNode(self, head: ListNode) -> ListNode:fast = headslow = headwhile fast and fast.next:  # 两个中间结点取后者,就这样写fast = fast.next.nextslow = slow.nextreturn slow

如果两个中间结点要取前者,条件就变为 fast.next and fast.next.next,如下所示:

class Solution:def middleNode(self, head: ListNode) -> ListNode:fast = headslow = headwhile fast.next and fast.next.next:  fast = fast.next.nextslow = slow.nextreturn slow

141. 环形链表

class Solution:def hasCycle(self, head: ListNode) -> bool:if not head or not head.next:return Falseslow, fast = head, headwhile fast and fast.next:slow = slow.nextfast = fast.next.nextif slow == fast:return Truereturn False

快慢指针更典型的例子是环形链表,如果链表是有环的,则快指针一定会从后面追上慢指针,否则它们不会相遇。这是因为如果快慢指针都进入了环,则由于快指针比慢指针速度快了 1,所以它们之间的距离一定是能被缩小到 0 的。

使用快慢指针时要注意:如果初始化两个指针都是 head,则 while 循环中必须先赋值再判断是否相等,而不能先判断相等(因为初始时就是相等的)。

142. 环形链表 II(剑指 Offer II 022. 链表中环的入口节点)(面试题 02.08. 环路检测)

class Solution:def detectCycle(self, head: ListNode) -> ListNode:if not head or not head.next:return Noneslow, fast = head, headflag = Falsewhile fast and fast.next:slow = slow.nextfast = fast.next.nextif slow == fast:flag = Truebreakif not flag:return Noneans = headwhile ans != slow:ans = ans.nextslow = slow.nextreturn ans

这题不仅要判断是否环形,还要找出入环点,作图分析即可,假设链表头到入环点距离为 D,慢指针走了 D + S1 的距离,快指针走了 D + S1 + n(S1 + S2) 的距离,其中 S1 + S2 为一圈的长度。显然,D + S1 + n(S1 + S2) = 2 (D + S1),可得 D = (n - 1)(S1 + S2) + S2,由于慢指针已经从入环点开始走了 S1,因此它只要再走 (n - 1)(S1 + S2) + S2 步,即可到达入环点,而这个步数可由另一个慢指针从链表头开始走 D 步来匹配。注意不要漏了 break!

160. 相交链表(剑指 Offer II 023. 两个链表的第一个重合节点)(面试题 02.07. 链表相交)

class Solution:def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:curA = headAcurB = headBwhile curA != curB:curA = curA.next if curA else headBcurB = curB.next if curB else headAreturn curA

同样是双指针思路(非快慢),分别从两个链表同时出发,遍历完一个链表就去遍历另一个链表,如果链表相交,则两个指针一定相遇于交点,否则同时为 None。注意必须是 if curA 而不是 if curA.next,才能使得 curA == curB == None,否则它们是不会变为 None 的。

61. 旋转链表

class Solution:def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:if not head:return Nonecur = headlength = 1while cur.next:cur = cur.nextlength += 1cur.next = headnew_tail = headfor _ in range((length - k - 1) % length):new_tail = new_tail.nextnew_head = new_tail.nextnew_tail.next = Nonereturn new_head

这题把链表变成环形之后,找到目标切分点即可。注意到切分点左右分别是新的尾节点 new_tail 和新的头节点 new_head,而新的尾节点 new_tail 距离原头节点 head 有 length - k - 1,且这个距离是随着 k 增大重复出现的,所以还得对 length 取余。

203. 移除链表元素(剑指 Offer 18. 删除链表的节点)

class Solution:def removeElements(self, head: ListNode, val: int) -> ListNode:dummy_head = ListNode(next=head) cur = dummy_headwhile cur.next:if cur.next.val == val:cur.next = cur.next.nextelse:cur = cur.nextreturn dummy_head.next

设置一个虚拟头节点 dummy_head,然后判断 cur.next 是否是目标值,如果是则删除(cur.next 指向 cur.next.next),如果不是则移动到 cur.next,循环判断 cur.next。最后返回虚拟头节点的 next ,即真正的头节点。

237. 删除链表中的节点(面试题 02.03. 删除中间节点)

class Solution:def deleteNode(self, node):""":type node: ListNode:rtype: void Do not return anything, modify node in-place instead."""node.val = node.next.valnode.next = node.next.next

题目给出要删除的中间节点 node 而不是头节点,那就把该节点 node 变成其下一个节点 node.next,然后删除下一个节点即可。

83. 删除排序链表中的重复元素

class Solution:def deleteDuplicates(self, head: ListNode) -> ListNode:if not head:return headcur = headwhile cur.next:if cur.val == cur.next.val:cur.next = cur.next.nextelse:cur = cur.nextreturn head

删除排序链表中的重复元素,判断当前节点与下一个节点是否相等即可。如果下一个节点的值与当前节点的值相同,就把当前节点的 next 指针往后移,直到指针指向了一个与当前节点值有不同值的节点,然后跳到这个节点,重复开始判断。

由于这题是一定不会删除头节点的,所以不需要创建虚拟头节点,但如果创建,必须保证虚拟头节点的值在链表节点值的范围之外

82. 删除排序链表中的重复元素 II

class Solution:def deleteDuplicates(self, head: ListNode) -> ListNode:if not head:return headdummy_head = ListNode(101, head)pre = dummy_headcur = pre.nextwhile cur and cur.next:if cur.val == cur.next.val:while cur.next and cur.val == cur.next.val:cur = cur.nextpre.next = cur.nextcur = cur.nextelse:pre = pre.nextcur = cur.nextreturn dummy_head.next

由于要删除所有重复出现的节点,所以用 pre 记录上一个不重复节点的位置,cur 遇到重复元素则一直到重复区间的最后。创建虚拟头节点,必须保证它的值在链表节点值的范围之外

面试题 02.01. 移除重复节点

class Solution:def removeDuplicateNodes(self, head: ListNode) -> ListNode:if not head:return headnums = {head.val}cur = headwhile cur.next:if cur.next.val in nums:cur.next = cur.next.nextelse:nums.add(cur.next.val)cur = cur.nextreturn head

与上一题相比,链表不是有序的,所以得用哈希表(集合)记录出现过的元素,后面如果再次出现则删除。

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

class Solution:def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:dummyHead = ListNode(0, head)fast = dummyHeadslow = dummyHeadfor _ in range(n):fast = fast.nextwhile fast.next:fast = fast.nextslow = slow.nextslow.next = slow.next.nextreturn dummyHead.next

删除链表的倒数第 n 个节点,用双指针法,第一个指针先遍历 n 次,然后两个指针一起遍历,这样当第一个指针遍历完之后,第二个指针正好遍历了(链表长度 - n)次,其位置即为要删除的位置。注意由于可能删除头节点,所以要用 dummyHead。

24. 两两交换链表中的节点

class Solution:def swapPairs(self, head: ListNode) -> ListNode:if not head or not head.next:return headdummyHead = ListNode(0, head)pre = dummyHeadcur = dummyHead.nextwhile cur and cur.next:# cur 与 post 进行交换post = cur.nextcur.next = post.nextpost.next = pre.nextpre.next = post# 来到下一个位置pre = curcur = cur.nextreturn dummyHead.next

pre 初始化为 dummyHead,然后看后面是否有两个节点,有的话就交换这两个节点,并且pre 等于交换后的在后面的节点(也是交换前的在前面的节点),继续看看后面是否有一对节点,如果没有则直接返回。对于交换写法,可以发现变量是头尾相连的,以此作为记忆。

206. 反转链表(剑指 Offer 24. 反转链表)(剑指 Offer II 024. 反转链表)

迭代法

class Solution:def reverseList(self, head: ListNode) -> ListNode:pre = Nonecur = headwhile cur:temp = cur.next     # 把下个指针记到 tempcur.next = pre      # cur 的 next 指针反过来指向 prepre = cur           # 已反向的 cur 变为 precur = temp          # cur 向右移一位return pre	

使用前一个节点 pre 和当前节点 cur。在节点 cur 时,先把下个指针记到 temp,然后 cur 的 next 指针反过来指向 pre,已反向的 cur 变为 pre,然后 cur 向右移一位,直到链表结束。在写法上,可以发现变量是头尾相连的,以此作为记忆。

递归法

class Solution:def reverse(self, pre, cur):if cur == None:return pretemp = cur.nextcur.next = prereturn self.reverse(cur, temp)def reverseList(self, head: ListNode) -> ListNode:return self.reverse(None, head)

无非就是用递归代替了 pre 与 cur 后移一位的操作而已。

从后往前的递归法

class Solution:def reverseList(self, head: ListNode) -> ListNode:if not head or not head.next:return headcur = self.reverseList(head.next) # 找到链表尾部head.next.next = head             # 把下个节点的 next 指针指向自己head.next = None                  # 删掉自己指向下个节点的 nextreturn cur

先找到链表尾部,然后从尾部开始把下个节点的 next 指针指向自己,同时删掉自己指向下个节点的 next,递归返回前一个节点,直到遇到空节点为止(从尾部到头部)。

92. 反转链表 II

class Solution:def reverseBetween(self, head: ListNode, left: int, right: int) -> ListNode:dummy_head = ListNode(-1)dummy_head.next = headpre = dummy_headfor _ in range(left - 1):pre = pre.nextcur = pre.nextfor _ in range(right - left):post = cur.next          # post一定是cur的nextcur.next = post.next     # 让cur指向后两位post.next = pre.next     # post指向头后一位pre.next = post          # 头后一位变为postreturn dummy_head.next

这题要求反转链表中的某一段,头插法是很不错的解法,思路详细看这篇题解。大概就是说,找到要反转的区域,然后遍历其中的元素,每次都把元素移动到区域的最前面(头插),这样遍历完整个区域,也就完成了反转。pre 恒为区域外左边第一个节点;而 cur 是最开始 pre 的后一个节点,例如示例图中值为 2 的节点,只不过 cur 会不断地往右移位;每次遍历时 post 作为 cur.next,都会被送到 pre 的右边(即区域的最前面)。

在这里插入图片描述

25. K 个一组翻转链表

class Solution:def reverseKGroup(self, head: ListNode, k: int) -> ListNode:count = 0cur = headwhile cur:cur = cur.nextcount += 1dummy_head = ListNode(-1)dummy_head.next = headpre = dummy_headcur = pre.nextfor _ in range(count // k):for _ in range(k - 1):temp = cur.nextcur.next = temp.nexttemp.next = pre.nextpre.next = temppre = curcur = pre.nextreturn dummy_head.next

一道困难题,借鉴上题的头插法思路就不难了。首先得到链表的长度 count,可知一共要反转(count // k)组,之后在每组内进行头插法,搞完一组后更新一下 pre 和 cur 即可。

2. 两数相加(面试题 02.05. 链表求和)

class Solution:def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:sum = l1.val + l2.valcarry = sum // 10head = ListNode(sum % 10)node = headwhile l1.next or l2.next or carry:l1 = l1.next if l1.next else ListNode(0)l2 = l2.next if l2.next else ListNode(0)sum = l1.val + l2.val + carrycarry = sum // 10node.next = ListNode(sum % 10)node = node.nextreturn head

两个链表对应位置相加,注意数字是逆序存储的,即链表头的数字是最低位,所以相加时会产生进位。两个链表不等长的话短的那个加0,余数作为结果链表的新节点,而商数除以10后作为进位(下一位的加数之一),最后如果还有一个进位不要漏了。

写法统一后面那题的话,就是用队列:

class Solution:def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:q1, q2 = [], []while l1:q1.append(l1.val)l1 = l1.nextwhile l2:q2.append(l2.val)l2 = l2.nexthead = ListNode(0)node = headcarry = 0while q1 or q2 or carry != 0:a = q1.pop(0) if q1 else 0b = q2.pop(0) if q2 else 0sum = a + b + carrycarry = sum // 10newNode = ListNode(sum % 10)node.next = newNodenode = node.nextreturn head.next

445. 两数相加 II(剑指 Offer II 025. 链表中的两数相加)

class Solution:def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:s1, s2 = [], []while l1:s1.append(l1.val)l1 = l1.nextwhile l2:s2.append(l2.val)l2 = l2.nexthead = Nonecarry = 0while s1 or s2 or carry != 0:a = s1.pop() if s1 else 0b = s2.pop() if s2 else 0sum = a + b + carrycarry = sum // 10newNode = ListNode(sum % 10)newNode.next = headhead = newNodereturn head

这题的两数相加是正序的,做三次反转链表也可以。此处用的是两个栈,注意输出也得是正序,所以链表是从尾部开始生成的,head 每次移动到新节点,直到结束才知道 head 。

234. 回文链表(剑指 Offer II 027. 回文链表)(面试题 02.06. 回文链表)

回文链表最简单的思路是遍历链表,用数组记录所有元素,然后判断数组正序是否等于逆序即可。更好的方法是使用快慢指针,如下:

class Solution:def isPalindrome(self, head: ListNode) -> bool:    if not head:return True# 找到前半部分链表的尾节点并反转后半部分链表first_half_tail = self.findMiddle(head)second_half_head = first_half_tail.nextsecond_half_head = self.reverseList(second_half_head)# 判断是否回文flag = Truep1 = headp2 = second_half_headwhile p2:if p1.val != p2.val:flag = Falsebreakp1 = p1.nextp2 = p2.next# 还原链表并返回结果second_half_head = self.reverseList(second_half_head)first_half_tail.next = second_half_headreturn flagdef findMiddle(self, head):fast = headslow = headwhile fast.next and fast.next.next:fast = fast.next.nextslow = slow.nextreturn slowdef reverseList(self, head):pre = Nonecur = headwhile cur:temp = cur.nextcur.next = prepre = curcur = tempreturn pre

思路很简单,首先是用快慢指针找到链表的中间位置,然后把后半部分的链表反转,接着就可以逐一判断前后两部分的元素是否相等,用 result 进行记录,最后再把后半部分链表反转回去(不改变链表结构)。

21. 合并两个有序链表(剑指 Offer 25. 合并两个排序的链表)

class Solution:def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:head = ListNode(0)cur = headwhile l1 and l2:if l1.val < l2.val:cur.next = l1l1 = l1.nextelse:cur.next = l2l2 = l2.nextcur = cur.nextcur.next = l1 if l1 else l2return head.next

合并两个有序的链表,方法就是新建一个节点 head,迭代进行:如果两个链表都非空,就让新链表指向数值小的节点,然后移动下一位,直到其中一个链表为空,则把另一个链表作为新链表剩下的部分。

23. 合并K个升序链表(剑指 Offer II 078. 合并排序链表)

class Solution:def mergeKLists(self, lists: List[ListNode]) -> ListNode:dummy_head = ListNode(0)cur = dummy_headheap = []for i in range(len(lists)):  # 将K个链表的头都加入到最小堆中if lists[i] :heapq.heappush(heap, (lists[i].val, i))lists[i] = lists[i].nextwhile heap:val, idx = heapq.heappop(heap)   # 弹出最小值cur.next = ListNode(val)  # 将最小值加入合并链表中cur = cur.nextif lists[idx]:      # 若最小值有后续节点,则加入到最小堆中,继续遍历heapq.heappush(heap, (lists[idx].val, idx))lists[idx] = lists[idx].nextreturn dummy_head.next

合并 K 个有序链表,每次合并时要取得 K 个数中的最小值,使用最小堆即可。将 K 个链表的头都加入到最小堆中,注意元组的成员得是值 val 和索引 i,而不能是值 val 和节点 ListNode,因为节点是不支持比较的,无法排序,所以不能放在堆中。

86. 分隔链表(面试题 02.04. 分割链表)

class Solution:def partition(self, head: ListNode, x: int) -> ListNode:if not head:return headsmall = ListNode(0)small_head = smalllarge = ListNode(0)large_head = largewhile head:if head.val < x:small_head.next = headsmall_head = small_head.nextelse:large_head.next = headlarge_head = large_head.nexthead = head.nextlarge_head.next = Nonesmall_head.next = large.nextreturn small.next

这题思路不难,就是用 small 和 large 两个链表分别记录比 x 小和比 x 大(或等)的节点,然后 small 拼接上 large,large 末尾指向 None 即可。

328. 奇偶链表

class Solution:def oddEvenList(self, head: ListNode) -> ListNode:if not head or not head.next or not head.next.next:return headoddHead = headevenHead = head.nextodd = oddHeadeven = evenHeadwhile even and even.next:odd.next = odd.next.nexteven.next = even.next.nextodd = odd.nexteven = even.nextodd.next = evenHeadreturn oddHead

这题固然也可以像上一题那样,开两个链表来记录,但是麻烦了。由于都在同一个链表中,所以直接两两改变链接就行了。

143. 重排链表(剑指 Offer II 026. 重排链表)

class Solution:def reorderList(self, head: ListNode) -> None:"""Do not return anything, modify head in-place instead."""if not head:returnl1 = headmiddle_node = self.middleNode(head)l2 = middle_node.nextmiddle_node.next = Nonel2 = self.reverseNode(l2)self.mergeList(l1, l2)def middleNode(self, head: ListNode) -> ListNode:slow, fast = head, headwhile slow.next and fast.next and fast.next.next:slow = slow.nextfast = fast.next.nextreturn slowdef reverseNode(self, head: ListNode) -> ListNode:pre = Nonecur = headwhile cur:temp = cur.nextcur.next = prepre = curcur = tempreturn predef mergeList(self, l1: ListNode, l2: ListNode) -> ListNode:while l1 and l2:l1_temp = l1.nextl2_temp = l2.next# 让l1指向l2,l2指向l1.next,即摆动了两个指针,然后都移动到下一位            l1.next = l2l1 = l1_templ2.next = l1l2 = l2_temp

此题思路可以分为三步走:
1、找到原链表的中点(876. 链表的中间结点)
2、将原链表的右半端反转(206. 反转链表)
3、将原链表的两端合并(21. 合并两个有序链表)

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

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

相关文章

leetcode674. 最长连续递增序列

一:题目 二:上码 1:方法一贪心 class Solution { public:/**思路:1.贪心**/int findLengthOfLCIS(vector<int>& nums) {int ans 1;int count 1;for (int i 1; i < nums.size(); i) {if(nums[i] > nums[i-1]) {count;}else{count 1;//出现不连续的状态}if…

WPF 从 .net core 3.1 到 .net 5.0

WPF 从 .net core 3.1 到 .net 5.0Intro昨天更新了一个简单的 asp.net core webapi 项目&#xff0c;从 3.1 更新到了 5.0&#xff0c;今天更新一个 WPF 应用到 net 5.0项目文件更新首先项目文件中的 SDK 发生了变化&#xff0c;原来是 Microsoft.NET.Sdk.WindowsDesktop 更新后…

进击吧! Blazor !第三期 信息交互

Blazor 是一个 Web UI 框架&#xff0c;可通过 WebAssembly 在任意浏览器中运行 .Net 。Blazor 旨在简化快速的单页面 .Net 浏览器应用的构建过程&#xff0c;它虽然使用了诸如 CSS 和 HTML 之类的 Web 技术&#xff0c;但它使用 C&#xff03;语言和 Razor 语法代替 JavaScrip…

leetcode718. 最长重复子数组

一:题目 二:上码 class Solution { public:/**思路:1.分析题意:1 2 3 6 7 41 2 6 7 4 3这里我们先遇到的1 2 但后来我们又遇见了6 7 4 那么我们的要的答案就是动态变化的2.动态规划五步走1>:确定dp数组以及下标的含义dp[i][j] 表示 以下标i-1结尾的A数组和以下标…

.NET 5 的 Target Framework 详解[上篇]

❝作者&#xff1a;.NET Team翻译&#xff1a;精致码农-王亮原文&#xff1a;http://dwz.win/Q4v❞我们希望极大地简化开发人员必须在项目文件和 NuGet 包中使用的「TFM」 (Target Framework Name, 目标框架名称)。这包括合并 .NET 5 和 .NET Standard 的概念&#xff0c;同时仍…

leetcode1143. 最长公共子序列

一&#xff1a;题目 二:上码 class Solution { public:/**思路:1.分析题意这个子序列就是我们是可以不连续的字符组成的2.动态规划五步走1>:确定dp数组的含义以及下标的含义dp[i][j] 表示的是text1中[0,i-1]字符范围,text2中[0,j-1]的字符范围 的最长公共子序列这里我们取i…

JAVA 15发布,越来越像C# ?9月排名,C#增幅狠甩JAVA

2016年.NET Core首个正式版本问世&#xff0c;如今已发布到了.NET Core3.1&#xff0c;再有2个月.NET5也将如约而至&#xff0c;跨平台开发已经快5年。微软 .NET 程序管理总监 Scott 表示&#xff0c;.NET 5 是 .NET Framework 和 .NET Core 的未来&#xff0c;最终将成为一个统…

leetcode1035. 不相交的线

一:题目 二:上码 class Solution { public:/**思路:1.分析题意:这里的我们要求解的是最大值,那么我们的求解过程肯定是动态变化的,举个例子2 5 1 2 510 5 2 1 5 2 如果我们一开始就让nums1[1] 5何 nums2[4] 5 相连的话 那么我们肯定不会求解出最大值那么题目中的说的直线不…

几个超级实用但很少人知道的 VS 技巧[更新]

大家好&#xff0c;今天分享几个我知道的实用 VS 技巧&#xff0c;而这些技巧我发现很多人都不知道。因为我经常在工作中遇到&#xff1a;我在同事电脑上解决问题&#xff0c;或在会议上演示代码示例时&#xff0c;使用了一些 VS “骚”操作&#xff0c;他们会好奇地问&#xf…

leetcode53. 最大子数组和(动态规划)

一:题目 二:上码 class Solution { public:int maxSubArray(vector<int>& nums) {/**动态规划:1>:确定dp数组的含义以及下标的含义dp[j]表示的是下标j之前的最大子数组和 这个就是还没有包括nums[j] 2>:确定dp数组的状态转移公式dp[j] max (dp[j-1]nums[j],n…

基于REACT和.NET CORE集成WINDOWS身份验证

有很多方法可以向您的应用程序添加身份验证。虽然OAuth是最常见的一种&#xff0c;但这并不是您唯一的选择。今天&#xff0c;我将向您展示如何通过React和.NET Core简单地完成Windows身份验证。探索我们的选择在深入探讨之前&#xff0c;让我们简要讨论一些可用的其他选项。了…

.NET Core加解密实战系列之——使用BouncyCastle制作p12(.pfx)数字证书

简介加解密现状&#xff0c;编写此系列文章的背景&#xff1a;需要考虑系统环境兼容性问题&#xff08;Linux、Windows&#xff09;语言互通问题&#xff08;如C#、Java等&#xff09;&#xff08;加解密本质上没有语言之分&#xff0c;所以原则上不存在互通性问题&#xff09;…

leetcode115. 不同的子序列

一&#xff1a;题目 二:代码 class Solution { public:/**思路:动规分析走一波1>:确定dp数组以及下标的含义dp[i][j] 表示的是 以下标i-1结尾的子序列s中出现以j-1结尾的子序列t的 个数2>:确定dp数组的状态递推公式这里考虑两种状况 一种就是 s[i-1] s[j-1] 一种就是字…

ASP.NET Core 3.x启动时运行异步任务(二)

这一篇是接着前一篇在写的。如果没有看过前一篇文章&#xff0c;建议先去看一下前一篇&#xff0c;这儿是传送门一、前言前一篇文章&#xff0c;我们从应用启动时异步运行任务开始&#xff0c;说到了必要性&#xff0c;也说到了几种解决方法&#xff0c;及各自的优缺点。最后&a…

leetcode583. 两个字符串的删除操作

一:题目 二:上码 class Solution { public:/**思路:题目给的是让求最值,那么首先就会想到的是动态规划,我们想得到答案的结果其实有多个的&#xff0c;但是我们是取最小的步数动态规划 五步走:1>:确定dp数组以及下标的含义dp[i][j]表示的是 以下标i-1结尾的字符串word1,和…

C# 中居然也有切片语法糖,太厉害了

一&#xff1a;背景 1. 讲故事昨天在 github 上准备找找 C# 9 又有哪些新语法糖可以试用&#xff0c;不觉在一个文档上看到一个很奇怪的写法: foreach (var item in myArray[0..5]) 哈哈&#xff0c;熟悉又陌生&#xff0c;玩过python的朋友对这个 [0..5] 太熟悉不过了&#x…

跟我一起学.NetCore之中间件(Middleware)简介和解析请求管道构建

前言中间件(Middleware)对于Asp.NetCore项目来说&#xff0c;不能说重要&#xff0c;而是不能缺少&#xff0c;因为Asp.NetCore的请求管道就是通过一系列的中间件组成的&#xff1b;在服务器接收到请求之后&#xff0c;请求会经过请求管道进行相关的过滤或处理&#xff1b;正文…

leetcode647. 回文子串

一&#xff1a;题目 二&#xff1a;上码 class Solution { public:/**思路:动态规划五步走1>:确定dp数组以及下标的含义dp[i][j] 表示的是在[i,j]范围内的字串 是否是 回文子串&#xff0c;如果是的话那么dp[i][j] true2>确定dp数组的状态转移方程那么就有两种情况 s[i…

leetcode516. 最长回文子序列

一:题目 二:上码 class Solution { public:/**思路:1.分析题意 这个是让我们求最值,那么首先想到动态规划2.动态规划1>:确定dp数组以及下标的含义dp[i][j] 表示字符串在[i,j]范围内的最长回文子序列2>:确定dp数组的状态递推公式那么就是s[i] 与 s[j] 相等 不相等两种情况…

C#刷剑指Offer | 二叉搜索树的后序遍历序列

【C#刷题】| 作者 / Edison Zhou这是EdisonTalk的第289篇原创内容我们来用之前学到的数据结构知识来刷《剑指Offer》的一些核心题目&#xff08;精选了其中30道题目&#xff09;&#xff0c;希望对你有帮助&#xff01;本文题目为&#xff1a;二叉搜索树的后序遍历序列。1题目介…