链表-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
    评论
### 回答1: 假设有两个已经按照升序排列的链表,要将它们合并成一个新的有序链表。可以按照以下步骤实现: 1. 定义一个新链表,并用一个指针指向它的头部。 2. 比较两个链表的头部节点,将较小的节点加入新链表,并将指针指向这个节点。 3. 重复步骤2,直到其中一个链表为空。 4. 将另一个非空的链表加入新链表的末尾。 实现代码可以类似下面这样: ```python class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next def mergeTwoLists(l1: ListNode, l2: ListNode) -> ListNode: dummy = ListNode(0) curr = dummy while l1 and l2: if l1.val < l2.val: curr.next = l1 l1 = l1.next else: curr.next = l2 l2 = l2.next curr = curr.next if l1: curr.next = l1 else: curr.next = l2 return dummy.next ``` 其中,dummy节点是用于返回新链表的头部的。curr指针用于在遍历链表的过程中连接新节点。最后返回dummy节点的下一个节点就是新链表的头部。 ### 回答2: 对于两个有序链表序列的合并问题,可以采用递归算法实现。具体过程如下: 1. 若其中一个链表为空,则直接返回另一个链表作为结果。 2. 比较两个链表的头节点的数据大小,取较小的节点作为新的头节点。 3. 将剩余的链表继续调用递归函数,将返回的结果接在新的头节点后面。 4. 返回新的合并后的链表。 示例代码如下: ```python class Node: def __init__(self, data): self.data = data self.next = None def merge_lists(head1, head2): if not head1: return head2 if not head2: return head1 if head1.data < head2.data: new_head = head1 new_head.next = merge_lists(head1.next, head2) else: new_head = head2 new_head.next = merge_lists(head1, head2.next) return new_head ``` 时间复杂度为 $O(m+n)$,其中 $m$ 和 $n$ 分别为两个链表的长度。由于采用了递归算法,会使用额外的栈空间,空间复杂度为 $O(m+n)$。需要注意的是,在实际代码中需要注意边界条件的判断和对链表的操作,避免出现空指针引用等错误。 ### 回答3: 线性结构是数据结构中最基本的结构之一,常见的线性结构有数组、链表、栈、队列等。有序链表是将元素按照一定规则有序排列的链表。合并两个有序链表,是指将两个有序链表中的元素按照一定规则合并成一个新的有序链表。这个问题可以分为如下的几个步骤进行解决: 1.创建一个新的头结点来作为新链表的头结点。 2.扫描两个链表中的元素,找到其中较小的元素,并将其插入到新链表的尾部。 3.重复步骤2,直到其中一个链表为空。 4.将另一个链表中剩余的元素插入到新链表的尾部即可。 下面是具体的代码实现: ``` /*定义链表结构体*/ typedef struct Node{ int data; /*数据域*/ struct Node* next; /*指针域*/ }LinkList; /*合并两个有序链表*/ LinkList* merge(LinkList* l1, LinkList* l2){ LinkList* head = (LinkList *)malloc(sizeof(LinkList)); /*新链表的头结点*/ LinkList* p = head; /*新链表的尾指针*/ LinkList* p1 = l1->next; /*l1的第一个结点*/ LinkList* p2 = l2->next; /*l2的第一个结点*/ while(p1 != NULL && p2 != NULL) { if(p1->data < p2->data) /*l1中的元素小*/ { p->next = p1; /*将l1中的结点插入到新链表的尾部*/ p1 = p1->next; /*指针后移*/ } else /*l2中的元素小*/ { p->next = p2; /*将l2中的结点插入到新链表的尾部*/ p2 = p2->next; /*指针后移*/ } p = p->next; /*新链表的尾指针后移*/ } /*将剩余元素插入到新链表的尾部*/ if(p1 != NULL) { p->next = p1; } else { p->next = p2; } return head; /*返回新链表的头结点*/ } ``` 总体来说,合并两个有序链表需要依次比较两个链表中的元素,并将小的元素插入到新的有序链表中。这个过程需要用到新建链表的头结点来保存新链表的头指针,以及尾指针来记录新链表的结尾。最后,如果其中一个链表还有剩余元素,也要将其插入到新链表中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值