https://github.com/datawhalechina/Programming
https://github.com/TheAlgorithms/Python
c++ https://github.com/wangzheng0822/algo/tree/master/c-cpp
python https://github.com/wangzheng0822/algo/tree/master/python
数组
实现一个支持动态扩容的数组
参考:https://blog.csdn.net/u013109501/article/details/88020739
#通过python实现动态数组
"""
数组特点:
占用一段连续的内存空间,支持随机(索引)访问,且时间复杂度为O(1)
添加元素时间复杂度:O(n)
删除元素时间复杂度:O(n)
"""
class Arr:
def __init__(self, capacity=10):
"""
构造函数
:param capacity: 数组最大容量,不指定的话默认为10
"""
self._capacity = capacity
self._size = 0 # 数组有效元素的数目,初始化为0
self._data = [None] * self._capacity # 由于python的list是动态扩展的,而我们要实现底层具有固定容量、占用一段连续的内存空间的数组,所以用None来作为无效元素的标识
def __getitem__(self, item):
"""让Arr类支持索引操作"""
return self._data[item]
def getSize(self):
"""返回数组有效元素的个数"""
return self._size
def getCapacity(self):
"""返回当前数组的容量"""
return self._capacity
def isEmpty(self):
"""判断当前数组是否为空"""
return self._size == 0
def add(self, index, elem):
"""
向数组中添加一个元素,注意数组占用的是一段连续的内存空间,所以在添加元素后,数组还是要保证这个特点的,因此需要将后面的元素都向后挪一个位置,而且要注意要先从
尾部开始挪,防止元素之间的覆盖
时间复杂度:O(n)
:param index: 添加的元素所在的索引
:param elem: 所要添加的元素
"""
if index < 0 or index > self._size: # 插入的位置无效
raise Exception('Add Filed. Require 0 <= index <= self._size')
if self._size == self._capacity: # 满了
self._resize(self._capacity * 2) # 默认扩容当前容量的二倍。容量翻倍要比容量加上一个固定值要好,这样做均摊复杂度为O(1)。具体请百度
for i in range(self._size - 1, index - 1, -1): # 从尾部开始挪动元素,在index处腾出一个空间
# 一定要注意在步长为负数的情况下,区间是左开右闭区间,即(index, self._size - 1],所以是index-1,与正常的左闭右开区间是相反的!
self._data[i + 1] = self._data[i]
self._data[index] = elem # 将该位置赋值为elem
self._size += 1 # 数组有效元素数加1
def addLast(self, elem):
"""
向数组尾部添加元素
时间复杂度:O(1)
:param elem: 所要添加的元素
"""
self.add(self._size, elem) # 直接调用add方法,注意不用再次判定合法性了,因为add函数中已经判断过了
def addFirst(self, elem):
"""
想数组头部添加元素
时间复杂度:O(n)
:param elem: 所要添加的元素
"""
self.add(0, elem) # 同理直接调用add方法
def get(self, index):
"""
获得索引index处的元素
时间复杂度:O(1)
:param index: 数组索引
:return: 数组索引处的值
"""
if index < 0 or index >= self._size: # 判断index的合法性
raise Exception('Get failed. Index is illegal.')
return self._data[index]
def getFirst(self):
"""
获得数组首位置元素的值
:return: 首位置元素的值
"""
return self.get(0) # 直接调用get函数,安全可靠
def getLast(self):
"""
获得数组末尾元素的值
:return: 末尾元素的值
"""
return self.get(self._size - 1) # 直接调用get函数,安全可靠
def set(self, index, elem):
"""
将索引为index的元素的值设为elem
时间复杂度:O(1)
:param index: 索引
:param elem: 新的值
"""
if index < 0 or index >= self._size: # 判断index的合法性
raise Exception('Sat failed. Index is illegal.')
self._data[index] = elem
def contains(self, elem):
"""
查看数组中是否存在元素elem,最好不要传入一个浮点数,你懂得。。
时间复杂度:O(n)
:param elem: 目标元素
:return: bool值,存在为真
"""
for i in range(self._size): # 遍历
if self._data[i] == elem:
return True # 找到了就返回True
return False # 遍历完了还没找到,就返回False
def find(self, elem):
"""
在数组中查找元素,并返回元素所在的索引。(如果数组中存在多个elem,只返回最左边elem的索引)
时间复杂度:O(n)
:param elem: 目标元素
:return: 元素所在的索引,没找到则返回-1(无效值)
"""
for i in range(self._size): # 遍历数组
if self._data[i] == elem:
return i # 找到就返回索引
return -1 # 没找到返回-1
def findAll(self, elem):
"""
找到值为elem全部元素的索引
:param elem: 目标元素
:return: 一个列表,值为全部elem的索引
"""
ret_list = Arr() # 建立一个新的数组用于存储索引值
for i in range(self._size): # 遍历数组
if self._data[i] == elem:
ret_list.addLast(i) # 找到就将索引添加进ret_list
return ret_list
def remove(self, index):
"""
删除索引为index的元素。index后面的元素都要向前移动一个位置
时间复杂度:O(n)
:param index: 目标索引
:return: 位于该索引的元素的值
"""
if index < 0 or index >= self._size: # index合法性检查
raise Exception('Remove failed.Require 0 <= index < self._size')
ret = self._data[index] # 拷贝一下index处的元素,便于返回
for i in range(index + 1, self._size): # index后面的元素都向前挪一个位置
self._data[i - 1] = self._data[i]
self._size -= 1 # 维护self._size
self._data[self._size] = None # 最后一个元素的垃圾回收
if self._size and self._capacity // self._size == 4: # 如果当前有效元素为总容量的四分之一且还存在有效元素,则将容量缩减为原来的一半
self._resize(self._capacity // 2)
return ret
def removeFirst(self):
"""
删除数组首位置的元素
时间复杂度:O(n)
:return: 数组首位置的元素
"""
return self.remove(0) # 调用remove函数
def removeLast(self):
"""
删除数组末尾的元素
时间复杂度:O(1)
:return: 数组末尾的元素
"""
return self.remove(self._size - 1) # 调用remove函数
def removeElement(self, elem):
"""
删除数组中为elem的元素,如果数组中不存在elem,那么什么都不做。如果存在多个相同的elem,只删除最左边的那个
时间复杂度:O(n)
:param elem: 要删除的目标元素
"""
index = self.find(elem) # 尝试找到目标元素(最左边的)的索引
if index != -1: # elem在数组中就删除,否则什么都不做
self.remove(index) # 调用remove函数
def removeAllElement(self, elem):
"""
删除数组内所有值为elem的元素,可以用递归来写,这里用的迭代的方法。elem不存在就什么都不做
:param elem: 要删除的目标元素
"""
while True:
index = self.find(elem) # 循环来找elem,如果还存在就继续删除
if index != -1: # 若存在
self.remove(index)
else:
break
def get_Max_index(self):
"""
获取数组中的最大元素的索引,返回最大元素的索引值,如果有多个最大值,默认返回最左边那个的索引
时间复杂度:O(n)
:return: 最大元素的索引
"""
if self.isEmpty():
raise Exception('Error, array is Empty!')
max_elem_index = 0 # 记录最大值的索引,初始化为0
for i in range(1, self.getSize()): # 从索引1开始遍历,一直到数组尾部
if self._data[i] > self._data[max_elem_index]: # 如果当前索引的值大于最大值索引处元素的值
max_elem_index = i # 更新max_elem_index,这样它还是当前最大值的索引
return max_elem_index # 遍历完后,将数组的最大值的索引返回
def removeMax(self):
"""
删除数组中的最大元素,返回最大元素的值,如果有多个最大值,默认值删除最左边那个
时间复杂度:O(n)
:return: 最大元素
"""
return self.remove(self.get_Max_index()) # 直接调用remove函数删除最大值
def get_Min_index(self):
"""
获取数组中的最小元素的索引,返回最小元素的索引值,如果有多个最小值,默认返回最左边那个的索引
时间复杂度:O(n)
:return: 最小元素的索引
"""
if self.isEmpty():
raise Exception('Error, array is Empty!')
min_elem_index = 0 # 记录最小值的索引,初始化为0
for i in range(1, self.getSize()): # 从索引1开始遍历,一直到数组尾部
if self._data[i] < self._data[min_elem_index]: # 如果当前索引的值小于最小值索引处元素的值
min_elem_index = i # 更新min_elem_index,这样它还是当前最小值的索引
return min_elem_index # 遍历完后,将数组的最小值的索引返回
def removeMin(self):
"""
删除数组中的最小元素,返回最小元素的值,如果有多个最小值,默认值删除最左边那个
时间复杂度:O(2n),可以看成是O(n)的
:return: 最小元素
"""
return self.remove(self.get_Min_index())
def swap(self, index1, index2):
"""
交换分别位于索引index1和索引index2处的元素
:param index1: 索引1
:param index2: 索引2
"""
if index1 < 0 or index2 < 0 or index1 >= self._size or index2 >= self._size: # 合法性检查
raise Exception('Index is illegal')
self._data[index1], self._data[index2] = self._data[index2], self._data[index1] # 交换元素
def printArr(self):
"""对数组元素进行打印"""
for i in range(self._size):
print(self._data[i], end=' ')
print('\nSize: %d-----Capacity: %d' % (self.getSize(), self.getCapacity()))
# private
def _resize(self, new_capacity):
"""
数组容量放缩至new_capacity,私有成员函数
:param new_capacity: 新的容量
"""
new_arr = Arr(new_capacity) # 建立一个新的数组new_arr,容量为new_capacity
for i in range(self._size):
new_arr.addLast(self._data[i]) # 将当前数组的元素按当前顺序全部移动到new_arr中
self._capacity = new_capacity # 数组容量变为new_capacity
self._data = new_arr._data # 将new_arr._data赋值给self._data,从而完成数组的容量放缩操作
实现一个大小固定的有序数组,支持动态增删改操作
参考:https://github.com/wangzheng0822/algo/blob/master/python/05_array/myarray.py
class MyArray:
"""A simple wrapper around List.
You cannot have -1 in the array.
"""
def __init__(self, capacity: int):
self._data = []
self._capacity = capacity
def __getitem__(self, position: int) -> object:
return self._data[position]
def __setitem__(self, index: int, value: object):
self._data[index] = value
def __len__(self) -> int:
return len(self._data)
def __iter__(self):
for item in self._data:
yield item
def find(self, index: int) -> object:
try:
return self._data[index]
except IndexError:
return None
def delete(self, index: int) -> bool:
try:
self._data.pop(index)
return True
except IndexError:
return False
def insert(self, index: int, value: int) -> bool:
if len(self) >= self._capacity:
return False
else:
return self._data.insert(index, value)
def print_all(self):
for item in self:
print(item)
def test_myarray():
array = MyArray(5)
array.insert(0, 3)
array.insert(0, 4)
array.insert(1, 5)
array.insert(3, 9)
array.insert(3, 10)
assert array.insert(0, 100) is False
assert len(array) == 5
assert array.find(1) == 5
assert array.delete(4) is True
array.print_all()
if __name__ == "__main__":
test_myarray()
实现两个有序数组合并为一个有序数组
参考:https://www.cnblogs.com/LanTianYou/p/8976671.html
def merge_sort(a, b):
ret = []
i = j = 0
while len(a) >= i + 1 and len(b) >= j + 1:
if a[i] <= b[j]:
ret.append(a[i])
i += 1
else:
ret.append(b[j])
j += 1
if len(a) > i:
ret += a[i:]
if len(b) > j:
ret += b[j:]
return ret
if __name__ == '__main__':
a = [1,3,4,6,7,78,97,190]
b = [2,5,6,8,10,12,14,16,18]
print(merge_sort(a, b))
15. 三数之和(中等)
https://leetcode-cn.com/problems/3sum/
题目
答案
思路:
先对数组进行排序,如果是计算两个元素的和,则分别设置头和尾两个指针,向中间靠拢。
如果是计算两个元素的和,则只需要先对第一个数进行循环取值下标i,剩下的两个指针分别指向i+1和数组的最后一个元素,这样的复杂度是 排序O(nlogn) + 查找O(n^2) = O(n^2)。
class Solution(object):
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
nums.sort()
result = []
lenn = len(nums)
for i in range(lenn-2):
if i > 0 and nums[i] == nums[i-1]:
continue
l, r = i+1, lenn - 1
while l < r:
s = nums[i] + nums[l] + nums[r]
if s < 0:
l += 1
elif s > 0:
r -= 1
else:
result.append([nums[i], nums[l], nums[r]])
while l < r and nums[l] == nums[l+1]:
l += 1
while l < r and nums[r] == nums[r-1]:
r -= 1
l, r = l+1, r-1
return result
169. 求众数(简单)
https://leetcode-cn.com/problems/majority-element/
题目
答案
思路1:set使元素唯一,然后统计元素的出现次数
class Solution(object):
def majorityElement(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
res=set(nums)
n=len(nums)/2
for item in res:
if(nums.count(item)>n):
return item
思路2:排序后位于中间位置的数字
class Solution(object):
def majorityElement(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
return sorted(nums)[len(nums)//2]
41. 缺失的第一个正数(困难)
https://leetcode-cn.com/problems/first-missing-positive/
题目
答案
思路:
题目要求时间复杂度为O(n),空间复杂度为O(1)。可以采用类似于桶排序的思想进行求解。
- 首先把数组内,范围在 ( 0, n ] 元素x,放到nums[x - 1],类似桶排序中的找位置;
- 放好之后,进行遍历,找第一个 i + 1 != nums[i],返回 i + 1,就是结果,如果没有就返回 n + 1。
class Solution:
def firstMissingPositive(self, nums):
n, i = len(nums), 0
if n == 0:
return 1
while i < n:
w = nums[i] - 1 # 获取当前位置的数据,减去1是为了得到 在list要插入的位置
if 0 < nums[i] <= n and nums[i] != nums[w]: # 0 < nums[i] <= n 判断是否出界
nums[i], nums[w] = nums[w], nums[i] # nums[i] != nums[w] 如果相等或者是本身就没必要替换了,避免死循环
else:
i += 1 # 当前位置上的数,没有找到合适的位置,进行下一个位置
for i in range(n): # 遍历返回
if i + 1 != nums[i]:
return i + 1
return n + 1
if __name__ == '__main__':
nums = [7, 8, 9, 11, 12]
solu = Solution()
print(solu.firstMissingPositive(nums))
参考
https://blog.csdn.net/xx_123_1_rj/article/details/80840451
https://blog.csdn.net/Jaster_wisdom/article/details/80660467
链表
实现单链表、循环链表、双向链表,支持增删操作
参考:https://blog.csdn.net/Daputao_net/article/details/81589675
单链表
class Node(object):
"""定义一个节点"""
def __init__(self, elem):
self.elem = elem
self.next = None
class SingleLinkList(object):
"""单链表"""
def __init__(self, node=None):
# 因为不需要让用户知道我的头结点在哪里所以head定义为私有的属性。
self.__head = node
def is_empty(self):
"""链表是否为空"""
return self.__head is None
def length(self):
"""链表的长度"""
# cur游标,用来移动遍历节点
cur = self.__head
# count记录数量
count = 0
while cur != None:
count += 1
cur = cur.next
return count
def travel(self):
"""遍历整个链表"""
cur = self.__head
while cur != None:
print(cur.elem, end=" ")
cur = cur.next
print("")
def add(self, item):
"""链表头部添加元素"""
node = Node(item)
node.next = self.__head
self.__head = node
def append(self, item):
"""链表尾部添加元素"""
node = Node(item)
if self.is_empty():
self.__head = node
else:
cur = self.__head
while cur.next != None:
cur = cur.next
cur.next = node
# pos/position:位置,方位 param:参数
def insert(self, pos, item):
"""指定位置添加元素
:param pos 从0开始(即将链表的第一个节点记为0节点)"""
# pre/previous以前的,在什么之前
if pos <= 0:
self.add(item)
elif pos > (self.length()-1):
self.append(item)
else:
node = Node(item)
pre = self.__head
count = 0
while count < (pos-1):
count += 1
pre = pre.next
node.next = pre.next
pre.next = node
def remove(self, item):
"""删除节点"""
pre = self.__head
# 判断是不是空链表
if pre == None:
return False
# 判断是不是头结点,包含了只有一个节点情况
elif pre.elem == item:
self.__head = pre.next
# pre = None
return True
else:
while pre.next != None:
if pre.next.elem == item:
pre.next = pre.next.next
return True
else:
pre = pre.next
return False
# 也可以使用这种方法
# cur = self.__head
# pre = None
# while cur != None:
# if cur.elem == item:
# # 先判断此结点是否是头节点
# # 头节点
# if cur == self.__head:
# self.__head = cur.next
# else:
# pre.next = cur.next
# break
# else:
# pre = cur
# cur = cur.next
def search(self, item):
"""查找节点是否存在"""
cur = self.__head
while cur != None:
if cur.elem == item:
return True
else:
cur = cur.next
return False
if __name__ == '__main__':
sll = SingleLinkList()
print(sll.remove(4))
sll.travel()
print("----------")
sll.append(2)
print(sll.search(2))
print(sll.remove(2))
print("----------")
sll.append(2)
sll.append(3)
sll.append(5)
sll.append(6)
sll.append(7)
sll.travel()
sll.add(1)
sll.travel()
sll.insert(3, 4)
sll.travel()
sll.remove(1)
sll.travel()
sll.remove(7)
sll.travel()
sll.remove(4)
sll.travel()
print(sll.remove(100))
sll.travel()
print(sll.search(6))
单向循环链表
class Node(object):
"""定义一个节点"""
def __init__(self, elem):
self.elem = elem
self.next = None
class SingleLinkList(object):
"""单向循环链表"""
def __init__(self, node=None):
# 因为不需要让用户知道我的头结点在哪里所以head定义为私有的属性。
self.__head = node
if node != None:
node.next = node
def is_empty(self):
"""链表是否为空"""
return self.__head is None
def length(self):
"""链表的长度"""
if self.is_empty():
return 0
# cur游标,用来移动遍历节点
cur = self.__head
# count记录数量,因为循环不会进入最后一个节点所以初始值为1
count = 1
while cur.next != self.__head:
count += 1
cur = cur.next
return count
def travel(self):
"""遍历整个链表"""
cur = self.__head
if cur == None:
return
else:
while cur.next != self.__head:
print(cur.elem, end=" ")
cur = cur.next
# 退出循环后cur指向尾节点,但是尾节点没有打印。
print(cur.elem)
def add(self, item):
"""链表头部添加元素"""
node = Node(item)
if self.is_empty():
self.__head = node
node.next = self.__head
# 或者
# self.__head = node
# node.next = node
else:
cur = self.__head
while cur.next != self.__head:
cur = cur.next
# 循环结束后cur指向尾节点
node.next = self.__head
self.__head = node
cur.next = node
def append(self, item):
"""链表尾部添加元素"""
node = Node(item)
if self.is_empty():
self.__head = node
node.next = node
else:
cur = self.__head
while cur.next != self.__head:
cur = cur.next
# 循环结束cur指向最后一个节点
cur.next = node
node.next = self.__head
# pos/position:位置,方位 param:参数
def insert(self, pos, item):
"""指定位置添加元素
:param pos 从0开始(即将链表的第一个节点记为0节点)"""
# pre/previous以前的,在什么之前
if pos <= 0:
self.add(item)
elif pos > (self.length()-1):
self.append(item)
else:
node = Node(item)
pre = self.__head
count = 0
while count < (pos-1):
count += 1
pre = pre.next
node.next = pre.next
pre.next = node
def remove(self, item):
"""删除节点"""
pre = self.__head
cur = self.__head
# 判断是不是空链表
if cur == None:
return False
# 判断是不是头结点
elif cur.elem == item:
# 判断是不是只有一个节点
if cur.next == self.__head:
self.__head = None
return True
else:
while pre.next != self.__head:
pre = pre.next
self.__head = cur.next
pre.next = self.__head
return True
else:
while pre.next != self.__head:
if pre.next.elem == item:
pre.next = pre.next.next
return True
else:
pre = pre.next
return False
def search(self, item):
"""查找节点是否存在"""
cur = self.__head
# 判断是否为空链表
if self.__head == None:
return False
# 判断是不是头结点
elif cur.elem == item:
return True
else:
while cur.next != self.__head:
if cur.elem == item:
return True
else:
cur = cur.next
# 循环退出后cur指向最后一个节点,但是没有进入最后一个节点
if cur.elem == item:
return True
return False
if __name__ == '__main__':
sll = SingleLinkList()
print(sll.remove(4))
sll.travel()
print("----------")
sll.append(2)
print(sll.search(2))
print(sll.remove(2))
print("----------")
sll.append(2)
sll.append(3)
sll.append(5)
sll.append(6)
sll.append(7)
sll.travel()
sll.add(1)
sll.travel()
sll.insert(3, 4)
sll.travel()
sll.remove(1)
sll.travel()
sll.remove(7)
sll.travel()
sll.remove(4)
sll.travel()
print(sll.remove(100))
sll.travel()
print(sll.search(6))
双向链表
class Node(object):
"""节点"""
def __init__(self, item):
self.elem = item
self.next = None
self.prev = None
class DoubleLinkList(object):
"""双向链表"""
def __init__(self, node=None):
self.__head = node
def is_empty(self):
"""链表是否为空"""
return self.__head is None
def length(self):
"""链表长度"""
# cur游标,用来移动遍历节点
cur = self.__head
# counter:记录数量
counter = 0
while cur != None:
counter += 1
cur = cur.next
return counter
def append(self, item):
"""链表尾部添加节点,尾插法"""
node = Node(item)
if self.is_empty():
self.__head = node
else:
cur = self.__head
while cur.next != None:
cur = cur.next
cur.next = node
node.prev = cur
def add(self, item):
"""链表头部添加节点,头插法"""
node = Node(item)
node.next = self.__head
self.__head = node
node.next.prev = node
def insert(self, pos, item):
"""任意位置添加节点"""
# pos的初始值为0
if pos <= 0:
self.add()
elif pos > (self.length()-1):
self.append()
else:
cur = self.__head
counter = 0
while counter != pos:
counter += 1
cur = cur.next
node = Node(item)
node.prev = cur.prev
cur.prev.next = node
node.next = cur
cur.prev = node
def travel(self):
"""遍历整个链表"""
cur = self.__head
while cur != None:
print(cur.elem, end=" ")
cur = cur.next
print("")
def remove(self, item):
"""根据元素删除节点"""
cur = self.__head
while cur != None:
if cur.elem == item:
# 先判断此结点是否是头节点
# 头节点
if cur == self.__head:
self.__head = cur.next
if cur.next != None:
# 链表不只有一个节点
cur.next.prev = None
else:
cur.prev.next = cur.next
if cur.next != None:
cur.next.prev = cur.prev
return True
else:
cur = cur.next
return False
def search(self, item):
"""根据元素查找节点是否存在"""
cur = self.__head
while cur != None:
if cur.elem == item:
return True
else:
cur = cur.next
return False
if __name__ == '__main__':
dll = DoubleLinkList()
print(dll.remove(4))
dll.travel()
print("----------")
dll.append(2)
print(dll.search(2))
print(dll.remove(2))
print("----------")
dll.append(2)
dll.append(3)
dll.append(5)
dll.append(6)
dll.append(7)
dll.travel()
dll.add(1)
dll.travel()
dll.insert(3, 4)
dll.travel()
dll.remove(1)
dll.travel()
dll.remove(7)
dll.travel()
dll.remove(4)
dll.travel()
print(dll.remove(100))
dll.travel()
实现单链表反转
参考:https://blog.csdn.net/su_bao/article/details/81072849
https://blog.csdn.net/The__Apollo/article/details/78769400
class Node(object):
def __init__(self, data, next=None):
self.val = data
self.next = next
def fun4(head):
if head == None:
return None
L,M,R = None,None,head
while R.next != None:
L = M
M = R
R = R.next
M.next = L
R.next = M
return R
#测试用例
if __name__ == '__main__':
l1 = Node(3)
l1.next = Node(2)
l1.next.next = Node(1)
l1.next.next.next = Node(9)
l = fun4(l1)
print (l.val, l.next.val, l.next.next.val, l.next.next.next.val)
实现两个有序的链表合并为一个有序链表
参考leetcode-023
实现求链表的中间结点
方法1
参考:https://blog.csdn.net/qq_27060423/article/details/82891248
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def middleNode(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
p=head
count=0
while p:
count+=1
p=p.next
i=0
p=head
while i<count//2:
p=p.next
i+=1
return p
方法2
参考:https://blog.csdn.net/weixin_41722370/article/details/83314501
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
import math
class Solution:
def middleNode(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
# 首先要知道链表一共有多少个结点
count = 0
res = {}
while head != None:
count += 1
res[count] = head
head = head.next
#j = math.ceil(count/2)
#if count % 2 == 0:
# return res[j+1]
#else:
# return res[j]
j = math.ceil((count-1)/2) + 1
return res[j]
141. 环形链表
https://leetcode-cn.com/problems/linked-list-cycle/
题目
答案
思路:
设置两个指针slow和fast,一个步长为1,一个步长为2进行遍历。如果有环,则slow和fast总会在某一点相遇。如果没有环,则fas或者fast.next会先为空。
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def hasCycle(self, head):
"""
:type head: ListNode
:rtype: bool
"""
fast = slow = head #fast每次跑2步,slow每次跑1步
while fast and fast.next: #判断跑得快的是否为空
fast = fast.next.next
slow = slow.next
if slow == fast: #存在环则必然会出现相等
return True
return False
参考
https://blog.csdn.net/qq_34364995/article/details/80518191
23. 合并K个排序链表
https://leetcode-cn.com/problems/merge-k-sorted-lists/
题目
答案
思路:
先将所有列表按照第一个元素的大小放入小根堆中,然后每次取回最小的元素的列表,将该列表下一个元素放入小根堆中。直到小根堆为空。这样就得到了排好序的一个列表。小根堆构建的复杂度为O(NlogN),每次取最小值的复杂度为O(logN),向小根堆添加元素的复杂度为O(logN)。所有总的实现复杂度为O(NlogN)。
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def mergeKLists(self, lists):
"""
:type lists: List[ListNode]
:rtype: ListNode
"""
heap = []
for l in lists:
if l != None:
heap.append((l.val,l))
heapq.heapify(heap) #调整a,使得其满足最小堆
dummy = ListNode(0)
cur = dummy
while heap:
_,h = heapq.heappop(heap) #从最小堆中弹出最小的元素
cur.next = h
cur = cur.next
if h.next:
heapq.heappush(heap,(h.next.val,h.next)) #向最小堆中压入新的元素
return dummy.next
参考
https://blog.csdn.net/qian2729/article/details/50528385