1.功能实现
链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而顺序表相应的时间复杂度分别是O(logn)和O(1)。
特点:使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。
基本操作:包括创建链表(初始化)、获取长度、插入、查找、删除、遍历,以及略复杂的链表逆序和结点交换。下面将这些操作一一实现并作出解释。
class ListNode(object):
def __init__(self,data,p = None):
self.data = data
self.next = p
class Linklist(object):
def __init__(self):
self.head = None
def set(self): # 初始建立
print('input:')
data = input()
if data != "":
self.head = ListNode(int(data))
p = self.head
else:
print('over!')
return
while 1:
data = input()
if data != "":
p.next = ListNode(int(data))
p = p.next
else:
print('over!')
break
@property
def show(self): # 遍历链表
print('链表元素如下:')
p = self.head
if p == None:
print('Empty!')
return
while p:
print(p.data,end=',')
p = p.next
print('over!')
return
@property
def isempty(self): # 判断是否空
p = self.head
if p == None:
return True
else:
return False
@property
def length(self): # 获取长度
p = self.head
l = 0
while p:
l += 1
p = p.next
return l
def insert(self,data,pos): # 数据插入
if self.isempty and pos != 1:
raise Exception('wrong position!')
p = self.head
if pos == 1:
self.head = ListNode(data)
self.head.next = p
n = 2
while n < pos and p.next != None:
p = p.next
n += 1
if n == pos:
tmp = p.next
p.next = ListNode(data)
p = p.next
p.next = tmp
elif n < pos:
raise Exception('wrong position!')
def delete(self,pos): # 删除操作
p = self.head
# 假设位置信息有效
if pos == 1:
return self.head.next
for i in range(pos - 2):
p = p.next
p.next = p.next.next
2.倒数第k结点及链表合并
1)题目如下:输入一个链表,输出该链表中倒数第k个结点。
class ListNode(object):
def __init__(self, x):
self.val=x
self.next=None
class Solution(object):
def __init__(self, head, k):
n=0
p=head
while p!=None:
n+=1
p=p.next
if n<k:
return None
p=head
m=1
while m<n-k+1:
m+=1
p=p.next
return p
2)题目如下:输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
class ListNode:
def __init__(self, x):
self.x=x
self.next=None
class Solution:
def merge(self, pHead1, pHead2):
if pHead1 is None:
return pHead2
if pHead2 is None:
return pHead1
if pHead1.val<=pHead2.val:
pHead1.next=merge(pHead1.nextm pHead2)
else:
pHead2.next=merge(pHead1, pHead2.next)
3.链表右移/链表分割/链表逆序
1). 61. Rotate List (将链表右移K个位置)
Given a list, rotate the list to the right by k places, where k is non-negative.
Example:
Given 1->2->3->4->5->NULL and k = 2,
return 4->5->1->2->3->NULL.
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def rotateRight(self, head, k):
"""
:type head: ListNode
:type k: int
:rtype: ListNode
"""
if head == None:
return None
length = 1
p = head
while p.next:
p = p.next
length += 1
if k == length:
return head
elif k > length:
k = k%length
cn = 1
q = head
while cn < (length-k):
q = q.next
cn += 1
p.next = head
newhead = q.next
q.next = None
return newhead
2. 86. Partition List(链表分割)
Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x.You should preserve the original relative order of the nodes in each of the two partitions.
For example,
Given 1->4->3->2->5->2 and x = 3,
return 1->2->2->4->3->5.
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def partition(self, head, x):
"""
:type head: ListNode
:type x: int
:rtype: ListNode
"""
if head == None:
return head
p1 = ListNode(-1)
p2 = ListNode(-1)
h1, h2 = p1, p2
while head:
if head.val <x:
p1.next = head
p1 = p1.next
else:
p2.next = head
p2 = p2.next
head = head.next
p2.next = None
p1.next = h2.next
return h1.next
3). 92. Reverse Linked List II(链表逆序)
class Solution:
def reverseBetween(self, head, m, n):
"""
:type head: ListNode
:type m: int
:type n: int
:rtype: ListNode
"""
if head == None:
return head
elif m == n:
return head
new = ListNode(-1)
new.next = head
head = new
p = head
pre = head
for i in range(m):
pre = p
p = p.next
q = p
for i in range(n-m):
q = q.next
# reverse
pre_p = q.next
cur = p
for i in range(n-m+1):
h = cur
tmp = cur.next
cur.next = pre_p
pre_p = cur
cur = tmp
pre.next = q
return head.next
4.移除重复项及带随机指针的链表复制
1)82. Remove Duplicates from Sorted List II (从有序列表中移除重复项)
Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.
For example,
Given 1->2->3->3->4->4->5, return 1->2->5.
Given 1->1->1->2->3, return 2->3.
1)82. Remove Duplicates from Sorted List II (从有序列表中移除重复项)
Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.
For example,
Given 1->2->3->3->4->4->5, return 1->2->5.
Given 1->1->1->2->3, return 2->3.
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def deleteDuplicates(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if head == None or head.next == None:
return head
fhead = ListNode(0)
fhead.next = head
pre = fhead
cur = head
while cur:
while cur.next and cur.val==cur.next.val:
cur = cur.next
if pre.next == cur: # 如果只此一个值,不删除,pre后移
pre = cur
else:
pre.next = cur.next # 如果不只一个,删除这些结点,pre暂不后移
cur = cur.next
return fhead.next
2)138. Copy List with Random Pointer(复制含有随机指针的链表)
# Definition for singly-linked list with a random pointer.
# class RandomListNode(object):
# def __init__(self, x):
# self.label = x
# self.next = None
# self.random = None
class Solution(object):
def copyRandomList(self, head):
"""
:type head: RandomListNode
:rtype: RandomListNode
"""
if head == None:
return None
p = head
while p:
tmp = p.next
p.next = RandomListNode(p.label)
p.next.next = tmp
p = tmp
p = head
while p:
if p.random:
p.next.random = p.random.next
p = p.next.next
newhead = RandomListNode(0)
p = head
q = newhead
while p:
tmp = p.next.next
q.next = p.next
q = q.next
p.next = tmp
p = tmp
return newhead.next
5.带环链表及交叉链表(双指针法)
1)160.Intersection of Two Linked Lists 两链表交叉
Write a program to find the node at which the intersection of two singly linked lists begins.For example, the following two linked lists:
A: a1 → a2
↘
c1 → c2 → c3
↗
B: b1 → b2 → b3
begin to intersect at node c1.
Notes:
If the two linked lists have no intersection at all, return null.
The linked lists must retain their original structure after the function returns.
You may assume there are no cycles anywhere in the entire linked structure.
Your code should preferably run in O(n) time and use only O(1) memory.
class Solution(object):
def getIntersectionNode(self, headA, headB):
"""
:type head1, head1: ListNode
:rtype: ListNode
"""
p1, p2 = headA, headB
while p1 is not p2:
p1 = headB if not p1 else p1.next
p2 = headA if not p2 else p2.next
return p1
2)142. Linked List Cycle II 带环的链表
Given a linked list, return the node where the cycle begins. If there is no cycle, return null.
Note: Do not modify the linked list.
Follow up:Can you solve it without using extra space?
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if head == None:
return None
pslow = head
pfast = head
k = 0
while pfast.next and pfast.next.next:
pslow = pslow.next
pfast = pfast.next.next
k += 1
if pslow == pfast:
break
if pfast.next==None or pfast.next.next==None:
return None
# 确定有环,开始寻找
p1 = head
p2 = pslow
while p1!=p2:
p1 = p1.next
p2 = p2.next
return p1