Leetcode刷题02-链表操作

链表

链表基础知识

单链表

1.逻辑结构:数据元素之间的逻辑关系

集合、线性结构(一对一)、树形结构(一对多)、图结构(多对多)

2.存储结构:顺序存储、链式存储、索引存储、散列存储

  • 顺序存储(顺序表):逻辑上相邻的元素物理位置也相邻
  • 链式存储(单链表):逻辑上相邻的元素物理位置不一定相邻。

3.数据操作:

  • 单链表定义
  • 单链表在指定位置插入元素
  • 删除指定位置元素
  • 头插法创建单链表
  • 尾插法创建单链表

4.单链表的定义

  • 带头结点的单链表:head没有实际意义。

  • 不带头结点的单链表:第一个结点就是头结点。

在这里插入图片描述

4.单链表的插入元素

  • 带头结点的单链表插入
def Insert(head, i, elem):
	assert i >= 0
    cur = head
    while i != 0:
        i -= 1
        cur = cur.next
        if not cur:
            return False
    temp = cur.next
    cur.next = elem
    elem.next = temp
    return True
  • 不带头结点的单链表
def Insert(i, elem):
    global head
    assert i >= 0
    if i == 0:
        elem.next = head
        head = elem
    cur = head
    while i > 1:
        i -= 1
        cur = cur.next
        if not cur:
            return False
    temp = cur.next
    cur.next = elem
    elem.next = temp
    return True

5.删除指定位置元素

  • 带头结点
def ListDelete(head, i):
    assert i >= 0
    cur = head
    while i != 0:
        i -= 1
        cur = cur.next
        if not cur.next:
            return False
    cur.next = cur.next.next
    return True

6.创建单链表

  • 尾插法
# 带头结点
def BuildLink_Tail(l):
	head = ListNode()
    cur = head
    for elem in l:
        cur.next = ListNode(elem)
        cur = cur.next
    return head

# 处理
head = BuildLink_Tail([1, 2, 3, 4])
while head.next:
    head = head.next
    print(head.val)

# 不带头结点
def BuildLink_Tail(l):
    if not l:
        return None
   	head = ListNode(l[0])
    cur = head
    for elem in l[1:]:
        cur.next = ListNode(elem)
        cur = cur.next
    return head

# 处理
head = BuildLink_Tail([1, 2, 3, 4])
while head:
    print(head.val)
    head = head.next
  • 头插法
# 带头结点
def BuildLink_Head(l):
	head = ListNode()
    for elem in l:
        temp = head.next
        head.next = ListNode(elem, temp)
    return head


# 不带头结点
def BuildLink_Head(l):
    head = None
    for elem in l:
        head = ListNode(elem, head)
    return head

双链表

class DLinkNode:
    def __init__(self, val=0, next=None, prior):
        self.val = val
        self.next = next
        self.prior = prior

用来解决单链表无法逆向索引的问题

循环链表

包括循环单链表和循环双链表

在这里插入图片描述

题目解析

移除链表元素

1.题目描述

题目链接

在这里插入图片描述

2.解题思路及代码

直接使用带头结点的单链表进行操作,可以节省很多边界条件。

	public ListNode removeElements(ListNode head, int val) {
        ListNode head1 = new ListNode();
        head1.next = head;
        
        ListNode prev = head1;
        
        while(prev.next != null) {
            if (prev.next.val == val)   prev.next = prev.next.next;
            else    prev = prev.next;
        }
        return head1.next;
    }
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeElements(self, head: ListNode, val: int) -> ListNode:
        head1 = ListNode(next=head)
        cur = head1
        while cur.next:
            if cur.next.val == val:
                cur.next = cur.next.next
            else:
                cur = cur.next
        return head1.next

旋转链表

1.题目描述

题目链接

在这里插入图片描述

2.解题思路及代码

