牛客网视频总结3
目录)
排序总结
排序方法 | 时间复杂度 | 稳定性 | 额外空间复杂度 | 简单介绍 |
---|---|---|---|---|
冒泡排序 | O ( N 2 ) O(N^2) O(N2) | 稳定 | - | 两两比较交换 |
选择排序 | O ( N 2 ) O(N^2) O(N2) | 不稳定 | - | 选最小的放前面(交换index) |
插入排序 | O ( N 2 ) O(N^2) O(N2) | 稳定 | - | 前面的先排好,从后往前比 |
归并排序 | O ( N l o g N ) O(NlogN) O(NlogN) | 稳定 | O ( N ) O(N) O(N) | 递归排序,永远先放左边的 |
快速排序 | O ( N l o g N ) O(NlogN) O(NlogN) | 不稳定 | O ( l o g N ) O(logN) O(logN) | 挑一个数放到最后面,<=> |
堆排序 | O ( N l o g N ) O(NlogN) O(NlogN) | 不稳定 | - | 变成大根堆,和最后一个数换 |
工程上的综合排序
- 如果数组装的是基础类型,如int, double, char, float, short,用快排(不要求稳定,快就行)
- 如果装的是自己定义的类型,如Student,用归并排序(要求稳定)
- 如果数组很短,长度<60,用插入排序,插入排序常数项小
桶排序(计数排序,计数排序)
- 非基于比较的排序,与被排序样本的实际数据状况有关,因此很少用
- 时间复杂度 O ( N ) O(N) O(N),额外空间复杂度 O ( N ) O(N) O(N)
- 稳定
计数排序
问:已知数组范围0-60,请排序
答:生成新数组[0,0,…,0],长度为61,给每个位置的词频初始化为0,排序时遇到1个2,则2位置上++变为1,又遇到一个2,再++变为2…
桶:1种数据状况出现的词频
相邻两数最大差值
问:给定一个数组,求如果排序之后,相邻两数的最大差值,要求时间复杂度
O
(
N
)
O(N)
O(N),且要求不能用非基于比较的排序
答:
- 数组中N个数,则准备N+1个桶
- 找最小值和最大值,求差为X,如果X==0,则返回0;如果X!=0,则将X分为N+1份。如最小值0,最大值99,共9个数,则第一个桶范围0-9,第二个桶10-19,第10个桶90-99
- 数组中的数属于哪个范围则进哪个桶
- 必存在一个空桶(N个数,N+1个桶),空桶左右相差一定大于一个桶内的相差,因此用下个桶的min-上个桶的max就能计算差值
- 建三个数组,分别Boolean类型代表桶是否空,min代表每个桶的最小值,max代表每个桶的最大值。
- 找每个桶的min-左边最近的非空桶的max,求差值最大的即为最大差值(不能先找空桶找左右两侧,会存在19,空,30,49的情况)
队列(先进先出)、栈(后进先出)
用数组结构实现栈:
普通数组,加一个index,index代表新来一个数该放到哪个位置上。入栈index++,出栈index–
用数组结构实现队列:
普通数组,加一个start,加一个end,加一个size。start代表拿一个数,应该拿什么位置上的,end代表新加一个数加在什么位置上,size代表队列长度。
getMin函数
设计两个栈,第一个栈是普通栈,第二个栈是最小值栈。新进栈的>此时最小值,则第二个栈进一个此时最小值的数;新进栈的<此时最小值,则第二个栈进新进栈的这个数。
出栈:左边出一个,右边出一个
class MinStack(object):
def __init__(self):
"""
initialize your data structure here.
"""
self.stack = []
self.minstack = []
def push(self, x):
"""
:type x: int
:rtype: None
"""
self.stack.append(x)
if len(self.minstack) == 0:
self.minstack.append(x)
else:
min_num = min(x, self.minstack[len(self.minstack)-1])
self.minstack.append(min_num)
def pop(self):
"""
:rtype: None
"""
self.stack.pop()
self.minstack.pop()
def top(self):
"""
:rtype: int
"""
return self.stack[len(self.stack)-1]
def min(self):
"""
:rtype: int
"""
return self.minstack[len(self.minstack)-1]
# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(x)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.min()
用队列结构实现栈
用两个队列,data和help
- 入栈:新数只进data
- 出栈:data.size>1,就把所有数都放help里(除最后一个);把data剩下的那个弹出,把help拷贝给data,data改成help
class MyStack(object):
def __init__(self):
self.queue = []
self.help = []
def push(self, x):
"""
:type x: int
:rtype: None
"""
self.queue.append(x)
def pop(self):
"""
:rtype: int
"""
for i in range(len(self.queue)-1):
self.help.append(self.queue[i])
print_num = self.queue[len(self.queue)-1]
self.queue = self.help
self.help = []
return print_num
def top(self):
"""
:rtype: int
"""
return self.queue[len(self.queue)-1]
def empty(self):
"""
:rtype: bool
"""
if len(self.queue)==0:
return True
else:
return False
# Your MyStack object will be instantiated and called as such:
# obj = MyStack()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.top()
# param_4 = obj.empty()
用栈实现队列
两个栈,一个push,一个pop
- 新数只进push
- 当pop是空,则一次性将push倒入pop里面;pop里面要是有东西,就不能倒了
- 用户只从pop里取
class CQueue(object):
def __init__(self):
self.stack1 = [];
self.stack2 = [];
def appendTail(self, value):
"""
:type value: int
:rtype: None
"""
self.stack1.append(value)
def deleteHead(self):
"""
:rtype: int
"""
if self.stack2 == []:
while len(self.stack1)!=0:
self.stack2.append(self.stack1.pop())
if len(self.stack2)==0:
return -1;
else:
return self.stack2.pop()
# Your CQueue object will be instantiated and called as such:
# obj = CQueue()
# obj.appendTail(value)
# param_2 = obj.deleteHead()