zoukankan      html  css  js  c++  java
  • 撒地方大神

    https://pythonav.com/index/

    1.对列表进行过滤
    li = [{"id":3}, {"id":1}, {"id":5}]
    filter_list = filter(lambda item: item.get("id")> 3, li)
    for item in filter_list:
        print(item.get("id"))
    	
    	
    2.写一个类似于字段用法的类
    class RepeatDic(object):
        def __init__(self):
            self.__li = []
    
        def __getitem__(self, item):
            filter_items = filter(lambda x: x[0] == item, self.__li)
            return [i[1] for i in filter_items]
    
        def __setitem__(self, key, value):
            self.__li.append((key, value))
    
        def __delitem__(self, key):
            self.__li = [item for item in self.__li if item[0] != key]
    
    
    obj = RepeatDic()
    
    obj["haha"] = "heihei"
    print(obj["haha"])
    obj["haha"] = "hehe"
    print(obj["haha"])
    del obj["haha"]
    print(obj["haha"])
    
    3.二分法查找
    li = range(0, 30,  2)
    def mid_find(li, left, right, val):
        if right >= left:
            mid = (left + right) // 2
            if li[mid] > val:
                right = mid - 1
                return mid_find(li, left, right, val)
            elif li[mid] < val:
                left = mid + 1
                return mid_find(li, left, right, val)
            else:
                return mid
        else:
            return None
    
    要点:左右边界移动,碰头时终止循环
    def mid_find2(li, val):
        left = 0
        right = len(li) - 1
        while left <= right:
            mid = (left + right) // 2
            if li[mid] > val:
                right = mid - 1
            elif li[mid] < val:
                left = mid + 1
            else:
                return mid
    
    ret = mid_find2(li, 120)
    print(ret)
    
    
    
    4.一个大小为100G的文件etl_log.txt, 要读取文件中的内容, 写出具体过程代码?
    要点:指定字节数读,弄成一个生成器
    def readFile(file_path):
        with open(file_path, "r", encoding="utf-8") as f:
            while 1:
                block = f.read(1024)
                if block:
                    yield block
                else:
                    return
    
    it = readFile("run.py")
    for item in it:
        print(item)
    
    5.写一个上下文管理类
    class NewFile(object):
        def __init__(self, path):
            self.path = path
            self.__file_handler  = None
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            if self.__file_handler:
                print("close")
                self.__file_handler.close()
    
        def __enter__(self):
            self.__file_handler = open(self.path, 'r', encoding="utf-8")
            print("open")
            return self.__file_handler
    
    with NewFile("run.py") as f:
        print(f.read())
    	
    6.冒泡排序
    要点:内层循环时时比较,时时交换
    def bubble_sort(li):
        for i in range(len(li)-1):  #第i趟
            exchange = False
            for j in range(len(li)-i-1):
                if li[j] > li[j+1]:
                    li[j], li[j+1] = li[j+1], li[j]
                    exchange = True
            if not exchange:  #这里属于优化,也就是如果这次循环中没有发生一次交换,那么此时已经是有序的
                return
     
     
    li = list(range(10000))
    random.shuffle(li)
     
    bubble_sort(li)
    
    7.后序遍历,我称之为深度优先遍历
    要点:深度优先 一般都可以用栈来实现,需要确定pop的条件,以及做好pop后的标识
    # 非递归方式
    def find(root_node):
        li = []
        stack = []
        stack.append([root_node,[root_node.lchild, root_node.rchild]])
        while len(stack) > 0:
            currNodeItem = stack[-1]
            if currNodeItem[1][0] is None and currNodeItem[1][1] is None:
                #当前是叶子节点,输出到列表
                li.append(currNodeItem[0].data)
                # 标志父亲节点这个儿子已经输出
                if len(stack) > 1: #考虑如果root节点就是叶子节点
                    parentNodeItem = stack[-2]
                    childs = parentNodeItem[1]
                    for index,child in enumerate(childs):
                        if currNodeItem[0] == child:
                            childs[index] = None
                            break
                # 把栈里的数据移除掉
                stack.pop()
            elif currNodeItem[1][0] is not None: #有左儿子,添加左儿子
                lchild = currNodeItem[1][0]
                stack.append([lchild, [lchild.lchild, lchild.rchild]])
            else: # 没有左儿子情况下,有右儿子,添加右儿子
                rchild = currNodeItem[1][1]
                stack.append([rchild, [rchild.lchild, rchild.rchild]])
    
        return ','.join(li)
    
    print(find(root)) #B,D,C,A,F,G,E  对应后序遍历
    
    # 递归遍历
    def post_order(root):
        if root:
            post_order(root.lchild)
            post_order(root.rchild)
            print(root.data, end=',')
    
    8.广度优先,层级遍历
    要点:使用 队列,一般出队,一边把儿子入队
    def find(root):
        from collections import deque
        que = deque()
        que.append(root)
        while len(que) > 0:
            currentNode = que.popleft()
            print(currentNode.data, end=',')
            if currentNode.lchild:
                que.append(currentNode.lchild)
            if currentNode.rchild:
                que.append(currentNode.rchild)
    
    find(root)
    
    9.选择排序
    # 选择排序,你就记成 选择性最小下标来排序
    # 每次循环取最开始那个值的索引 作为最小值索引
    def select_sort(li):
        for i in range(len(li)-1): #第几趟
            min_loc = i
            change_flag = False
            for j in range(i+1, len(li)):
                if li[j] < li[min_loc]:
                    change_flag = True
                    min_loc = j
            if not change_flag:
                return
            li[i], li[min_loc] = li[min_loc], li[i]
    
    li = [2,5,4,58,1,175,1,4]
    select_sort(li)
    print(li)
    
    
    10.插入排序
    #记录手里牌的下标和抓到牌的值,利用冒泡的方式去把抓到牌往左冒
    #刚开始手里有一张牌,
    def insert_sort(li):
        for i in range(1, len(li)): #摸到牌的下标
            tmp = li[i]
            j = i - 1 #手牌下标
            while j >= 0 and tmp < li[j]:
                li[j+1] = li[j]
                j-=1
            li[j+1] = tmp
    
    11.快速排序
    #快排是分而治之的思想
    # 要点:递归终止条件就是上下边界碰头, 分区时维护两个指标指针,一个追整个数据,一个追踪小于的标志的值的个数
    # 标志值可以去最后的一位数, 两指针出现不相等时,要把大的值交换到 靠右边,  在最后要把标志值交换一下
    def quickSort(li, p, r):
        if p>=r:return
        q = partition(li,p,r)
        quickSort(li,p,q-1)
        quickSort(li,q+1,r)
    
    def partition(li, p, r):
        '''
    
        :param li: 数据列表
        :param p: 数据区间的上标
        :param r: 数据区间的下标
        :return:
        '''
        pivot = li[r] #定义分区点为最后位置的元素
        i = p # 定义 i 指针, 用于追踪小于标志值
        j = p
        while j <= r: # 循环遍历 j 指针
            if li[j] < pivot:
                if j != i: # 如果出现i j不相等,说明比标志值的大的值出现,开始实时把这个值交换到右边
                    swap(li, i, j)
                i+=1
            j+=1
        swap(li, i, r) #当p和r碰头时,循环终止,把标志值交换到  小于标志值的分界处
        return i
    
    def swap(li, i, j):
        li[i], li[j] = li[j],li[i]
    
    li = [42,4,4651,47,785,2,7,2,485]
    quickSort(li,0, len(li)-1)
    print(li)
    
    
    12.Python 一个数如果恰好等于它的因子之和,这个数就称为"完数"。例如6=1+2+3.编程找出1000以内的所有完数
    for i in range(2, 1001):
        m = []
        for j in range(1,i):
            if i % j == 0:
                m.append(j)
        if sum(m) == i:
            print(i)
    
    13.单例模式
    class singleton(object):
        __instance = None
    
        def __new__(cls, *args, **kwargs):
            if cls.__instance is None:
                cls.__instance = object.__new__(cls, *args, **kwargs)
            return cls.__instance
    
    a = singleton()
    b  = singleton()
    print(id(a), id(b))
    
    14.99乘法表
    for row in range(1,10):
        for col in range(1, row+1):
            print("%s * %s = %s"%(col, row, col*row), end="  ")
        print()
    
    15.看代码 写结果
    https://zhuanlan.zhihu.com/p/23582996?refer=passer
    
    16.类继承查找循环
    要点:python2的经典类和新式类(继承了object) 都是按照深度优先查找类,只不过在查过中,有个细节不一样就是
    遇到 重复类的保留情况,经典类是去掉后面的保留第一个,而新式类则是去掉前面的保留最后一个
    python3的C3 MRO算法有点复杂,这个我没怎么去了解
    一般5到6个类的继承关系我直接去看,一旦比这复杂,我会直接调用__mro__属性来查看
    class A(object):
        def __init__(self):
            print("enter A")
            super(A, self).__init__()
            print("leave A")
    
    class B(object):
        def __init__(self):
            print("enter B")
            super(B, self).__init__()
            print("leave B")
    
    class C(A):
        def __init__(self):
            print("enter C")
            super(C, self).__init__()
            print("leave C")
    
    class D(A):
        def __init__(self):
            print("enter D")
            super(D, self).__init__()
            print("leave D")
    
    class E(B,C):
        def __init__(self):
            print("enter E")
            super(E, self).__init__()
            print("leave E")
    
    class F(E,D):
        def __init__(self):
            print("enter F")
            super(F, self).__init__()
            print("leave F")
    
    # print(F.__mro__)
    
    16.二叉树的最大深度
    from collections import deque
    class Solution(object):
        def preorderTraversal(self, root):
            """
            :type root: TreeNode
            :rtype: List[int]
            """
            if not root: return 0
    
            queue = deque()
            queue.append(root)
            depth = 0
    
            while queue:
                size = len(queue)
                for i in range(size):
                    curr = queue.popleft()
                    if curr.left:
                        queue.append(curr.left)
                    if curr.right:
                        queue.append(curr.right)
                depth += 1
            return depth
    
    obj = Solution()
    ret = obj.preorderTraversal(e)
    print(ret)
    

    套路系列:
        刷二叉树

        1.动态规划
            场景:动态规划问题的一般形式就是求最值
            特点:本质就是穷举,存在重叠子问题,可以通过备忘录和DPtable来优化穷举过程
                并且一定存在最优子结构,怎么穷举,就需要列出状态转移方程
            动态规划三要素:重叠子问题,最优子结构,状态转移方程(这步是最难的)
            过程:明确「状态」 -> 定义 dp 数组/函数的含义 -> 明确「选择」-> 明确 base case
                通过DP table实现自底向上, 备忘录、DP table 就是在追求“如何聪明地穷举”。⽤空间换时间的思路
            
            先确定「状态」,也就是原问题和⼦问题中变化的变量。由于硬币数量⽆
                限,所以唯⼀的状态就是⽬标⾦额 amount 。
            然后确定 dp 函数的定义:当前的⽬标⾦额是 n ,⾄少需要 dp(n) 个硬
                币凑出该⾦额
            然后确定「选择」并择优,也就是对于每个状态,可以做出什么选择改变当
                前状态。具体到这个问题,⽆论当的⽬标⾦额是多少,选择就是从⾯额列表
                coins 中选择⼀个硬币,然后⽬标⾦额就会减少
            最后明确 base case,显然⽬标⾦额为 0 时,所需硬币数量为 0;当⽬标⾦额
                ⼩于 0 时,⽆解,返回 -1
            
            # 伪码框架
            def coinChange(coins: List[int], amount: int):
            # 定义:要凑出⾦额 n,⾄少要 dp(n) 个硬币
            def dp(n):
            # 做选择,选择需要硬币最少的那个结果
            for coin in coins:
            res = min(res, 1 + dp(n - coin))
            return res
            # 我们要求的问题是 dp(amount)
            return dp(amount)
            
            
            int coinChange(vector<int>& coins, int amount) {
                // 数组⼤⼩为 amount + 1,初始值也为 amount + 1
                vector<int> dp(amount + 1, amount + 1);
                // base case
                dp[0] = 0;
                for (int i = 0; i < dp.size(); i++) {
                    // 内层 for 在求所有⼦问题 + 1 的最⼩值
                    for (int coin : coins) {
                        // ⼦问题⽆解,跳过
                        if (i - coin < 0) continue;
                        dp[i] = min(dp[i], 1 + dp[i - coin]);
                    }
                }
                return (dp[amount] == amount + 1) ? -1 : dp[amount];
            }
            
        2.回溯算法(DFS)
            解决⼀个回溯问题(一般常见全排列问题,纯暴力穷举),实际上就是⼀个决策树的遍历过程。你只需要思考 3 个问题:
            1、路径:也就是已经做出的选择。
            2、选择列表:也就是你当前可以做的选择。
            3、结束条件:也就是到达决策树底层,⽆法再做选择的条件。
        
            # 多叉树的前序遍历和后序遍历
            result = []
            def backtrack(路径, 选择列表):
                if 满⾜结束条件:
                    result.add(路径)
                    return
                for 选择 in 选择列表:
                    做选择
                    backtrack(路径, 选择列表)
                    撤销选择
            
            List<List<Integer>> res = new LinkedList<>();
            /* 主函数,输⼊⼀组不重复的数字,返回它们的全排列 */
            List<List<Integer>> permute(int[] nums) {
                // 记录「路径」
                LinkedList<Integer> track = new LinkedList<>();
                backtrack(nums, track);
                return res;
            }
            
            // 路径:记录在 track 中
            // 选择列表:nums 中不存在于 track 的那些元素
            // 结束条件:nums 中的元素全都在 track 中出现
            void backtrack(int[] nums, LinkedList<Integer> track) {
                // 触发结束条件
                if (track.size() == nums.length) {
                    res.add(new LinkedList(track));
                    return;
                }
                
                for (int i = 0; i < nums.length; i++) {
                    // 排除不合法的选择
                    if (track.contains(nums[i]))
                        continue;
                    // 做选择
                    track.add(nums[i]);
                    // 进⼊下⼀层决策树
                    backtrack(nums, track);
                    // 取消选择
                    track.removeLast();
                }
            }
        
        3.BFS算法
            场景:抽象成图,比如求最短路径(二叉树的最小高度,打开密码锁的最少步数)
            一般是用队列维护,空间复杂度比DFS复杂,一般还需维护一个数据集,防止走回头路
            
            框架:
            // 计算从起点 start 到终点 target 的最近距离
            int BFS(Node start, Node target) {
                Queue<Node> q; // 核⼼数据结构
                Set<Node> visited; // 避免⾛回头路
                q.offer(start); // 将起点加⼊队列
                visited.add(start);
                int step = 0; // 记录扩散的步数
                while (q not empty) {
                    int sz = q.size();
                    /* 将当前队列中的所有节点向四周扩散 */
                    for (int i = 0; i < sz; i++) {
                        Node cur = q.poll();
                        /* 划重点:这⾥判断是否到达终点 */
                        if (cur is target)
                            return step;
                        /* 将 cur 的相邻节点加⼊队列 */
                        for (Node x : cur.adj())
                            if (x not in visited) {
                                q.offer(x);
                                visited.add(x);
                            }
                    }
                    /* 划重点:更新步数在这⾥ */
                    step++;
                }
            }
        
        4.滑动窗口算法(双指针问题)
            场景:子串,子数组问题
            维护⼀个窗⼝,不断滑动,然后更新答案
            
            框架:
            int left = 0, right = 0;
            while (right < s.size()) {`
                // 增⼤窗⼝
                window.add(s[right]);
                right++;
                while (window needs shrink) {
                    // 缩⼩窗⼝
                    window.remove(s[left]);
                    left++;
                }
            }
            
        5.二分法查找

     

    哈哈

  • 相关阅读:
    IIS部署Asp.Net Core 项目运行时报错,处理程序“aspNetCore”在其模块列表中有一个错误模块“AspNetCoreModuleV2"
    Linux Mysql5.7.22安装
    Nginx初体验
    asp.net core Csc任务不支持SharedCompilationId参数,请确认改参数存在于此任务中,并且是可设置的公共实例属性
    【Node.js 】Express框架
    【Node.js】 初体验
    Mongodb 配置
    【C#】Windows服务守护并发送邮件通知
    新建【Git】仓库后给使用者授权
    Git提交修改的代码出现提交不上去
  • 原文地址:https://www.cnblogs.com/xinsiwei18/p/13488721.html
Copyright © 2011-2022 走看看