- 很简单的一道题,给A,B两个数组,输出出现在A中而没有出现在B中的元素,输出元素前后顺序不变,遍历一遍就OK了。
- 反转链表的第M个至第N个元素
- 0-1 背包
第一题很简单,直接遍历就行,在笔试的时候,我没有检查输入= =!
def fun(list_A,list_B):
if len(list_A) < 1:return []
if len(list_B) < 1:return list_A
res = []
for item in list_A:
if item not in list_B:
res.append(item)
return res
性能分析:空间复杂度 O ( n ) O(n) O(n),时间复杂度 O ( n 2 ) O(n^2) O(n2)。
这一题其实并不难,我在笔试的时候觉得比较坑的是VIVO的python调试只显示你的结果和答案是不是一致,而不显示你的输出,因此我当时边界条件没有确定好,所以这道题跪了。。。
class Node:
next = None
val = None
def reversed_m_to_n(pHead,m,n):
assert n>=m
if pHead == None:return pHead
pNode = pHead
for i in range(m-2): # 这个m-2在笔试的时候写成了m-1。。。
# 如果m超出了链表的长度,返回空
if pNode.next == None:return None
pNode = pNode.next
# 第m个节点的前一个节点,记录这个节点方便后面把它的next设成第n个节点
m_minus_1 = pNode
pNode = pNode.next
# 记录第m个节点,后面把它的next设置成第n+1个节点
mth_Node = pNode
pPrev = pNode
pNode = pNode.next
pNext = pNode.next
for i in range(n-m):
pNode.next = pPrev
pPrev = pNode
pNode = pNext
# 如果n超过了链表长度,直接打断,并反转第m个至链表尾
if pNode.next == None:
break
pNext = pNode.next
# 此时pNode就是第n+1个节点了,pPrev是第n个节点
m_minus_1.next = pPrev
mth_Node.next = pNode
return pHead
def create_liked_list(string):
pHead = Node()
length = len(string)
if length < 1:raise Exception('please enter an non-empty string!')
# 这一步必须有,因为要返回head,不能丢失head
pNode = pHead
for i in range(length):
pNode.val = string[i]
pNode.next = Node()
pNode = pNode.next
return pHead
def print_linked_list(pHead):
# if pHead == None:
# return
while(pHead != None and pHead.next != None):
print(pHead.val,end='\t')
pHead = pHead.next
print()
上面这个代码测试,已测试以下情形
- 正常情况 正常输出现象
- n>m>链表长度 返回空,输出空
- n>链表长度>m 返回第m个至链表尾的反转
m = 4
n = 7
head = create_liked_list('89743251')
print('raw linked list:')
print_linked_list(head)
head = reversed_m_to_n(head,m,n)
print("reversed %dth to %dth element's linked list:"%(m,n))
print_linked_list(head)
性能分析:空间复杂度 O ( 1 ) O(1) O(1),时间复杂度 O ( n ) O(n) O(n)。
第三题换了个说法,但还是0-1背包问题,具体的描述记不太清楚了,就用0-1背包的变量设置直接上动态规划。
先写二维数组的解法:
def knapsack(C,value_list,weight_list):
'''
C : 背包容量
value_list : 商品价值列表
weight_list :商品重量列表
'''
n = len(value_list)
dp = [[0 for i in range(C+1)] for j in range(n+1)]
for i in range(1,n+1):
for j in range(1,C+1):
# 如果当前背包容量还够装下当前商品
if j >= weight_list[i-1]:
dp[i][j] = max(dp[i-1][j],dp[i-1][j-weight_list[i-1]]+value_list[i-1])
else:
dp[i][j] = dp[i-1][j]
return dp[n][C]
性能分析:空间复杂度 O ( n 2 ) O(n^2) O(n2),时间复杂度 O ( n 2 ) O(n^2) O(n2)。
得到dp矩阵后,可以回溯获取选择了哪些个商品,由dp矩阵的特性可知:
def look_back(dp,value_list,weight_list):
i = len(dp) - 1
j = len(dp[0]) - 1
res = []
while (i>0):
if dp[i][j] == dp[i-1][j]:
i -= 1
elif dp[i][j] == dp[i-1][j-weight_list[i-1]] + value_list[i-1]:
res.append(i)
j = j-weight_list[i-1]
i -= 1
return(res)
分析上述过程,其实dp可以使用1维矩阵来表示,从而降低空间复杂度。
在计算dp矩阵时,每次只使用上一行的数据,故每次计算时,除保存当前行数据外,再额外保存上一行数据即可。
def knapsack_ON(C,value_list,weight_list):
'''
C : 背包容量
value_list : 商品价值列表
weight_list :商品重量列表
'''
n = len(value_list)
current_row = [0 for i in range(C+1)]
last_row = [0 for i in range(C+1)]
for i in range(1,n+1):
for j in range(1,C+1):
# 如果当前背包容量还够装下当前商品
if j >= weight_list[i-1]:
current_row[j] = max(last_row[j],last_row[j-weight_list[i-1]]+value_list[i-1])
else:
current_row[j] = last_row[j]
# 此处注意不要直接用last_row = current_row,因为这样是浅复制
last_row = [item for item in current_row]
return current_row[-1]