• 算法面试题


    1、有a,b,c,d四个人,其中一个是小偷;a说我不是小偷,b说一定是c,c说小偷是d,d说c在胡说八道;
    其中三个人说的真话,一个人说的假话,请用编程得出谁是小偷

    def thief_is():
        for thief in ('a', 'b', 'c', 'd'):
            sum = ('a' != thief) + (thief == 'c') + 
                (thief == 'd') + (thief != 'd')
            if sum == 3:
                print("thief is %s"%thief)
    thief_is()
    

    2、有n阶台阶,一次可以跳1级,也可以跳2级,。。。也可以跳n级;那么跳上第n阶有几种方式,请用编程求出结果

    def calnum(num):
        if num <= 1:
           result = 1
        else:       
             result = num * calnum(num-1) # 函数内部调用自己
        return result
    print(calnum(1))
    

    3、有一个列表,请使用编程实现对它的反转,直接修改原列表,不用内置方法

    l = [1,2,3,4,5,6]
    l1 = []
    for i in range(len(l)):
        l1.append(l[-i-1])
    
    print(l1)
    

    4、有模块B,其中有一个prinit("B");
    模块A、C都导入了B;
    启动文件main.py中,导入了A和C;
    问prinit("B")被执行了几次

    1次  单例模式,只有在首次导入时才会加载
    

    5、数据库中有一个自增的用户表,用户名有重复的,请用sql命令删除重复的记录,并随机保留一条

    假设有一样一张数据库表TNames,有两个字段 ID:主键 int;Name:nvarchar(50)
    
    TNames表中有一些重复数据行 例如:
    
      ID    Name
    
    ---------------------------
    
      1    wang
    
      2    wang
    
      3    lee
    
      4    lee
    
      5    lee
    
      6    zhang
    
      7    zhang
    
      8    zhao
    
     
    
    现要求从这张表删除重复的记录,结果要求为:数据表中最后剩下wang、lee、zhang、zhao四条不重的记录。
    
    解题思路:1)首先要找到重复的Name 执行Sql为
    
    select Name from TNames group by Name having count(*)>1
    
       2)其次根据上一步的Sql找到每一组重复Name的最大ID或最小ID 执行Sql为
    
     select max(id) from TNames where Name in(select Name from TNames group by Name having count(*)>1) group by Name 
    
          3)根据上两步查询删除TNames表中条件为 Name 包括在第一步执行Sql中,且ID不包括第二步执行Sql中的记录,具体Sql语句为
    
    delete from TNames where id not in(
    select max(id) from TNames where name in(
    select name from TNames group by name having count(*)>1) group by name) and name in (select name from TNames group by name having count(*)>1)
    
     
    
    经过第3步的执行,便可以从数据表中清除重复的记录。
    

    6、有一个单链表,请用编程实现单链表的反转

    class Node(object):
        def __init__(self, data, next=None):
            self.val = data
            self.next = next
    
        def fun4(head):
            if head == None:
                return None
            L, M, R = None, None, head
            while R.next != None:
                L = M
                M = R
                R = R.next
                M.next = L
            R.next = M
            return R
    
    
    if __name__ == '__main__':
        l1 = Node(1)
        l1.next = Node(2)
        l1.next.next = Node(3)
        l1.next.next.next = Node(4)
        print(type(l1))
        print(type(l1.next))
        print(type(l1.next.next))
        l = Node.fun4(l1)
        print(l.val, l.next.val, l.next.next.val, l.next.next.next.val)
    

    7、如何实现数据库的热备份,并且由原来的表变成四个表

    8、sqlalchemy的使用,关于阻塞的,我不记得具体问题了

    9、用Python实现单链表,并实现它的逆序

    10、用python中序遍历一个二叉树

    先创建一颗二叉树:

    class BinaryTree:
        def __init__(self, data):
            self.data = data
            self.left = None
            self.right = None
    
        def get(self):
            return self.data
    
        def getLeft(self):
            return self.left
    
        def getRight(self):
            return self.right
    
        def setLeft(self, node):
            self.left = node
    
        def setRight(self, node):
            self.right = node
    

    好,这里我们定义好了一个二叉树类,并给它添加了一下方法,然后我们来实例化一颗二叉树:

    binaryTree = BinaryTree(0)
    binaryTree.setLeft(BinaryTree(1))
    binaryTree.setRight(BinaryTree(2))
    binaryTree.getLeft().setLeft(BinaryTree(3))
    binaryTree.getLeft().setRight(BinaryTree(4))
    binaryTree.getRight().setLeft(BinaryTree(5))
    binaryTree.getRight().setRight(BinaryTree(6))
    

    实例化好的二叉树是长这个样子的:

    中序遍历的顺序是:先遍历树的左节点,再遍历树的父节点,再遍历树的右节点。
    对于我们上面创建的二叉树,它的中序遍历结果就是:3 -> 1 -> 4 -> 0 -> 5 -> 2 -> 6
    在前序遍历的时候是先遍历父节点,所以result.append(now.data),就在遍历左节点和右节点的前面。
    而中序遍历要先遍历左节点,所以result.append(now.data)就要在遍历左节点的后面,遍历右节点的前面。

    def intermediateTraversal(now, result=[]):
        if now == None:
            return result
        intermediateTraversal(now.left, result)
        result.append(now.data)
        intermediateTraversal(now.right, result)
        return result
    
    print(intermediateTraversal(binaryTree))
    # 执行结果:[3, 1, 4, 0, 5, 2, 6]
    

    11、不额外增加内存实现对数组的翻转,不能使用python内置方法(sorted(reverse=True),[::-1])

    language = ['java', 'c语言', 'python']
    for index, val in enumerate(language):
        if index <= len(language)//2:
            temp = language[-index-1]
            language[-index - 1] = val
            language[index] = temp
    print(language)
    
    1. python名次 1 优点:简单上手快 , java名次 2 优点:稳定,用者多,市场大 , c语言名次 3 优点:编程的基础

      language = ['java', 'c语言', 'python']
      ranking = (1,3,2)
      advantage = ({'优点':'简单好上手',}, {'优点':'编程的基础'},{'优点': '用者多,市场大'})
      

      题解

      # 1.请按名次升序排列语言,以字典的形式展示;
      
      ranking = list(ranking)
      ranking[0],ranking[2] = ranking[2],ranking[0]
      # print(ranking)
      dict_language = dict(zip(ranking,language))
      print({k:dict_language[k] for k in (sorted(dict_language.keys()))})
      
      '''
      {1: 'python', 2: 'java', 3: 'c语言'}
      '''
      
      # 2.请按名次降序排列优点,以字典的形式展示;
      dict_advantage = dict(zip(ranking,advantage))
      print({k:dict_advantage[k] for k in (sorted(dict_advantage.keys(),reverse=True))})
      
      1. 给定无序正整数数组,线性时间内找出第K大的值。

      无序正整数数组 = [3,4,4,5,5,61,1,2,2,3,3,3,3,6,7,7,7,7,8,9]

      解题思路:去重,用线性算法(归并排序和桶排序)排序,取出第K大的值。 参考博客:算法与数据结构

    2. list1 = ['a','b','c'],list2 = [1,2,3],以list1的元素为键,以list2的元素为值,生成一个字典,并按照从键小到大的顺序排序

    list_key = ['a','b','c']
    list_value = [1,2,3]
    dict1 = {k:v for k,v in sorted(zip(list_key,list_value),reverse=True)}
    print(dict1)
    
    1. 求斐波那契数列第n项的值。
    # 方式1:简单递归
    def fib(n):
        if n < 2:
            return n
        else:
            return fib(n-1) + fib(n-2)
    if __name == "__main__":
        result = fib(100)  # 你等到天荒地老,他还没有执行完
        # 如上所示,代码简单易懂,然而这代码却极其低效。先不说这种递归的方式造成栈空间极大浪费,就仅仅是该算法的时间复杂度已经属于O(2^n)了。指数级别时间复杂度的算法跟不能用没啥区别!
        
        
    # 方式2:
    def fib(n):
        results - list(range(n+1))  # 用于缓存以往结果,以便复用(目标2)
        for i in range(n+1):  # 按照顺序从小往大算(目标2)
            if i < 2:
                results[i] = i
            else:
                # 使用状态转移方程(目标1), 同时复用以往结果(目标2)
                results[i] = results[i-1] + results[i-2]
            return results[-1]
        
    if __name == "__main__":
        result = fib(100) # 秒算
                            
    

    15.一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。

    机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。

    问总共有多少条不同的路径?

    例如,上图是一个7 x 3 的网格。有多少可能的路径?

    解这题,如前所述,我们需要完成三个子目标

    1. 建立状态转移方程。该题就难在这里,这一步搞不定基本上就GG了。实际上,如图3所示,第i行第j列的格子的路径数,是等于它左边格子和上面格子的路径数之和:

    2.缓存并复用以往结果。与之前说的一堆数列不同,这里的中间结果可以构成一个二维数列(如上图),所以需要用二维的数组或者列表来存储。

    3.按顺序从小往大算。这次有两个维度,所以需两个循环,分别逐行和逐列让问题从小规模到大规模计算。

    代码实现:

    # m是行数,n是列数
    def count_paths(m,n):
        results = [[1]*n]*m  # 将二维列表初始化为1,以便之后用于缓存(目标2)
        # 题外话:results的空间复杂度不是O(nm),是O(n)
        
        # 第0行和第0列的格子路径数显然均取值为1,所以跳过
        for i in range(1,m):  # 外循环逐行集散(目标3)
            for j in range(1,n):  # 内循环逐行计算(目标3)
                # 状态方程(目标1),以及中间结果复用(目标2)
                results[i][j] = results[i-1][j] + results[i][j-i]
                
        return results[-1][-1]
    
    
    if __name == "__main__":
        result = count_paths(7,3)  # 结果为28
    
    1. 把一元的钞票换成一分、二分、五分的硬币(每种至少一枚),问有多少种兑换方法。(请用伪代码或擅长语言进行逻辑实现)
    # 方式一:暴力破解法
    n=int(input())
    cnt=0
    for fen5 in range(n//5,0,-1):
        for fen2 in range(n//2,0,-1):
            for fen1 in range(n,0,-1):
                if (fen5 * 5+fen2 * 2+fen1 == n):
                    print('fen5:{:d}, fen2:{:d}, fen1:{:d}, total:{:d}'.format(fen5, fen2, fen1, fen1+fen2+fen5))
                    cnt=cnt+1
    print('count = {:d}'.format(cnt))
    
    
    # 方式二:
    count = 0
    x = int(input())    #x∈(8,100)
    a = x // 5          
    for m in range(a,0,-1):         #fen5
        b = (x - (m * 5)) // 2     
        for n in range(b,0,-1):         #fen2 
            c = x - (5 * m) - (2 * n)       #fen1
            if m > 0 and n > 0 and c > 0:   #每种硬币至少有一枚
                print("fen5:{}, fen2:{}, fen1:{}, total:{}".format(m,n,c,m + n + c))
                count += 1
     
    print("count = {}".format(count))
    
  • 相关阅读:
    python实现git操作
    CentOS 安装R包 报错:internet routines cannot be loaded ,如何解决
    CentOS 6.8上安装指定版本的注释软件 VEP,release 93.4
    Anaconda3安装后在Pycharm中报错:ImportError: DLL load failed: 找不到指定的模块
    CentOS编译fastp 0.19.4 时报错/usr/bin/ld: cannot find -lz
    推荐一款非常好用的在线python编辑器——Colaboratory
    mac如何用quick look预览多个文件或者图片
    Pileup 格式详细说明
    CentOS 7 上安装 Django 2.2.4,解决报错:No module named ‘_sqlite3′
    Message: 'chromedriver' executable needs to be available in the path.
  • 原文地址:https://www.cnblogs.com/zhangchaocoming/p/13423793.html
Copyright © 2020-2023  润新知