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個節點是一樣的。