首先是k的操作,如果k大于链表的长度,那么只需要移动k%length次即可,然后需要将首尾相连,然后确定head和末尾的值即可。

	public ListNode rotateRight(ListNode head, int k) {
        int len = 0;
        if (head == null)   return null;
        ListNode cur = head;
        while(cur.next != null) {
            cur = cur.next;
            len ++ ;
        }
        k = k % (len + 1);
        cur.next = head;
        cur = head;
        for (int i = 0; i < len - k; i ++ ) {
            cur = cur.next;
        }
        head = cur.next;
        cur.next = null;
        return head;
    }
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        if not head:
            return None
        len = 0
        cur = head
        while cur.next:
            cur = cur.next
            len += 1
        cur.next = head
        k = k % (len + 1)
        cur = head
        for i in range(len - k):
            cur = cur.next
        head = cur.next
        cur.next = None
        return head

合并两个有序链表

1.题目描述

题目链接

在这里插入图片描述

2.题目思路及代码

使用两个指针指向两个链表,然后把链表中小的元素放到新的链表中,为了避免边界问题,这里使用了带头结点的链表,因此最后需要返回head.next

	public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode head = new ListNode();
        ListNode cur1 = list1;
        ListNode cur2 = list2;
        ListNode cur = head;
        while(cur1 != null && cur2 != null) {
            if (cur1.val > cur2.val) {
                cur.next = cur2;
                cur2 = cur2.next;
            } else {
                cur.next = cur1;
                cur1 = cur1.next;
            }
            cur = cur.next;
        }
        
        cur.next = cur1 == null ? cur2 : cur1;
        
        return head.next;
    }
# 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, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
        cur1 = list1
        cur2 = list2
        head = ListNode()
        cur = head
        
        while cur1 and cur2:
            if cur1.val > cur2.val:
                cur.next = cur2
                cur2 = cur2.next
            else:
                cur.next = cur1
                cur1 = cur1.next
            cur = cur.next
        
        cur.next = cur1 if cur1 is not None else cur2
        
        return head.next

相交链表

1.题目描述

题目链接

在这里插入图片描述

2.解题思路及代码

使用双指针分别指向headA和headB,然后分别移动到下一节点,如果指向headA的为空,则指向headB,同理如果指向headB的指针为空,则指向headA,直到两个指针值相等,返回最后的值即可。

具体证明详见链接中的题解。

	public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if (headA == null || headB == null) return null;
        
        ListNode curA = headA, curB = headB;
        
        while (curA != curB) {
            if (curA == null) {
                curA = headB;
            } else {
                curA = curA.next;
            }
            if (curB == null) {
                curB = headA;
            } else {
                curB = curB.next;
            }
        }
        return curA;
    }
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        curA = headA
        curB = headB
        while curA != curB:
            curA = headB if curA is None else curA.next
            curB = headA if curB is None else curB.next
        return curA

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

1.题目描述

题目链接

在这里插入图片描述

2.解题思路及代码

为了保证能够删除重复的所有元素,因此如果链表的下一个节点和下下个节点值相同,就要让链表的下一个节点指向第三个节点(如果第三个节点的值仍然和链表下一节点值相等,结点指向继续往下走,因此这里需要保存下一个节点的值),这里依然使用带有头结点的链表,从而避免边界问题。

	public ListNode deleteDuplicates(ListNode head) {
        if (head == null)   return null;
        ListNode head1 = new ListNode();
        head1.next = head;
        ListNode cur = head1;
        while (cur.next != null && cur.next.next != null) {
            
            if (cur.next.val == cur.next.next.val) {
                int x = cur.next.val;
                while (cur.next != null && cur.next.val == x)
                    cur.next = cur.next.next;
            } else {
                cur = cur.next;
            }
        }
        return head1.next;
    }
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def deleteDuplicates(self, head: ListNode) -> ListNode:
        if not head:
            return None
        head1 = ListNode(next=head)
        cur = head1
        while cur.next and cur.next.next:
            if cur.next.val == cur.next.next.val:
                x = cur.next.val
                while cur.next and cur.next.val == x:
                    cur.next = cur.next.next
            else:
                cur = cur.next
        return head1.next
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值