数据结构与算法--链表

链表

单链表:链表是指通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域、一个是指针域(存放指向下一个节点指针),最后一个节点的指针域指向null(空指针)。
链表的入口节点称为链表的头节点,即head。
双链表:每一个节点有两个指针域,一个指向下一个节点,另一个指向上一个节点。
双链表既可以向前查询也可以向后查询。
循环列表:链表首尾相连。
链表的存储方式: 链表在内存中不是连续分布的,链表通过指针域的指针链接在内存中的各个节点。即链表散乱分布在内存中的某地址上。
链表定义:

class ListNodedef __init__(self, val):
		self.val = val
		self.next = None

移除链表元素

删除链表中等于给定值 val 的所有节点。

# 输入:head = [1,2,6,3,4,5,6], val = 6
# 输出:[1,2,3,4,5]

def solution(head, val):
	pre_head = ListNode(-1)
    pre_head.next = head
    pre = pre_head
    while pre:
        if pre.next and pre.next.val == val:
            pre.next = pre.next.next
        else:
            pre = pre.next
    return pre_head.next	

反转链表

反转一个单链表。
示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL

def solution(head):
	pre = None
	cur = head
	while cur:
		tmp = cur.next
		cur.next = pre
		pre = cur
		cur = tmp
		
	return pre

两两交换链表中的节点

给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
输入: head = [1,2,3,4]
输出:[2,1,4,3]

def solution(head):
	pre = ListNode(-1)
	pre.next = head
	res = pre
	while pre.next and pre.next.next:
		cur = pre.next
		tmp = pre.next.next
		
		cur.next = tmp.next
		pre.next = tmp
		tmp.next = cur
		
		pre = pre.next.next
	return res.next

删除链表的倒数第N个节点

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
进阶:你能尝试使用一趟扫描实现吗?
输入:head = [1,2,3,4,5], n = 2 输出:[1,2,3,5]

def solution(head, n):
	pre = ListNode(0)
	pre.next = head
	slow, fast = pre, pre
	for i in range(n):
		fast = fast.next
	while fast:
		fast = fast.next
		slow = slow.next
	slow.next = slow.next.next
	return pre.next

链表相交

给定两个(单向)链表,判定它们是否相交并返回交点。请注意相交的定义基于节点的引用,而不是基于节点的值。换句话说,如果一个链表的第k个节点与另一个链表的第j个节点是同一节点(引用完全相同),则这两个链表相交。
输入:listA = [4,1,8,4,5], listB = [5,0,1,8,4,5]
输出:Reference of the node with value = 8

def solution(heada, headb):
	cur_a, cur_b = heada, headb
	while cur_a != cur_b:
		cur_a = cur_a.next if cur_a else headb
		cur_b = cur_b.next if cur_b else heada
	return cur_a

环形链表II

题意: 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

为了表示给定链表中的环,使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

def solution(head):
	slow, fast = head, head
	while fast and fast.next:
		slow = slow.next
		fast = fast.next.next
		if slow == fast:
			p = head
			q = slow
			while p != q:
				p = p.next
				q = q.next
			return p
	return None

设计一个链表

在链表类中实现这些功能:

get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。
addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。

# 单链表
class ListNode:
	def __init__(self,val):
		self.val = val
		self.next = None

class MyLinkedList:
	def __init__(self):
		self._head = ListNode(0)
		self._count = 0
	def get(self, index):
		if 0 <= index < self._count:
			node = self._head
			for _ in range(index+1):
				node = node.next
			return node
		else:
			return -1
	def addAHead(self, val):
		self.addAIndex(0, val)
	def addATail(self, val):
		self.addAIndex(self._count, val)
	def addAIndex(self, index, val):
		if index < 0:
			index = 0
		elif index > self._count:
			return
		self._count += 1
		add_node = ListNode(val)
		pre_node, cur_node = None, self._head
		for _ in range(index + 1):
			pre_node, cur_node = cur_node, cur_node.next
		else:
			pre_node.next, add_node.next = add_node, cur_node
	def delAIndex(self, index):
		if 0 <= index < self.count:
			self._count -= 1
			pre_node, cur_node = None, self.head
		for _ in range(index+1):
			pre_node, cur_node = cur_node, cur_node.next
		else:
			pre_node, cur_node = cur_node.next, None

# 双链表
# 相对于单链表, Node新增了prev属性
class Node:
    
    def __init__(self, val):
        self.val = val
        self.prev = None
        self.next = None


class MyLinkedList:

    def __init__(self):
        self._head, self._tail = Node(0), Node(0)  # 虚拟节点
        self._head.next, self._tail.prev = self._tail, self._head
        self._count = 0  # 添加的节点数

    def _get_node(self, index: int) -> Node:
        # 当index小于_count//2时, 使用_head查找更快, 反之_tail更快
        if index >= self._count // 2:
            # 使用prev往前找
            node = self._tail
            for _ in range(self._count - index):
                node = node.prev
        else:
            # 使用next往后找
            node = self._head   
            for _ in range(index + 1):
                node = node.next
        return node

    def get(self, index: int) -> int:
        """
        Get the value of the index-th node in the linked list. If the index is invalid, return -1.
        """
        if 0 <= index < self._count:
            node = self._get_node(index)
            return node.val
        else:
            return -1

    def addAtHead(self, val: int) -> None:
        """
        Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list.
        """
        self._update(self._head, self._head.next, val)

    def addAtTail(self, val: int) -> None:
        """
        Append a node of value val to the last element of the linked list.
        """
        self._update(self._tail.prev, self._tail, val)

    def addAtIndex(self, index: int, val: int) -> None:
        """
        Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted.
        """
        if index < 0:
            index = 0
        elif index > self._count:
            return
        node = self._get_node(index)
        self._update(node.prev, node, val)

    def _update(self, prev: Node, next: Node, val: int) -> None:
        """
            更新节点
            :param prev: 相对于更新的前一个节点
            :param next: 相对于更新的后一个节点
            :param val:  要添加的节点值
        """
        # 计数累加
        self._count += 1
        node = Node(val)
        prev.next, next.prev = node, node
        node.prev, node.next = prev, next

    def deleteAtIndex(self, index: int) -> None:
        """
        Delete the index-th node in the linked list, if the index is valid.
        """
        if 0 <= index < self._count:
            node = self._get_node(index)
            # 计数-1
            self._count -= 1
            node.prev.next, node.next.prev = node.next, node.prev
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值