python本身没有数组结构,虽然列表可以完成数组的基本功能,也可通过嵌套实现多维列表,但是当数据量较大时,速度会变慢。通常我们可以利用array模块或Numpy里封装的array()创建数组。
在这里,基于Python的列表实现动态数组的创建。
class DynamicArr:
def __init__(self, capacity=20):
'''
构造函数
:param capacity:数组容量大小,默认为20
'''
self._capacity = capacity
self._length = 0 # 数组的有效长度
# 基于列表实现,通过赋值None实现底层具有连续的内存空间,容量固定的数组
self._data = [None] * self._capacity
def __getitem__(self, index):
'''使得DynamicArr类实例化对象支持索引随机访问'''
return self._data[index]
def __setitem__(self, index, value):
'''使得DynamicArr类实例化对象支持直接赋值'''
self._data[index] = value
def getLength(self):
'''返回当前数组长度'''
return self._length
def getCapacity(self):
'''返回数组容量'''
return self._capacity
def add(self, index, value):
'''
往数组增加一个元素
:param index:待添加元素在数组的目标下标
:param value:待添加元素的值
'''
if index < 0 or index > self._length: # 无效的插入位置
raise Exception('invaild index: require 0 <= index <= self._size')
if self._length == self._capacity: # 数组已满
# 将数组容量扩充至两倍,比单独扩充一个单位要好,均摊复杂度为O(1)
self._resize(self._capacity*2)
for i in range(self._size, index-1, -1):
self._data[i+1] = self._data[i]
self._data[index] = value
self._length += 1
def addLast(self, value): # 往数组的末尾添加元素
return self.add(self._length, value)
def _resize(self, newCapacity):
'''
重构数组的容量
:param newCapacity:新的容量大小
'''
newArr = DynamicArr(newCapacity)
for i in range(self._length):
newArr.addLast(self._data[i])
self._capacity = newArr._capacity
self._data = newArr._data
class StaticOrderArr:
def __init__(self, capacity=20): # 数组默认容量为20
self._capacity = capacity
self._length = 0
self._data = [None] * self._capacity
def __getitem__(self, index):
return self._data[index]
def __setitem__(self, index, value):
'''使数组支持更改操作'''
if index <= self._length and index >= 0:
if index == 0 or index == self._length-1:
self._data[index] = value
else:
if self._data[index-1] <= value and self._data[index+1] >= value:
self._data[index] = value
else:
raise Exception('set failed: require value meets the demand of order')
else:
raise Exception('set failed: invaild index')
def add(self, value):
'''
往有序数组添加值为value的元素
'''
if self._length == self._capacity:
raise Exception('The arrary is full')
elif self._length == 0:
self._data[0] = value
self._length += 1
else:
for i in range(self._length-1, -1, -1):
if self._data[i] > value:
self._data[i+1] = self._data[i]
else:
self._data[i+1] = value
self._length += 1
break
if self._data[0] > value:
self._data[0] = value
self._length += 1
def remove(self, index):
'''删除有序数组中下标为index的元素'''
if self._length == 0:
raise Exception('remove failed: Array is empty')
if index < 0 or index > self._length:
raise Exception('invaild index,require 0 <= index <= self._length')
else:
for i in range(index+1,self._length,1):
self._data[i-1] = self._data[i]
self._length -= 1
def getLength(self):
return self._length
def getCapacity(self):
return self._capacity
def isorder(arr=[]):
'''
判断数组是否有序
'''
arrSize = len(arr)
flag = True
if not arr:
flag = True
else:
for i in range(arrSize-1):
if arr[i] < arr[i+1]:
pass
else:
flag = False
return flag
def mergeSort(arr1=[],arr2=[]):
newArr = []
if isorder(arr1) and isorder(arr2): # 判断参数的合理性
if not arr1: # 当参数存在空数组的情况
newArr = arr2
elif not arr2:
newArr = arr1
else: # 当参数为两个有序数组的情况
i = j = 0
len1 = len(arr1);len2 = len(arr2)
while i < len1 and j < len2:
'''循环比较两个数组之间相对位置的元素大小,将较小的元素放入到新的数组中,直到有一组排序完毕'''
if arr1[i] <= arr2[j]:
newArr.append(arr1[i])
i += 1
else:
newArr.append(arr2[j])
j += 1
while i < len1: # 当arr1没有排序完毕
newArr.append(arr1[i])
i += 1
while j < len2: # 当arr2没有排序完毕
newArr.append(arr2[j])
j += 1
return newArr
else:
print('待排序的数组要求必须有序!')
用哈希表思想实现:
class Solution:
def twoSum(self, nums, target):
hash_dict = dict()
for i in range(len(nums)):
num = nums[i]
if hash_dict.get(target - num) == None:
hash_dict[num] = i
else:
return [hash_dict[target - num], i]
s = Solution()
s.twoSum([1,3,5,8,2,-1],10)
用哈希表思想实现:当某个值第二次出现时,则开始进入循环,此时可直接判断该数不是快乐数
class Solution:
def isHappy(self, n):
hash_set = dict()
while True:
if hash_set.get(n) == None:
hash_set[n] = 1
num = str(n)
length = len(num)
n = 0
for i in range(length):
n += int(num[i]) ** 2
if n == 1:
flag = True
break
else:
num = n
else:
flag = False
break
return flag
采用的思路是:遍历数组arr,再对target - arr[i]采用两数之和的求解方法,则arr[i]与两数之和函数所返回的列表[n1, n2]则可组成一个所求解。
def twoSum(nums, target):
hash_table = dict()
length = len(nums)
result = []
for i in range(length):
if hash_table.get(target - nums[i]) == None:
hash_table[nums[i]] = True
else:
result.append([target - nums[i], nums[i]])
return result
def threeSum(nums, target):
length = len(nums)
hash_table = dict()
result = []
for i in range(length):
target2 = target - nums[i]
if hash_table.get(nums[i]) == None:
hash_table[nums[i]] = True
temps = twoSum(nums[:i] + nums[i+1:], target2)
if temps:
for temp in temps:
temp.append(nums[i])
result.append(temp)
result_final = [list(t) for t in set(tuple(_) for _ in result)]
return result_final
思路:直接遍历,将第一个元素做初始比较数,设置一个count计数器,初始为1。遍历数组,当遇到相同值则+1,遇到不同值则-1,当count为零时,则将比较数改为当前数组元素。
class Solution:
def majorityElement(self, nums: List[int]) -> int:
length = len(nums)
count = 1
comp = nums[0]
for i in range(1,length):
if nums[i] == comp:
count += 1
else:
count -= 1
if count == 0:
comp = nums[i]
count = 1
return comp
采用思路:利用哈希思想,遍历数组,对其中大于等于零的元素进行hash。遍历完数组后,从1开始遍历哈希表,遇到的第一没有访问过的值即为所求缺失的第一个正数
def firstMissingPositive(nums):
hash_table = dict()
maxPostive = -1
if not nums: # 数组为空
return 1
for num in nums:
if num >= 0 and hash_table.get(num) == None:
hash_table[num] = True
if maxPostive < num:
maxPostive = num
if maxPostive == -1: # 数组中没有正数
return 1
for i in range(1, maxPostive+2): # maxPostive+2 : 当所求最小正整数为数组中最大正数+1时
if hash_table.get(i) != True:
return i
class linkedList:
def __init__(self, data, pnext=None):
self.data = data
self.next = pnext
# 打印链表
def show(node):
p = node
while p:
print(p.data, end = ' ')
p = p.next
print('\n')
# 创建一个单链表
def createLinkedlist(lst=[]):
linkedlst = linkedList(lst[0])
head = linkedlst
p = head
for _ in lst[1:]:
node = linkedList(_)
p.next = node
p = node
return head
# 在链表index处的结点后插入值为value的结点
def insert(index, head, value):
count = 0
p = head
while p != None:
if count == index:
break
else:
p = p.next
count += 1
node = linkedList(value)
node.next = p.next
p.next = node
# 删除链表中所有值为value的结点
def delete(head, value):
while head.data == value: # 当头结点的值为value
head = head.next
pre = head
q = pre.next
while q != None:
if q.data == value:
pre.next = q.next
q = q.next
else:
pre = q
q = q.next
return head
class Recylelinkedlist:
'''不带头结点的单循环链表'''
def __init__(self, value, pnext=None):
self.next = pnext
self.data = value
# 创建一个带头结点单链表
def createRecyLinkedlist(lst=[]):
recylinkedlst = Recylelinkedlist(lst[0])
head = recylinkedlst
p = head
for _ in lst[1:-1]:
node = Recylelinkedlist(_)
p.next = node
p = node
node = Recylelinkedlist(lst[-1])
node.next = head
p.next = node
return head
def append(head, value):
'''
在尾结点后插入结点value
'''
p = head
while p.next != head: # 找到尾结点
p = p.next
node = Recylelinkedlist(value,head)
p.next = node
def pop(head):
'''删除单循环链表尾结点'''
p = head
while p.next.next != head:
p = p.next
p.next = head
def delFirst(head_node):
'''删除头结点'''
p = head_node
while p.next != head_node: # 找到尾结点
p = p.next
head = head_node.next
p.next = head
return head
# 在链表index处的结点后插入值为value的结点(若超过链表长度则继续循环往下数)
def insert(index, head, value):
r = head
count = 0
while count != index: # 找到index对应的结点
r = r.next
count += 1
if r.next == head: # 当目标位置刚好为尾结点位置
node = Recylelinkedlist(value,head)
r.next = node
else:
node = Recylelinkedlist(value)
node.next = r.next
r.next = node
# 删除链表中所有值为value的结点
def delete(head, value):
while True: # 若头结点的值为value
if head.data == value:
head = delFirst(head)
else:
break
pre = head
q = head.next
while q != head:
if q.data == value:
pre.next = q.next
q = q.next
else:
pre = q
q = q.next
return head
# 打印链表
def show(node):
p = node
while p.next != node:
print(p.data, end = ' ')
p = p.next
print(p.data) # 打印尾结点
print('\n')
lst = [13,41,4,1,41,5,6]
head = createRecyLinkedlist(lst)
show(head)
append(head,10)
show(head)
head = delFirst(head)
show(head)
pop(head)
show(head)
insert(2, head, 99)
show(head)
head = delete(head, 41)
show(head)
class DoubleRecylelinkedlist:
'''不带头结点的双向循环链表'''
def __init__(self, value, pnext=None, ppre=None):
self.next = pnext
self.pre = ppre
self.data = value
# 创建一个带头结点单链表
def createDoubleRecyLinkedlist(lst=[]):
doubleRecylinkedlst = DoubleRecylelinkedlist(lst[0])
head = doubleRecylinkedlst
p = head
for _ in lst[1:-1]:
node = DoubleRecylelinkedlist(_)
p.next = node
node.pre = p
p = node
node = DoubleRecylelinkedlist(lst[-1])
node.next = head
node.pre = p
p.next = node
head.pre = node
return head
def append(head, value):
'''
在尾结点后插入结点value
'''
p = head.pre # 尾结点
node = DoubleRecylelinkedlist(value)
p.next = node
node.pre = p
node.next = head
head.pre = node
def pop(head):
'''删除双循环链表尾结点'''
p = head.pre.pre
p.next = head
head.pre = p
def delFirst(head_node):
'''删除头结点'''
p = head_node.pre # 找到尾结点
head = head_node.next
head.pre = p
p.next = head
return head
# 在链表index处的结点后插入值为value的结点(若超过链表长度则继续循环往下数)
def insert(index, head, value):
r = head
count = 0
while count != index: # 找到index对应的结点
r = r.next
count += 1
if r.next == head: # 当目标位置刚好为尾结点位置
node = DoubleRecylelinkedlist(value)
r.next = node
node.pre = r
node.next = head
head.pre = node
else:
node = DoubleRecylelinkedlist(value)
node.next = r.next
r.next.pre = node
node.pre = r
r.next = node
# 删除链表中所有值为value的结点
def delete(head, value):
while True: # 若头结点的值为value
if head.data == value:
head = delFirst(head)
else:
break
pre = head
q = head.next
while q != head:
if q.data == value:
pre.next = q.next
q.next.pre = pre
q = q.next
else:
pre = q
q = q.next
return head
# 打印链表
def show(node):
p = node
while p.next != node:
print(p.data, end = ' ')
p = p.next
print(p.data) # 打印尾结点
print('\n')
lst = [13,41,4,1,41,5,6]
head = createDoubleRecyLinkedlist(lst)
show(head)
print(head.data,head.pre.data,head.next.data)
append(head,10)
show(head)
head = delFirst(head)
show(head)
pop(head)
show(head)
insert(2, head, 99)
show(head)
head = delete(head, 41)
show(head)
def reversedLinklist(linkedlist):
r = linkedlist
p = r.next
r.next = None
q = p
p = p.next
while q != None:
q.next = r
r = q
q = p
if p != None:
p = p.next
return r
def mergeSortLinkedlist(linkedlist1, linkedlist2):
'''两个有序的不带头结点的链表合并为一个不带头结点的有序链表'''
p = linkedlist1
q = linkedlist2
if q != None and p != None:
if p.data <= q.data:
head = p
p = p.next
head.next = None
else:
head = q
q = q.next
head.next = None
r = head # 创建头结点
while q != None and p != None:
if p.data <= q.data:
r.next = p
r = p
p = p.next
else:
r.next = q
r = q
q = q.next
if p: # 若linkedlist1没有排序结束
q = p
r.next = q
return head
def middleNode(linkedlist):
p = linkedlist
length = 0
while p != None:
length += 1
p = p.next
count = length // 2
p = linkedlist
while count:
p = p.next
count -= 1
return p
class Solution(object):
def hasCycle(self, head):
"""
:type head: ListNode
:rtype: bool
"""
if head:
while True:
if head.val == 'vncbasdnvnvmz':
return True
else:
head.val = 'vncbasdnvnvmz'
head = head.next
if head == None:
break
return False
采用思路:将链表转换为列表,对列表进行排序,再依据列表数据建立链表
执行用时 : 116 ms, 在Merge k Sorted Lists的Python提交中击败了84.19% 的用户
内存消耗 : 20.1 MB, 在Merge k Sorted Lists的Python提交中击败了11.89% 的用户
class Solution(object):
def mergeKLists(self, lists):
"""
:type lists: List[ListNode]
:rtype: ListNode
"""
if lists:
re = []
for lst in lists:
if lst:
while lst:
re.append(lst.val)
lst = lst.next
if re:
re.sort()
head = ListNode(re[0])
r = head
for value in re[1:]:
node = ListNode(value)
r.next = node
return head