1、删除链表的倒数第K个节点
题目描述:
给定一个链表: 1->2->3->4->5, 和 k = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
解题思路:
- 使用两个指针p,q,刚开始两个指针指向链表的头部
- 让q指针向后移动k个节点,p和q节点之间的举例保持为k
- p和q同时向后移动,直到q.next = None,此时p节点为删除节点的前一个节点
- 删除倒数第k个节点,p.next = p.next.next
实现代码如下:
from SingleLink import SingleLink
def delKthToTail(link, k):
"""
删除链表的倒数第K个元素
1. 判断用户输入的合法性?link k
2. 如果输入数据合法
1). p,q两个指针指向头部
2). 让q指针向后移动k个位置,两者保持距离为k
3). p,q同时向后移动,直到q.next为None
4). 删除倒数第K个元素,p.next = p.next.next
:param link:
:param k:
:return:
"""
#1. 判断用户输入的合法性?link k
if not link:
return
if not link._head:
return
if k <= 0:
return
# 2.1)让p指针和q指针指向头部
p = link._head
q = link._head
# 2). 让q指针向后移动k个位置,两者保持距离为k
for i in range(k):
q = q.next
# 3). p,q同时向后移动,直到q.next为None
while q.next != None:
p = p.next
q = q.next
# 4). 删除倒数第K个元素,p.next = p.next.next
p.next = p.next.next
return link
if __name__ == '__main__':
link = SingleLink()
for i in range(5):
link.append(i + 1)
link1 = delKthToTail(link, 3)
link1.travel()
SingleLink代码如下:
class Node(object):
"""单链表节点的封装"""
def __init__(self, element):
self.element = element
self.next = None
class SingleLink(object):
"""单链表的封装"""
def __init__(self):
# 默认为空
self._head = None
def is_empty(self):
"""是否为空"""
return self._head == None
def __len__(self):
"""
求链表长度
1. 判断是否为空,为空直接返回0
2. 不为空时依次遍历,长度加1之后将下一个节点赋值给当前
"""
if self.is_empty():
return 0
else:
cur = self._head
length = 0
while cur != None:
length += 1
cur = cur.next
return length
def travel(self):
"""遍历链表"""
if self.is_empty():
print('空链表')
else:
cur = self._head
while cur.next != None:
print(cur.element, end=',')
cur = cur.next
print(cur.element)
def append(self, item):
"""
尾部添加元素
1. 先判断链表是否为空,若为空,将_head指向新节点
2. 若不为空,找到尾部,将尾节点next指向新节点
:param item:
:return:
"""
node = Node(item)
if self.is_empty():
self._head = node
else:
cur = self._head
while cur.next != None:
cur = cur.next
if cur.next == None:
cur.next = node
def add(self, item):
"""
头部添加元素:
1. 创建一个保存item值的节点
2. 将新节点的next指向头结点,即_head指向的位置
3. 将链表的头_head指向新节点
:param item:
:return:
"""
node = Node(item)
node.next = self._head
self._head = node
def insert(self, index, item):
"""
指定位置添加元素
1. 指定位置为头部之前,则头部添加元素
2. 指定位置为尾部之后,则尾部添加元素
3. 中间位置:需要找出指定位置的前一个元素,得到其尾部,插入的节点的尾部指向前面得到的尾部,
前一个元素新的尾部指向插入的头部
:param index:
:param item:
:return:
"""
if index <= 0:
self.add(item)
elif index >= len(self):
self.append(item)
else:
node = Node(item)
count = 0 # 当前节点的位置
cur = self._head
# 寻找插入节点的前一个节点
while count < index - 1:
count += 1
cur = cur.next
# 插入节点的前一个节点的尾部成为了插入节点的尾部指向
# 然后将插入节点的前一个节点的尾部指向更新为新插入节点的头部
node.next = cur.next
cur.next = node
def remove(self, item):
"""
删除指定元素的节点
1. 删除头部节点
2. 删除其他位置的节点
:param item:
:return:
"""
"""
既然要删除当前节点,首先想的就是遍历链表找到对应节点并且删除,
这里直接省去了遍历的操作,直接给出了对应的节点。
既然想删除当前节点那么将给定的节点的val和next全部转换成当前节点的下一个节点所对应的值,
那么当前节点在本链表中就相当于替换成了下一个节点。
"""
cur = self._head
pre = None
while cur != None:
if cur.element == item:
if not pre:
self._head = cur.next
else:
pre.next = cur.next
break
else:
pre = cur
cur = cur.next
def search(self, item):
"""
判断查找的元素在节点中是否存在,返回Bool类型
:param item:
:return:
"""
cur = self._head
while cur.next != None:
if cur.element == item:
return True
cur = cur.next
if cur.element == item:
return True
return False
2、旋转链表
题目描述:给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。
示例 1:
输入: 1->2->3->4->5, k = 2
输出: 4->5->1->2->3
示例 2:
输入: 0->1->2, k = 4
输出: 2->0->1
解题思路:
- 访问到链表最后,尾部节点的next指向头部节点,将链表转换为单向寻哈un链表,最后在需要断开的位置再断开变成单向链表
- 对k进行处理,k = k%链表长度,因为存在k > 链表长度和k < 小于链表长度两种情况
- 寻找断开位置的前一个节点,length - k - 1,更新头部节点–>link._head = prev.next
- 断开链表,尾部.next=None
from SingleLink import SingleLink
def rorateRight(link, k):
# 1). 判断合法性?link是否存在,是否为空
if not link:
return
if not link._head:
return
# 2). 如果合法
# 1. 访问链表到最后,将链表转换为单向循环链表,尾部节点的next指向头部
length = 1
cur = link._head
while cur.next != None:
length += 1
cur = cur.next
# 首尾相连
cur.next = link._head
# 2. 寻找断开位置的前一个结点,len-k%len-1,更新链表头结点
k = k % length
prev = link._head
for i in range(length - k - 1):
prev = prev.next
# 更新链表头结点
link._head = prev.next
# 3.断开链表循环的部分,尾部指向为None
prev.next = None
return link
if __name__ == '__main__':
link = SingleLink()
for i in range(5):
link.append(i)
link.travel()
link1 = rorateRight(link, 2)
link1.travel()
SingleLink代码和上面删除链表的倒数第K个节点是一样的。