链表是以结点的方式存储,每个节点含有data域与next域组成:
class Node:
def __init__(self, value, next):
self.value = value
self.next = next
链表分为带头的链表和不带头的链表。
给你一个链表,将该链表逆序
空间复杂度为O(n)的我就不说了,下面介绍一下空间复杂度为O(1)的方法。
定义3个变量head,next,reverse,head存储当前要操作的节点,next代表下个要操作的节点,reverse代表逆序链表当前节点。
具体过程可以看教程:https://www.bilibili.com/video/BV1Y64y1c7YJ?from=search&seid=10189832355923554107&spm_id_from=333.337.0.0
class Node:
def __init__(self, value):
self.value = value
self.next = None
def reverse_linkedlist(head):
if not head:
return
head_node = head
next_node = head_node
reverse_node = None
while head_node:
next_node = next_node.next
head_node.next = reverse_node
reverse_node = head_node
head_node = next_node
return reverse_node
给定两个有序链表的头指针head1和head2,打印出链表的公共部分。
比如:
1->2->2->3->5->6
1->2->3->4->5->6
公共部分为1、2、3、5、6
解决思路,算法就很直接,考的纯coding问题,两个指针,如果碰到相同的两个指针加一,如果不相等,就把小值的指针加一。
class Node:
def __init__(self, value):
self.value = value
self.next = None
def common_part_for_linkedlist(head1, head2):
common_part = set()
while head1 and head2:
if head1.value == head2.value:
common_part.add(head1.value)
head1 = head1.next
head2 = head2.next
elif head1.value > head2.value:
head2 = head2.next
else:
head1 = head1.next
return common_part
给定一个链表,判断是否为回文链表。
可以使用回文的特性,正向遍历的值与反向遍历的值相同。用栈来保存正向信息,逆序遍历进行弹栈操作,如果栈为空,那么为回文链表。
class Node:
def __init__(self, value):
self.value = value
self.next = None
def huiwen(head):
if not head:
return False
stack = []
tmp = head
while tmp:
stack.append(tmp.value)
tmp = tmp.next
pop_stack(head, stack)
if not stack:
return True
return False
def pop_stack(head, stack):
if not head:
return
pop_stack(head.next, stack)
v = stack.pop()
if head.value != v:
stack.append(v)
如果要求其空间复杂度为O(1),那要怎么办呢?
定义两个指针,一个往前,一个往后,遍历比较,一旦不同,就是为false,具体实现方式如下:
class Node:
def __init__(self, value):
self.value = value
self.next = None
class HuiWen:
def __init__(self, head):
self.head = head
self.pre = head
self.is_ok = True
def compare(self, last):
if not last:
return
self.compare(last.next)
if self.pre.value != last.value:
self.is_ok = False
self.pre = self.pre.next
def huiwen(self):
if not self.head:
return False
self.compare(self.head)
return self.is_ok
测试用例:
class TestCase:
def test_case1(self):
head = Node(1)
head.next = Node(2)
head.next.next = Node(3)
head.next.next.next = Node(2)
head.next.next.next.next = Node(1)
n = HuiWen(head)
print(n.huiwen())
def test_case2(self):
head = Node(1)
head.next = Node(2)
head.next.next = Node(2)
head.next.next.next = Node(1)
n = HuiWen(head)
print(n.huiwen())
def test_case3(self):
head = Node(1)
head.next = Node(3)
head.next.next = Node(2)
head.next.next.next = Node(1)
n = HuiWen(head)
print(n.huiwen())
def run(self):
self.test_case1()
self.test_case2()
self.test_case3()
if __name__ == '__main__':
TestCase().run()
输出:
True
True
False
将单向链表按照某值划分成左边小,中间相等,右边大的形式。
有一个链表,定义一个值pivot,要求将链表分类,变成链表左边小于pivot,中间等于pivot,右边大于pivot的形式。
这个其实很简单,定义3个头节点,分别代表小于pivot,等于pivot,大于pivot的链表,分类后将其串起来,要注意链表为空的情况。
class Node:
def __init__(self, value):
self.value = value
self.next = None
def solution(head, pivot):
if not head: nn
return
ls_head = Node(0)
eq_head = Node(0)
gt_head = Node(0)
tmp1 = ls_head
tmp2 = eq_head
tmp3 = gt_head
tmp = head
while tmp:
if tmp.value > pivot:
tmp3.next = tmp
tmp = tmp.next
tmp3 = tmp3.next
tmp3.next = None
elif tmp.value < pivot:
tmp1.next = tmp
tmp = tmp.next
tmp1 = tmp1.next
tmp1.next = None
else:
tmp2.next = tmp
tmp = tmp.next
tmp2 = tmp2.next
tmp2.next = None
new_head = Node(0)
new_tmp = new_head
if ls_head.next:
new_tmp.next = ls_head.next
while new_tmp.next:
new_tmp = new_tmp.next
if eq_head.next:
new_tmp.next = eq_head.next
while new_tmp.next:
new_tmp = new_tmp.next
if gt_head.next:
new_tmp.next = gt_head.next
return new_head.next
题目描述:给定一个链表头部head,判断链表是否有环,并返回入环的节点?
最简单的思路就是把问题转化成给定一个链表,判断该链表中是否存在重复节点,使用set数据结构进行保存。
class Node:
def __init__(self, value):
self.value = value
self.next = None
def __str__(self):
return str(self.__dict__)
def is_circle(head):
tmp_set = set()
tmp_node = head
cnt = 0
while tmp_node is not None:
tmp_set.add(tmp_node)
cnt += 1
if cnt > len(tmp_set):
return tmp_node
tmp_node = tmp_node.next
return None
题目描述:给定两个无环单链表,head1和head2,如何判断其是否相交?
首先先明确单链表相交的情况,有且仅有一种情况,下面是一个例子:
1–2--3–
--5–6--7
2–3--4–
那么明确了这个就有解决思路了
如果是空间复杂度为O(N)的解决方法,就是使用set对node进行存储,这边不再多说,
对于空间复杂度为O(1)的解决方法,首先获取两个链表的长度n1,n2,让长的链表先走abs(n2-n1)步,然后两个链表同时开始走,假如两个指针指向的node相同就说明有相交。
class Node:
def __init__(self, value):
self.value = value
self.next = None
def is_intersect(head1, head2):
n1 = 0
n2 = 0
tmp1 = head1
tmp2 = head2
while tmp1:
tmp1 = tmp1.next
n1 += 1
while tmp2:
tmp2 = tmp2.next
n2 += 1
tmp1 = head1
tmp2 = head2
if n1 > n2:
point = n1 - n2
cnt = 0
while cnt < point:
tmp1 = tmp1.next
cnt += 1
else:
point = n2 - n1
cnt = 0
while cnt < point:
tmp2 = tmp2.next
cnt += 1
while tmp1 and tmp2:
if tmp1 == tmp2:
return True
tmp1 = tmp1.next
tmp2 = tmp2.next
return False
首先分为有环与无环
对于无环链表的相交问题就是上一题
对于有环链表分为以下两种情况
判断这两个区别的地方就是入环节点是否相同。
设编号为1,2,3,4,…,n个人围坐一圈,约定编号为a人从1开始报数,数到m的那个人出列,他的下一位又开始从1报数,数到m的那个人又出列,依次类推,输出最后出局的人的编号。
给定两个int n和m,代表游戏的人数。请返回最后一个出局的人的编号。保证n和m小于等于1000。
这个问题思路就是使用环形链表进行数据结构的存储,算法方面没什么难度。
class Node:
def __init__(self, value):
self.value = value
self.next = None
def build_linkedlist(n):
if n <= 0:
return None
head = Node(0)
tmp_node = head
for i in range(n):
tmp_node.next = Node(i + 1)
tmp_node = tmp_node.next
tmp_node.next = head.next
return head.next
def joseph(n, m):
linkedlist = build_linkedlist(n)
tmp = linkedlist
left_node_num = n
while left_node_num > 1:
k = 1
while k < m - 1:
tmp = tmp.next
k += 1
tmp.next = tmp.next.next
tmp = tmp.next
left_node_num -= 1
return tmp.value