栈和队列基础:
- 定义:存放数据的线性表。
- 操作:入栈/队列、出栈/队列、判断满/空。
- 空间复杂度:O(n)
- 单次操作时间复杂度:O(1)
- 区别:栈是先进后出(FILO, First In Last Out),队列是先进先出(FIFO, First In First Out),具体如下图:
栈和队列的实现:
- 数组和链表皆可(线性表)
- 指针:(辅助变量),①栈顶/底指针,②队头/尾指针
- 关键:出入元素的同时移动指针
栈的应用:括号匹配检测:
- 括号、引号等符号是成对出现的,必须相互匹配,设计一个算法,自动检测输入的字符串中的括号是否匹配,比如:
- 从左向右扫描字符串:
- 不匹配进栈:
- 匹配后出栈:
参考:https://www.cnblogs.com/qiaojushuang/p/9048675.html
LeetCode例题:
给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: k[encoded_string]
,表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。
你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a
或 2[4]
的输入。
示例:
s = "3[a]2[bc]", 返回 "aaabcbc".
s = "3[a2[c]]", 返回 "accaccacc".
s = "2[abc]3[cd]ef", 返回 "abcabccdcdcdef"
解法:
-
思路:使用两个栈分别存储数字和字母
-
注意1: 数字是多位的话,要处理后入数字栈
-
注意2: 出栈时过程中产生的组合后的字符串要继续入字母栈
-
注意3: 记得字母出栈的时候字符要逆序组合成字符串
- 注意4: 不用字符串而用字母栈的原因是字符串的 join 效率会比字符串加法高一些
class Solution(object):
def decodeString( s):
"""
:type s: str
:rtype: str
"""
nums, chars = [], []
i, length = 0, len(s)
while i < length:
j = i + 1
if s[i].isdigit():
num = int(s[i])
while j < length:
if s[j].isdigit(): #是否只由数字构成,是返回True
num = num * 10 + int(s[j])
j += 1
else:
break
nums.append(num)
elif s[i] == '[' or s[i].isalpha():
chars.append(s[i])
else:
t, tmpc = chars.pop(), []
while t != '[':
tmpc.append(t)
#默认移除列表最后一个元素,并返回最后一个元素,这里是从栈中弹出最后一个字符并删除,直至’[‘
t = chars.pop()
tchars = nums.pop() * ''.join(tmpc[::-1])
chars.append(tchars)
i = j
return ''.join(chars)
另一种解法:
class Solution:
def decodeString(self, s):
"""
:type s: str
:rtype: str
"""
stack = []
num = 0
string = ''
for i in s:
if i == '[':
stack.append(string)
stack.append(num)
string = ''
num = 0
elif i == ']':
n = stack.pop()
prestring = stack.pop()
string = prestring+n*string
elif i.isdigit():
num = 10*num + int(i)
else:
string += i
return string
设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。
- push(x) -- 将元素 x 推入栈中。
- pop() -- 删除栈顶的元素。
- top() -- 获取栈顶元素。
- getMin() -- 检索栈中的最小元素。
示例:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.getMin(); --> 返回 -2
解法:采用双栈的方式,一个用于记录数值,一个用于记录最小值,当x与最小值相等的情况也要考虑进去
class MinStack:
def __init__(self):
"""
initialize your data structure here.
"""
self.l = []
self.min = []
def push(self, x):
"""
:type x: int
:rtype: void
"""
self.l.append(x)
if self.min == []:
self.min.append(x)
else:
if self.min[-1]>x:
self.min.append(x)
else:
self.min.append(self.min[-1])
def pop(self):
"""
:rtype: void
"""
self.l.pop()
self.min.pop()
def top(self):
"""
:rtype: int
"""
return self.l[-1]
def getMin(self):
"""
:rtype: int
"""
return self.min[-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.getMin()
哈希表基础:
- 定义:存放数据的集合
- 操作:根据(Key, Value)进行,插入,查找,删除(可以没有)
- 空间复杂度:O(m)
- 单次操作时间复杂度:O(1)
- 本质:Key的索引
例题:
- 给出n个[0, m)范围内的整数,去重
- 快速排序:期望时间复杂度O(nlogn),附加空间复杂度O(1)
- 计数(基数)排序:时间复杂度O(n + m) 超越比较排序下限,附加空间复杂度O(m)
哈希表实现:
- 处理冲突(Key, Value):开放地址法(数组)和拉链法(数组+链表)
- 负载率= 已有元素大小/ 存储散列大小
应用:
- 字符串匹配:设字符串A=‘12314123’,求‘123’在A中出现的次数?不会写KMP又想要O(n)肿么办? ①Key相等时Value有可能不同;
②每次比较Value也是不小的开销,特别是Value可能很大;
③不考虑Value将产生错误率(错误率换时间);
④多重哈希(降低错误率);
哈希表删除问题:
- 能否直接删除哈希表中的元素?
- 考虑两种不同的实现方式
- 硬删除vs 软删除
LeetCode例题:
给定一个未排序的整数数组,找出最长连续序列的长度。
要求算法的时间复杂度为 O(n)。
示例:
输入: [100, 4, 200, 1, 3, 2]
输出: 4
解释: 最长连续序列是 [1, 2, 3, 4]。它的长度为 4。
解法:
利用哈希表解决,题目要求 O(n) 复杂度。
- 用哈希表存储每个端点值对应连续区间的长度
- 若数已在哈希表中:跳过不做处理
- 若是新数加入:
- 取出其左右相邻数已有的连续区间长度 left 和 right
- 计算当前数的区间长度为:cur_length = left + right + 1
- 根据 cur_length 更新最大长度 max_length 的值
- 更新区间两端点的长度值
class Solution:
def longestConsecutive(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
d = {}
max_len = 0
for num in nums:
if num not in d:
left = d.get(num-1,0)
right = d.get(num+1,0)
cur_len = 1+left+right
if cur_len > max_len:
max_len = cur_len
d[num]=cur_len
d[num-left]=cur_len
d[num+right]=cur_len
return max_len
布隆过滤器基础:
定义:是判断一个字符串是否出现过的数据结构,相比哈希表是空间换时间,布隆过滤器是错误率换空间。
实现:
- 由01的数字序列构成
- 插入:多个不同hash函数计算Key,置1
- 查找:有一个为0不可能存在,全为1可能存在
- 空间:
优缺点:
- 优点:时间和空间、多个hash函数可以并行、交差并(位运算)
- 缺点:错误率随负载率上升而上升、无法删除
To be continue......