链表-02

链表-02


思路:

链表的题目主要涉及:链表的增、删、改和查,这4种

注意:

  1. 当仅仅对链表进行遍历时,链表是不变的,其余的3种操作都会改变链表的值和next节点

  2. 删除节点时,最好用哑变量(指向头结点的节点),防止删除后的链表为空的情况

  3. 循环向链表中添加节点时,一定要记得添加完一个节点后,指针要往后移动

  4. 修改链表时,如果要更改某个节点,并且之后还要用到这个节点,一定要把这个节点保存在变量中,以防丢失

  5. 在遍历链表时,一定要记得先判断节点是否为空

2. 两数相加

思路:链表的遍历和新链表的创建(添加节点); 当循环向链表中添加元素时,一定要记得指针后移

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

class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        res = ListNode(0) #根节点
        node = res # 根节点的指针
        carry = 0
        while (l1!=None or l2!=None):
            
            v1 = l1.val if l1 else 0
            v2 = l2.val if l2 else 0
            sum_ = carry+v1+v2
            
            node.next = ListNode(sum_%10) # 添加节点
            node = node.next #指针后移
            carry = sum_//10
            l1 = l1.next if l1 else None #链表的遍历
            l2 = l2.next if l2 else None 
        if carry!=0:
            node.next = ListNode(carry)
        return res.next
19. 删除链表的倒数第N个节点

思路:链表的遍历 和节点的删除

链表的删除最好使用哑变量,以防删除后是空链表的情况

方法1:一次遍历

根据 k + (n-k) = (n-k) +k 的原理,先让指针往前一定k个节点,然后同时移动p和q,这样当指针p走完全程后,指针q刚好走到倒数第k个节点。

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

class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        if not head:
            return head 
        dummy = ListNode(-1)
        dummy.next = head 
        p = dummy 
        q = dummy

        while n+1:
            p = p.next 
            n-=1
        
        while p:
            p = p.next 
            q = q.next 
        q.next = q.next.next 
        return dummy.next 

方法2:两次遍历,第一次遍历计算链表的长度len,第二次遍历找到len-n的前一个节点

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

class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        if not head:
            return head 
        length = 0
        node = head 
        while node:
            length += 1
            node = node.next 
        
        m = length - n -1 
        if m <0:
            return head.next 
        node = head 
        while m:
            node = node.next 
            m-=1
        node.next = node.next.next 
        return head 
面试题 02.02. 返回倒数第 k 个节点
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def kthToLast(self, head: ListNode, k: int) -> int:
        p = head 
        q = head 
        while k:
            p = p.next 
            k-=1
        while p:
            p = p.next 
            q = q.next 
        return q.val 
面试题18. 删除链表的节点

思路:删节点时首先要判断,是否删除根节点;如果不想判断可以 用哑变量

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

class Solution:
    def deleteNode(self, head: ListNode, val: int) -> ListNode:
        if head.val == val:
            head = head.next
            return head 

        curr = head 
        while curr.next and curr.next.val!=val:
            curr = curr.next 
        curr.next = curr.next.next 
        return head

方法2:使用哑变量

    def deleteNode(self, head: ListNode, val: int) -> ListNode:
        dummy = ListNode(-1)
        dummy.next = head 
        pre = dummy 
        while pre.next and pre.next.val!=val:
            pre = pre.next 
        pre.next = pre.next.next 
        return dummy.next 
21. 合并两个有序链表

思路:节点的插入

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

class Solution:
    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
        if not l1 and not l2:
            return None 

        arr = []
        while l1:
            arr.append(l1.val)
            l1 = l1.next 
        while l2:
            arr.append(l2.val)
            l2 = l2.next 
        arr.sort()
        dummpy = ListNode(0)
        node = dummpy
        for num in arr:
            node.next = ListNode(num)
            node = node.next 
        return dummpy.next 
23. 合并K个排序链表

思路:链表的遍历和添加节点

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

class Solution:
    def mergeKLists(self, lists: List[ListNode]) -> ListNode:
        arr = []
        for i in range(len(lists)):
            while lists[i]:
                arr.append(lists[i].val)
                lists[i] = lists[i].next 
        arr_sort = sorted(arr)
        dummpy = ListNode(0)
        node = dummpy 
        for num in arr_sort:
            node.next = ListNode(num)
            node = node.next 
        return dummpy.next 
