首页 > 编程语言 > 详细

【面试-python】

时间:2021-07-13 15:00:32      阅读:12      评论:0      收藏:0      [点我收藏+]

1.使用Python实现删除list的重复元素

a = [3,4,5,2,3,4]
b = {}
b = b.fromkeys(a)
c = c.list(b.keys())
print(c)

2.python 如何进行内存管理的?

从三个方面来说,一对象的引用计数机制,二垃圾回收机制,三内存池机制

一、对象的引用计数机制
Python内部使用引用计数,来保持追踪内存中的对象,所有对象都有引用计数。

引用计数增加的情况:
1,一个对象分配一个新名称
2,将其放入一个容器中(如列表、元组或字典)

引用计数减少的情况:
1,使用del语句对对象别名显示的销毁
2,引用超出作用域或被重新赋值
sys.getrefcount( )函数可以获得对象的当前引用计数
多数情况下,引用计数比你猜测得要大得多。对于不可变数据(如数字和字符串),解释器会在程序的不同部分共享内存,以便节约内存。

二、垃圾回收
1,当一个对象的引用计数归零时,它将被垃圾收集机制处理掉。
2,当两个对象a和b相互引用时,del语句可以减少a和b的引用计数,并销毁用于引用底层对象的名称。然而由于每个对象都包含一个对其他对象的应用,因此引用计数不会归零,对象也不会销毁。(从而导致内存泄露)。为解决这一问题,解释器会定期执行一个循环检测器,搜索不可访问对象的循环并删除它们。

三、内存池机制
Python提供了对内存的垃圾收集机制,但是它将不用的内存放到内存池而不是返回给操作系统。
1,Pymalloc机制。为了加速Python的执行效率,Python引入了一个内存池机制,用于管理对小块内存的申请和释放。
2,Python中所有小于256个字节的对象都使用pymalloc实现的分配器,而大的对象则使用系统的malloc。
3,对于Python对象,如整数,浮点数和List,都有其独立的私有内存池,对象间不共享他们的内存池。也就是说如果你分配又释放了大量的整数,用于缓存这些整数的内存就不能再分配给浮点数。

3.Python里面如何拷贝一个对象?(赋值,浅拷贝,深拷贝的区别)

赋值(=),就是创建了对象的一个新的引用,修改其中任意一个变量都会影响到另一个。

浅拷贝:创建一个新的对象,但它包含的是对原始对象中包含项的引用(如果用引用的方式修改其中一个对象,另外一个也会修改改变){1,完全切片方法;2,工厂函数,如list();3,copy模块的copy()函数}

深拷贝:创建一个新的对象,并且递归的复制它所包含的对象(修改其中一个,另外一个不会改变){copy模块的deep.deepcopy()函数}

4.Python手写实现冒泡排序

冒泡排序的原理不难,假定要将被排序的数组R[1..n]从大到小垂直排列,每个数字R可以看作是重量为R.key的气泡。

根据轻气泡在上、重气泡在上的原则,从下往上扫描数组R:凡扫描到违反本原则的轻气泡,则使其向上"飘浮"。如此反复进行,直到最后任何两个气泡都是轻者在上、重者在下为止。
然后将所有气泡逆序,就实现了数组从小到大的排序。

步骤:
1 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2 对第0个到第n-1个数据做同样的工作。这时,最大的数就到了数组最后的位置上。
3 针对所有的元素重复以上的步骤,除了最后一个。
4 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

Python实现

def bubble_sort(arry):
    #获得数组的长度
    n = len(arry)                   
    for i in range(n):
        for j in range(1,n-i):
            #如果前者比后者大
            if  arry[j-1] > arry[j] :  
                #则交换两者     
                arry[j-1],arry[j] = arry[j],arry[j-1]      
    return arry

5. Python手写实现选择排序

选择排序(Selection sort)是一种简单直观的排序算法。

它的工作原理如下。首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小元素,然后放到排序序列第二个位置。以此类推,直到所有元素均排序完毕。

Python实现

def select_sort(ary):
    n = len(ary)
    for i in range(0,n):
        #最小元素下标标记
        min = i                             
        for j in range(i+1,n):
            if ary[j] < ary[min] :
                #找到最小值的下标
                min = j
        #交换两者                     
        ary[min],ary[i] = ary[i],ary[min]   
    return ary

6.请用Python手写实现插入排序

插入排序(Insertion Sort)的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

算法执行步骤:
1 从第一个元素开始,该元素可以认为已经被排序
2 取出下一个元素,在已经排序的元素序列中从后向前扫描
3 如果被扫描的元素(已排序)大于新元素,则将被扫描元素后移一位
4 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
5 将新元素插入到该位置后
6 重复步骤2~5



Python实现

def insert_sort(ary):
    n = len(ary)
    for i in range(1,n):
        if ary[i] < ary[i-1]:
            temp = ary[i]

            #待插入的下标
            index = i           
            #从i-1 循环到 0 (包括0)
            for j in range(i-1,-1,-1):  
                if ary[j] > temp :
                    ary[j+1] = ary[j]
                    #记录待插入下标
                    index = j   
                else :
                    break
            ary[index] = temp
    return ary

