LeetCode刷题:第二周

LeetCode刷题:第二周


相关系列笔记:
LeetCode刷题:前言
LeetCode刷题:第一周
LeetCode刷题:第二周

前言

  本周Topic是【链表】,对应的5道题:
    22.返回倒数第k个节点
    21.合并两个有序链表
    148.排序链表
    147.对链表进行插入排序
    25.K个一组翻转链表

知识点

1、链表

  链表(linked list) 是一组数据项的集合,其中每个数据项都是一个节点的一部分,每个节点还包含指向下一个节点的链接。

  链表的节点的结构如下:
在这里插入图片描述
  data为自定义的数据,next为下一个节点的地址。

  根据结构的不同,链表可以分为单向链表、单向循环链表、双向链表、双向循环链表等。其中,单向链表和单向循环链表的结构如下图所示:

在这里插入图片描述

2、单向链表的实现

1)Node实现

  每个Node分为两部分。一部分含有链表的元素,可以称为数据域;另一部分为一指针,指向下一个Node。

class Node():
    __slots__=['_item','_next']    #限定Node实例的属性
    def __init__(self,item):
        self._item=item
        self._next=None     #Node的指针部分默认指向None
    def getItem(self):
        return self._item
    def getNext(self):
        return self._next
    def setItem(self,newitem):
        self._item=newitem
    def setNext(self,newnext):
        self._next=newnext

2) SinglelinkedList的实现

class SingleLinkedList():  
    def __init__(self):
        self._head=None    #初始化链表为空表
        self._size=0

3) 检测链表是否为空

def isEmpty(self):
    return self._head==None 

4) add在链表前端添加元素

def add(self,item):
    temp=Node(item)
    temp.setNext(self._head)
    self._head=temp

5) append在链表尾部添加元素

def append(self,item):
    temp=Node(item)
    if self.isEmpty():
        self._head=temp   #若为空表,将添加的元素设为第一个元素
    else:
        current=self._head
        while current.getNext()!=None:
            current=current.getNext()   #遍历链表
        current.setNext(temp)   #此时current为链表最后的元素

6) search检索元素是否在链表中

def search(self,item):
    current=self._head
    founditem=False
    while current!=None and not founditem:
        if current.getItem()==item:
            founditem=True
        else:
            current=current.getNext()
    return founditem

7) index索引元素在链表中的位置

def index(self,item):
    current=self._head
    count=0
    found=None
    while current!=None and not found:
        count+=1
        if current.getItem()==item:
            found=True
        else:
            current=current.getNext()
    if found:
        return count
    else:
        raise ValueError,'%s is not in linkedlist'%item

8) remove删除链表中的某项元素

def remove(self,item):
    current=self._head
    pre=None
    while current!=None:
        if current.getItem()==item:
            if not pre:
                self._head=current.getNext()
            else:
                pre.setNext(current.getNext())
            break
        else:
            pre=current
            current=current.getNext()

9) insert链表中插入元素

def insert(self,pos,item):
   if pos<=1:
       self.add(item)
   elif pos>self.size():
       self.append(item)
   else:
       temp=Node(item)
       count=1
       pre=None
       current=self._head
       while count<pos:
           count+=1
           pre=current
           current=current.getNext()
       pre.setNext(temp)
       temp.setNext(current)

LeetCode例题

22. 括号生成

  数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合
    示例:
    输入:n = 3
    输出:[
       “((()))”,
       “(()())”,
       “(())()”,
       “()(())”,
       “()()()”
       ]

  实现
在这里插入图片描述

class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        #回溯法
        result = []
        def backtrack(left, right, tmp):
            if right > left or left > n: return
            if left + right == 2 * n:
                result.append(tmp)
                return
            backtrack(left + 1, right, tmp + '(')
            backtrack(left, right + 1, tmp + ')')
        backtrack(0, 0, '')
        return result

在这里插入图片描述