61. 旋转链表

思路:链表的遍历和节点的插入

将倒数第一个节点插入到链表的头部,并将倒数第二个节点的next设置为None, 因此每次遍历需要找到倒数第二个节点

注意一定要保证最后一个节点的next是None,否则算法会卡壳

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

class Solution:
    def rotateRight(self, head: ListNode, k: int) -> ListNode:
        if not head:
            return head 
        if not head.next:
            return head 
        length = 0
        node = head 
        while node:
            length += 1
            node = node.next 
        k = k%length
        for i in range(k):
            node = head 
            pre = head 
            while node.next and node.next.next:
                node = node.next            
            
            tail = node.next 
            node.next = None
            tail.next = head 
            head = tail 
        return head 
82. 删除排序链表中的重复元素 II

思路:首先对原链表中的节点值进行去重,然后对去重后的节点值,创建新的链表

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

class Solution:
    def deleteDuplicates(self, head: ListNode) -> ListNode:
        if not head:
            return None 
        arr = []
        node = head 
        while node:
            arr.append(node.val)
            node = node.next 
        dic = {}
        for num in arr:
            dic[num] = dic.get(num, 0)+1
        uniq_arr = []
        for num, cnt in dic.items():
            if cnt ==1:
                uniq_arr.append(num) 
        dummy = ListNode(-1)
        node = dummy
        for num in uniq_arr:
            node.next = ListNode(num)
            node = node.next 
        return  dummy.next
83. 删除排序链表中的重复元素

思路:元素的删除

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

class Solution:
    def deleteDuplicates(self, head: ListNode) -> ListNode:
        if not head:
            return None 
        node = head 
        while node and node.next:
            if node.val == node.next.val:
                node.next = node.next.next 
            else:
                node = node.next 
        return head 
86. 分隔链表

思路:在链表的遍历时,将小于x的节点加入到before链表中,将大于等于x的节点加入到after中,然后before链表再跟after链表合并起来

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
import numpy 
class Solution:
    def partition(self, head: ListNode, x: int) -> ListNode:
        before = before_head = ListNode(0)
        after = after_head = ListNode(0)
        while head:
            if head.val >=x:
                after.next= head 
                after = after.next 
            else:
                before.next = head 
                before = before.next 
            head = head.next 
        after.next = None
        before.next = after_head.next 
        return before_head.next
206. 反转链表
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        if not head:
            return None 

        pre = None 
        curr = head 
        while curr:
            post = curr.next 
            curr.next = pre 
            pre = curr
            curr = post
        return pre 
234. 回文链表

思路:使用快慢指针,找到中间节点;判断前半部分跟后半部分的节点是否对称

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

class Solution:
    def isPalindrome(self, head: ListNode) -> bool:
        if not head or not head.next:
            return True 

        s = head
        f = head 
        pre_list = [head.val]
        while f and f.next:
            f = f.next.next             
            s = s.next 
            pre_list.append(s.val)
        if not f:
            pre_list.pop()
        post_node = s 
        post_list = []
        while post_node:
            post_list.append(post_node.val)
            post_node = post_node.next 
        return pre_list == post_list[::-1]
        
328. 奇偶链表
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def oddEvenList(self, head: ListNode) -> ListNode:
        if not head or not head.next:
            return head 
        
        
        dummy = ListNode(0)
        odd = dummy
        mid = ListNode(0)
        event = mid

        curr = head 
        index = 0
        while curr:
            index+=1
            if index%2==1:
                odd.next = curr
                odd = odd.next 
            else: 
                event.next = curr
                event = event.next 
            curr = curr.next 
        if event:
            event.next = None 
        odd.next = mid.next
        return dummy.next

odd = dummy
mid = ListNode(0)
event = mid

    curr = head 
    index = 0
    while curr:
        index+=1
        if index%2==1:
            odd.next = curr
            odd = odd.next 
        else: 
            event.next = curr
            event = event.next 
        curr = curr.next 
    if event:
        event.next = None 
    odd.next = mid.next
    return dummy.next

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值