7.Python手写实现快速排序

1 从数列中挑出一个元素,称为 “基准”(pivot),
2 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
3 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

换言之
快速排序时基于分治模式处理的,
对一个典型子数组A[p...r]排序的分治过程为三个步骤:
1.分解:
A[p..r]被划分为俩个(可能空)的子数组A[p ..q-1]和A[q+1 ..r],使得
A[p ..q-1] 

8.请用Python手写实现堆排序

堆排序在 top K 问题中使用比较频繁。堆排序是采用二叉堆的数据结构来实现的,虽然实质上还是一维数组。二叉堆是一个近似完全二叉树 。

二叉堆具有以下性质:

父节点的键值总是大于或等于(小于或等于)任何一个子节点的键值。
每个节点的左右子树都是一个二叉堆(都是最大堆或最小堆)。

步骤:
1 构造最大堆(Build_Max_Heap):若数组下标范围为0~n,考虑到单独一个元素是大根堆,则从下标n/2开始的元素均为大根堆。于是只要从n/2-1开始,向前依次构造大根堆,这样就能保证,构造到某个节点时,它的左右子树都已经是大根堆。

2 堆排序(HeapSort):由于堆是用数组模拟的。得到一个大根堆后,数组内部并不是有序的。因此需要将堆化数组有序化。思想是移除根节点,并做最大堆调整的递归运算。第一次将heap[0]与heap[n-1]交换,再对heap[0...n-2]做最大堆调整。第二次将heap[0]与heap[n-2]交换,再对heap[0...n-3]做最大堆调整。重复该操作直至heap[0]和heap[1]交换。由于每次都是将最大的数并入到后面的有序区间,故操作完后整个数组就是有序的了。

3 最大堆调整(Max_Heapify):该方法是提供给上述两个过程调用的。目的是将堆的末端子节点作调整,使得子节点永远小于父节点。



Python实现
def heap_sort(ary) :
    n = len(ary)
    #最后一个非叶子节点
    first = int(n/2-1)       
    #构造大根堆
    for start in range(first,-1,-1) :     
        max_heapify(ary,start,n-1)

    #堆排,将大根堆转换成有序数组
    for end in range(n-1,0,-1):           
        ary[end],ary[0] = ary[0],ary[end]
        max_heapify(ary,0,end-1)
    return ary

#最大堆调整:将堆的末端子节点作调整,使得子节点永远小于父节点
#start为当前需要调整最大堆的位置,end为调整边界
def max_heapify(ary,start,end):
    root = start
    while True :
        #调整节点的子节点
        child = root*2 +1               
        if child > end : break
        if child+1 

9,请用Python手写实现归并排序

归并排序是采用分治法的一个非常典型的应用。归并排序的思想就是先递归分解数组,再合并数组。

先考虑合并两个有序数组,基本思路是比较两个数组的最前面的数,谁小就先取谁,取了后相应的指针就往后移一位。然后再比较,直至一个数组为空,最后把另一个数组的剩余部分复制过来即可。

再考虑递归分解,基本思路是将数组分解成left和right,如果这两个数组内部数据是有序的,那么就可以用上面合并数组的方法将这两个数组合并排序。如何让这两个数组内部是有序的?可以再二分,直至分解出的小组只含有一个元素时为止,此时认为该小组内部已有序。然后合并排序相邻二个小组即可。

10.无序数组第k 大的元素

思路:快排中partition 思想:
对于某个索引j,nums[j] 经过partition 操作:
nums[left] 到nums[j - 1] 中的所有元素都不大于nums[j];
nums[j + 1] 到nums[right] 中的所有元素都不小于nums[j]
即nums[j]元素的位置是排序好了的,我们判断索引j 是否满足条件,若满足则直接返回结果,若
不满足我只需要遍历左序列或者右序列,直至满足要求;无需对整个序列进行排序,所以减少了计算
量;
1. class Solution:
2. def findKthLargest(self, nums: List[int], k: int) -> int:
3. # 快排中分治思想
4. n = len(nums)
5. left, right, target = 0, n-1, n - k
6. while True:
7. pivote = self.getPivote(nums, left, right)
8. if pivote == target: return nums[target]
9. # 只需遍历pivote 左边或者右边减少计算量
10. elif pivote < target: left = pivote + 1
11. elif pivote > target: right = pivote - 1
12.
13. # 分治思想pivote 左边都是不大于pivote 的数,右边是不小于pivote 的数
14. def getPivote(self, nums, left, right):
15. pivote = random.randint(left, right)
16. nums[left], nums[pivote] = nums[pivote], nums[left]
17. pivote = nums[left]
18. # 双指针法
19. while left < right:
20. while nums[right] >= pivote and left < right: right -= 1
21. nums[left] = nums[right]
22. while nums[left] <= pivote and left < right: left += 1
23. nums[right] = nums[left]
24. nums[left] = pivote
25. return left

 


 

【面试-python】

原文:https://www.cnblogs.com/pergrand/p/15005731.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!