21. 合并两个有序链表

  将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的
     示例:
      输入:1->2->4, 1->3->4
      输出:1->1->2->3->4->4

  实现
在这里插入图片描述

# 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, l1: ListNode, l2: ListNode) -> ListNode:
        # 递归
        if l1 and l2:
            if l1.val > l2.val: 
                l1, l2 = l2, l1
            l1.next = self.mergeTwoLists(l1.next, l2)
        return l1 or l2

在这里插入图片描述

148. 排序链表

  给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表
  进阶:
    • 你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?
       示例 1:
在这里插入图片描述
        输入:head = [4,2,1,3]
        输出:[1,2,3,4]
      示例 2:
在这里插入图片描述
        输入:head = [-1,5,3,4,0]
        输出:[-1,0,3,4,5]
      示例 3:
        输入:head = []
        输出:[]

  实现
在这里插入图片描述

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def sortList(self, head: ListNode) -> ListNode:
        # 使用快慢指针寻找链表中点,分解链表,递归融合2个有序链表
        if not (head and head.next): 
            return head

        pre, slow, fast = None, head, head
        while fast and fast.next: 
            pre, slow, fast = slow, slow.next, fast.next.next
        pre.next = None
        return self.mergeTwoLists(*map(self.sortList, (head, slow)))
    
    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
        if l1 and l2:
            if l1.val > l2.val: l1, l2 = l2, l1
            l1.next = self.mergeTwoLists(l1.next, l2)
        return l1 or l2

在这里插入图片描述

147. 对链表进行插入排序

  对链表进行插入排序
在这里插入图片描述
     插入排序的动画演示如上。从第一个元素开始,该链表可以被认为已经部分排序(用黑色表示)。
    每次迭代时,从输入数据中移除一个元素(用红色表示),并原地将其插入到已排好序的链表中。
     插入排序算法:
       1. 插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。
       2. 每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。
       3. 重复直到所有输入数据插入完为止。
     示例 1:
       输入: 4->2->1->3
       输出: 1->2->3->4
    示例 2:
       输入: -1->5->3->4->0
       输出: -1->0->3->4->5

  实现
在这里插入图片描述

class Solution:
    def insertionSortList(self, head: ListNode) -> ListNode:
        # 找个排头
        dummy = ListNode(-1)
        pre = dummy
        # 依次拿head节点
        cur = head
        while cur:
            # 把下一次节点保持下来
            tmp = cur.next
            # 找到插入的位置
            while pre.next and pre.next.val < cur.val:
                pre = pre.next
            # 进行插入操作
            cur.next = pre.next
            pre.next = cur
            pre= dummy
            cur = tmp
        return dummy.next

在这里插入图片描述

25. K 个一组翻转链表

  给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
    k 是一个正整数,它的值小于或等于链表的长度。
    如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
       示例:
        给你这个链表:1->2->3->4->5
        当 k = 2 时,应当返回: 2->1->4->3->5
        当 k = 3 时,应当返回: 3->2->1->4->5

  实现
在这里插入图片描述

# 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: ListNode, k: int) -> ListNode:
        tmp = head
        for _ in range(k):         # 判断从当前节点起,够不够k个节点   【递归的终止条件】
            if tmp == None:        # 不够则后续节点都不用变动
                return head
            tmp = tmp.next
            
        # 设置两个指针             # 经过上面的终止条件后,下面要做的就是将一段长度为k的链表反转
        p, rev = head, None        # 起始情况 rev   p      ➡       走一步后   rev   p 
        for _ in range(k):         #         None   p0->p1->...pk-1    None <- p0   p1->...pk-1
            rev, rev.next, p = p, rev, p.next # 最终指针p指向pk-1.next, 也就是下一段的入口
        head.next = self.reverseKGroup(p, k)  # 进行递归             【递归入口】  
        return rev                 # rev恰好是原来长度为k的链表的末尾,也是当前这一段链表的头

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_42691585/article/details/115008627