排序
- 快速排序 快排
时间复杂度:O(nlogn)空间复杂度:O(1)
不稳定
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
# 将给定数组排序
# @param arr int整型一维数组 待排序的数组
# @return int整型一维数组
#
class Solution:
def MySort(self , arr ):
# write code here
self.quick_sort(0, len(arr)-1, arr)
return arr
def quick_sort(self, start, end, arr):
if start >= end:
return
left, right = start, end
pivot = arr[(start + end)//2]
while left <= right:
while left <= right and arr[left] < pivot:
left += 1
while left <= right and arr[right] > pivot:
right -= 1
if left <= right:
arr[left], arr[right] = arr[right], arr[left]
left += 1
right -= 1
self.quick_sort(start, right, arr)
self.quick_sort(left, end, arr)
- 冒泡排序
一对一对的比较 反复loop
367219 - 362179 - 321679 - 213679 - 123679
时间复杂度:O(n^2)空间复杂度:O(1)
- 选择排序
选一个最大或最小值放在起始位,不断loop后面的找到最值,更新在后面的位置
367219 - 167239 - 127639 - 123679
时间复杂度:O(n^2)空间复杂度:O(1)
- 插入排序
每次把当前元素跟前面排好的相比,不断地swap到应该在的地方
367219 - 236719 - 123679
时间复杂度:O(n^2)空间复杂度:O(1)
- 归并排序
时间复杂度:O(nlogn)空间复杂度:O(1)
稳定 - 堆排序
时间复杂度:O(nlogn)空间复杂度:O(1)
不稳定
class Solution:
def MySort(self , arr ):
# write code here
# return self.bubble_sort(arr)
# return self.select_sort(arr)
# return self.insert_sort(arr)
return self.quick_sort(arr)
# return self.merge_sort(arr)
def bubble_sort(self, arr):
# 冒泡排序 不通过
for i in range(len(arr) - 1):
for j in range(len(arr) - i - 1):
if arr[j] > arr[j+1]:
arr[j], arr[j+1] = arr[j+1], arr[j]
return arr
def select_sort(self, arr):
# 选择排序 不通过
for i in range(len(arr)):
min_index = i
for j in range(i+1, len(arr)):
if arr[j] < arr[min_index]:
min_index = j
arr[min_index], arr[i] = arr[i], arr[min_index]
return arr
def insert_sort(self, li):
# 插入排序 不通过
for i in range(1, len(li)):
tmp = li[i] # tmp要插入的之
j = i - 1
while j >= 0 and li[j] > tmp: # 前面的值比tmp大
li[j+1] = li[j] # 前面的值向后移一位
j = j - 1 # 继续向前对比
li[j+1] = tmp # 直到while不满足条件, 也就是前面的值比tmp小, 插入到比tmp小的值后
return li
def quick_sort(self, li):
# 快速排序 通过
if len(li) < 2:
return li
else:
tmp = li[0]
less = [i for i in li[1:] if i <= tmp]
more = [i for i in li[1:] if i > tmp]
return self.quick_sort(less) + [tmp] + self.quick_sort(more)
def merge_sort(self, li):
# 归并排序 可能通过 可能不通过
if len(li) < 2:
return li
else:
num = len(li) // 2
left = self.merge_sort(li[:num])
right = self.merge_sort(li[num:])
return self.merge(left, right)
def merge(self, left, right):
l,r = 0,0
result = []
while l < len(left) and r < len(right):
if left[l] < right[r]:
result.append(left[l])
l += 1
else:
result.append(right[r])
r += 1
result += left[l:]
result += right[r:]
return result
反转链表
假设 链表为 1->2->3->4->null 空就是链表的尾
obj: 4->3->2->1->null
那么逻辑是
首先设定待反转链表的尾 pre = none
head 代表一个动态的表头 逐步取下一次链表的值
然后利用temp保存 head.next 第一次迭代head为1 temp 为2 原始链表中是1->2
现在我们需要翻转 即 令head.next = pre 实现 1->none
但此时链表切断了 变成了 1->none 2->3->4
所以我们要移动指针,另pre = head 也就是pre从none 变成1 下一次即可完成2->1的链接
此外另head = next 也就是说 把指针移动到后面仍然链接的链表上
这样执行下一次循环 则实现 把2->3 转变为 2->1->none
然后再次迭代
直到最后一次 head 变成了none 而pre变成了4 则pre是新的链表的表头
完成翻转
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# 返回ListNode
def ReverseList(self, pHead):
# write code here
pre = None
head = pHead
while head:
temp = head.next
head.next = pre
pre = head
head = temp
return pre
LRU缓存结构
二维数组中第0位即:[1,1,1],第一个1表示opt=1,要set(1,1),即要将(1,1)插入缓存
二维数组中第1为即:[1,2,2],第一个1表示opt=1,要set(2,2),即要将(2,2)插入缓存
二维数组中第2位即:[1,3,2],第一个1表示opt=1,要set(3,2),即要将(3,2)插入缓存
二维数组中第3位即:[2,1],第一个2表示opt=2,要get(1),即从缓存中查找key为1的值,前面已经插入了key=1,所以返回1,这个要保存到返回数组中
二维数组中第5位即:[2,2],第一个2表示opt=2,要get(2),即从缓存中查找key为2的值,由于缓存大小为3,所以前面插入的key=2已经被挤出缓存,所以返回结果为-1,这个要保存到返回数组中
所以输出为[1,-1]
示例1中,输入最后一个单独的3表示缓存大小
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# lru design
# @param operators int整型二维数组 the ops
# @param k int整型 the k
# @return int整型一维数组
#
class Solution:
def LRU(self , operators: List[List[int]], k: int) -> List[int]:
# write code here
stack = []
res = []
lru = {}
for op in operators:
if(op[0] == 1):
if(len(stack) >= k):
del lru[stack.pop(0)]
if(op[1] in lru):
stack.pop(stack.index(op[1]))
stack.append(op[1])
lru[op[1]] = op[2]
elif(op[0] == 2):
if(op[1] not in lru):
res.append(-1)
else:
res.append(lru[op[1]])
stack.append(stack.pop(stack.index(op[1])))
return res
加入的时候判断内存是否溢出
get的时候判断dict.keys()
class Solution:
def LRU(self , operators , k ):
A,a=dict(),[]
def set(key,value):
if len(a)<k:
A[key]=value
a.append(key)
else:
del A[a.pop(0)]
A[key]=value
a.append(key)
def get(key):
if key in A.keys():
a.remove(key)
a.append(key)
return A[key]
else: return -1
sol=[]
for i in operators:
if i[0]==1: set(i[1],i[2])
else:
sol.append(get(i[1]))
return sol
# write code here
遍历
输入:
{1,2,3}
返回值:
[[1,2,3],[2,1,3],[2,3,1]]
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param root TreeNode类 the root of binary tree
# @return int整型二维数组
#
class Solution:
def threeOrders(self , root: TreeNode) -> List[List[int]]:
# write code here
return [self.front(root), self.middle(root), self.back(root)]
def front(self, root, var=None):
if root is None:
return # 终止递归
if var is None:
var = [] # 开始递归,初始化结果存储列表
var.append(root.val)
lt = self.front(root.left, var)
rt = self.front(root.right, var)
return var
def middle(self, root, var=None):
if root is None:
return
if var is None:
var = []
lt = self.middle(root.left, var)
var.append(root.val)
rt = self.middle(root.right, var)
return var
def back(self, root, var=None):
if root is None:
return
if var is None:
var = []
lt = self.back(root.left, var)
rt = self.back(root.right, var)
var.append(root.val)
return var
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
#
#
# @param root TreeNode类 the root of binary tree
# @return int整型二维数组
#
firstArr = []
midArr = []
lastArr = []
class Solution:
def threeOrders(self , root ):
# write code here
res = []
#前序遍历
res.append(self.firstSearch(root))
res.append(self.midSearch(root))
res.append(self.lastSearch(root))
return res
def firstSearch(self, root):
if root != None:
firstArr.append(root.val)
self.firstSearch(root.left)
self.firstSearch(root.right)
return firstArr
def midSearch(self, root):
if root != None:
self.midSearch(root.left)
midArr.append(root.val)
self.midSearch(root.right)
return midArr
def lastSearch(self, root):
if root != None:
self.lastSearch(root.left)
self.lastSearch(root.right)
lastArr.append(root.val)
return lastArr
https://blog.csdn.net/chinesekobe/article/details/110874773?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164333012316780261931344%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=164333012316780261931344&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_positive~default-1-110874773.first_rank_v2_pc_rank_v29&utm_term=%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E9%81%8D%E5%8E%86&spm=1018.2226.3001.4187
# -*- coding:utf-8 -*-
class Solution:
def GetLeastNumbers_Solution(self, tinput, k):
# write code here
l = len(tinput)
for i in range(k):
# find the smallest number
min_index = i
for j in range(i+1, l):
if tinput[j]< tinput[min_index]:
min_index = j
tinput[i], tinput[min_index] = tinput[min_index], tinput[i]
return tinput[0:k]
方法一:排序
本题使用排序算法解决最直观,对数组 arr 执行排序,再返回前 kk 个元素即可。使用任意排序算法皆可,本文采用并介绍 快速排序 ,为下文 方法二 做铺垫。
快速排序原理:
快速排序算法有两个核心点,分别为 “哨兵划分” 和 “递归” 。
哨兵划分操作: 以数组某个元素(一般选取首元素)为 基准数 ,将所有小于基准数的元素移动至其左边,大于基准数的元素移动至其右边。
如下图所示,为哨兵划分操作流程。通过一轮 哨兵划分 ,可将数组排序问题拆分为 两个较短数组的排序问题 (本文称之为左(右)子数组)
kua
class Solution:
def GetLeastNumbers_Solution(self, tinput, k):
# write code here
def quick_sort(arr, l, r):
if l>=r: return
i, j = l, r
while i < j:
while i < j and tinput[j] >= tinput[l]: j-=1
while i < j and tinput[i] <= tinput[l]: i+=1
tinput[i], tinput[j] = tinput[j], tinput[i]
tinput[i], tinput[l] = tinput[l], tinput[i]
quick_sort(tinput, l, i-1)
quick_sort(tinput, i+1, r)
quick_sort(tinput, 0, len(tinput)-1)
return tinput[:k]
# -*- coding:utf-8 -*-
class Solution:
def jumpFloor(self, number):
# write code here
#由于一次可以跳1个台阶或2个台阶,所以可得到
if number < 3:
return number
#当台阶大于等于3的时候,f(n) = f(n - 1) + f(n - 2)
return self.jumpFloor(number - 1) + self.jumpFloor(number - 2)
# -*- coding:utf-8 -*-
class Solution:
def jumpFloor(self, number):
# write code here
#由于一次可以跳1个台阶或2个台阶,所以可得到
if number < 3:
return number
#当台阶大于等于3的时候
else:
#定义初始值为1 和 2
a, b =1, 2
for i in range(number - 2):
a, b = b, a + b #根据f(n) = f(n-1) + f(n-2),可得状态转移方程如左
return b
# -*- coding:utf-8 -*-
class Solution:
def FindGreatestSumOfSubArray(self, array):
# write code here
dp = [i for i in array]
for i in range(1,len(array)):
dp[i] = max(dp[i-1]+array[i],array[i])
return max(dp)
最长无重复字数组
队列的思想,队列和堆栈的不同是:先进先出,所以要用pop(0)来剔除首元素
class Solution:
def maxLength(self , arr ):
# write code here
res = 0
l = list()
for i in arr:
while i in l:
l.pop(0)
l.append(i)
res = max(res, len(l))
return res
class Solution:
def maxLength(self , arr ):
# write code here
l = []
m = 0
n = 0
for i in arr:
if i not in l:
l.append(i)
n += 1
else:
m = max(m,n)
l = l[l.index(i)+1:]
l.append(i)
n = len(l)
return max(m,n)
使用小学时候的方法
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
# 计算两个数之和
# @param s string字符串 表示第一个整数
# @param t string字符串 表示第二个整数
# @return string字符串
#
class Solution:
def solve(self , s , t ):
# write code here
full = 0 #保存进位
l1,l2 = len(s),len(t)
length_max = max(l1,l2)
result = ''
for i in range(length_max):
if i<l1:
x1 = int(s[l1-i-1])
else:
x1 = 0
if i<l2:
x2 = int(t[l2-i-1])
else:
x2 = 0
tem = x1+x2+full
if tem >=10: #判断进位
full =1
result += (str(tem-10))
else:
full = 0
result += (str(tem))
if full == 1: #判断首位是否进位
result += '1'
return result[::-1]
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 反转字符串
# @param str string字符串
# @return string字符串
#
class Solution:
def solve(self , str: str) -> str:
# write code here
if not str:
return ""
nums = list(str)
i = 0
j = len(nums)-1
while i < j:
nums[i], nums[j] = nums[j], nums[i]
i += 1
j -= 1
return ''.join(nums)
# return str[::-1] # 一行解决字符串反转,没有额外空间
class Solution:
def solve(self , str: str) -> str:
new_str = ""
for i in str:
new_str = i + new_str
return new_str