网易提前批笔试题2020

网易提前批笔试2020

一、题目1

将文件系统中相互依赖的文件打包到一起,不依赖的单独打包。给出一个文件系统中的所求文件名以及一些文件的依赖关系。
输出:
需要打包的数量

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实现,朋友圈个数问题

主要是这张图很棒(根据这张图就就很明了该怎么做了,图片来源于上述参考链接):网易提前批笔试题2020_第1张图片

二、题目2

题目描述:
数组交换过后,相对位置发生变换的对数。发生交换的对数为偶数输出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)

你可能感兴趣的:(面试,python,数据结构,算法,leetcode)