将文件系统中相互依赖的文件打包到一起,不依赖的单独打包。给出一个文件系统中的所求文件名以及一些文件的依赖关系。
输出:
需要打包的数量
example
["fileA", "fileB", "fileC", "fileD", "fileE"],[ ["fileA", "fileB"], ["fileB", "fileC"], ["fileD", "fileE"]]
输出:
2
思路:并查集,对每一个连通的子图,选出一个节点,作为代表。一个为filenames 的list,另一个list为其父节点list。利用relations更新父节点list后不断迭代至父节点list不再变化则退出。
代码
a= ["fileA", "fileB", "fileC", "fileD", "fileE"]
b = [ ["fileA", "fileB"], ["fileB", "fileC"], ["fileD", "fileE"]]
import copy
class Solution:
def split_package(self , filenames , relations ):
# write code here
# 初始root,每个节点的父节点就是其本身
root_name = [i for i in filenames]
# 根据relations 更改其父节点
for re in relations:
root,node = re
index = filenames.index(node)
root_name[index] = root
# 将同一群下的文件的父节点变为一致
print(root_name)
while 1:
t = copy.deepcopy(root_name)
for i in range(len(root_name)):
node = root_name[i]
index = filenames.index(node)
root_name[i] = root_name[index]
# 对比list交换前后是否发生变化,未发生则终止while
if root_name==t:
break
print(root_name)
return len(set(root_name))
h = Solution()
m = h.split_package(a,b)
m
results:
['fileA', 'fileA', 'fileB', 'fileD', 'fileD']
['fileA', 'fileA', 'fileA', 'fileD', 'fileD']
2
reference
1.并查集原理及Python实现,朋友圈个数问题
主要是这张图很棒(根据这张图就就很明了该怎么做了,图片来源于上述参考链接):
题目描述:
数组交换过后,相对位置发生变换的对数。发生交换的对数为偶数输出2,为奇数输出1。
输入数据:数组长度,位置交换的list
example:
5,[[2,4],[1,4],[0,3],[0,3]]
初始数组为[5,4,3,2,1],则交换后的数组为[5,3,1,2,4]
由此可知,相对位置发生变化的有4对,分别是(3,4),(1,2),(1,4),(2,4)
代码:
**版本1:**逆序对的朴素算法即暴力法,针对每个元素,遍历该元素后续的所有元素查找计算相当该元素的逆序对。但是时间复杂度为O(n^2),在提交的时候也超时了。
class Solution:
def determine_virus_type(self , size , swap_indexes ):
# write code here
count = 0
raw_list = [i for i in range(size,0,-1)]
for index in swap_indexes:
i ,j = index
raw_list[i],raw_list[j] = raw_list[j],raw_list[i]
count = self.get_choice_2(raw_list)
print(count)
if count%2:
return 1
else:
return 2
def get_choice_2(self,m):
h = 0
for i in range(len(m)):
for j in m[i+1:]:
if m[i]<j:
h += 1
return h
y = Solution()
size = 5
hi = [[2,4],[1,4],[0,3],[0,3]]
y.determine_virus_type(size,hi)
result:
最终通过了47%的案例,然后超时了,还有更优的方法,我比较函数(即函数get_choice_2)应该还可以优化。
版本2(最终版本):
采用归并排序的方法,将原问题划分成两个规模只有一半的子问题,分别求出各自的逆序对个数,最后加上两段之间的逆序对数,即是全部的逆序对数。时间复杂度可以变为O(n)。
# 采用归并排序的方法,将原问题划分成两个规模只有一半的子问题,
# 分别求出各自的逆序对个数,最后加上两段之间的逆序对数,即是全部的逆序对数。时间复杂度可以变为O(n)。
class Solution:
def __init__(self):
self.count = 0
def determine_virus_type(self , size , swap_indexes ):
# write code here
count = 0
raw_list = [i for i in range(size,0,-1)]
for index in swap_indexes:
i ,j = index
raw_list[i],raw_list[j] = raw_list[j],raw_list[i]
count = self.mergeSort(raw_list)
print(count)
print(self.count)
if self.count%2:
return 1
else:
return 2
# 归并排序算法
def mergeSort(self,arr):
import math
if(len(arr)<2):
return arr
middle = math.floor(len(arr)/2)
left, right = arr[0:middle], arr[middle:]
return self.merge(self.mergeSort(left), self.mergeSort(right))
def merge(self,left,right):
result = []
while left and right:
if left[0] >= right[0]:
result.append(left.pop(0))
else:
self.count += 1
result.append(right.pop(0));
while left:
result.append(left.pop(0))
while right:
result.append(right.pop(0));
return result
y = Solution()
size = 5
hi = [[2,4],[1,4],[0,3],[0,3]]
y.determine_virus_type(size,hi)