2023秋招笔试算法Python3题解

诸神缄默不语-个人CSDN博文目录

签两方了,感觉秋招已经结束了,所以发布一下之前写的笔试编程题题解。
不全。可能有些题我会继续补。
不保证能过。
后续依然有可能继续刷算法题,但是就另外专门写博文来解析了。
打码是因为原则上其实是不让公开题目的。所以仅供学习参考。
(大厂特指互联网大厂)

文章目录

  • 1. 手机厂 算法
    • 题一
    • 题二
    • 题三
  • 2. 安全厂 算法
  • 3. 大厂 算法
    • 第一题
    • 第二题
  • 4. 游戏厂 开发
  • 5. 游戏厂 开发
    • 编程题一
    • 编程题二
    • 编程题三
  • 6. 传统制造业 算法
  • 7. 大厂
  • 8. 大厂 算法
  • 9. 银行
    • 第一题
    • 第二题
    • 第三题
  • 10. 手机厂 算法
  • 11. 游戏厂 全栈
    • 第一题
    • 第二题
    • 第三题
  • 12. 金融科技厂 算法
  • 13. 大厂(和第7家是同一家)
    • 第一题
    • 第二题
    • 第三题
  • 14. 大厂 算法
    • 第一题
    • 第二题
  • 15. 国企 算法
    • 第一题
    • 第二题
  • 16. 安全厂 算法
    • 第一题
    • 第二题
    • 第三题
  • 17. 银行 开发
    • 第一题
    • 第二题
  • 18. 传统能源公司 算法
    • 第一题
    • 第二题
    • 第三题
    • 第四题
  • 19. 国企 算法
    • 第一题
    • 第二题

1. 手机厂 算法

解法不难,但是题目真是给我看蒙了。感觉风格就是超级实用(第一题一看就是手机厂能出的题)

题一

具体的忘了总之是摄像头拍照→ISP处理→算法处理,给出了50个时间戳序列,计算能满足98%场景下的延时(也就是时间差)
其实也不用sorted,只需要找到第二大的元素就可以

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 输出最优预测时长tOffset 
# @param strTimestameLog string字符串 log
# @return int整型
#
class Solution:
    def GetPredictTime(self , strTimestameLog: str) -> int:
        # write code here
        list3=strTimestameLog.split()
        tsExposureEnd=[int(x) for x in list3[0].split(",")]
        tsIspEnd=[int(x) for x in list3[1].split(",")]
        tsAlgorithmEnd=[int(x) for x in list3[2].split(",")]

        duration1=[tsIspEnd[i]-tsExposureEnd[i] for i in range(50)]
        duration2=[tsAlgorithmEnd[i]-tsIspEnd[i] for i in range(50)]

        duration12=[duration1[i]+duration2[i] for i in range(50)]
        return sorted(duration12)[-2]

题二

找字符串中同时是前缀和后缀的最长的字符串的长度(前缀和后缀不能交叠)

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param s string字符串 
# @return int整型
#
class Solution:
    def longestPrefixSuffix(self , s: str) -> int:
        # write code here
        for epoch_num in range(int(len(s)/2),0,-1):
            if s[:epoch_num]==s[-epoch_num:]:
                return epoch_num
        return 0

题三

这个题目也贼复杂,总之就是给出一串数字,将这串数字分配给n个桶,要求桶的和之间的差最小,然后求最小的痛和。
分配逻辑就是先把大于平均值的数分掉(因为被分配到这些数字的桶肯定只能分这一个数字),剩下的里面按顺序把大的数字分给数字和最小的桶。

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 返回最小工时之和
# @param tasks int整型二维数组 项目任务工时
# @param n int整型 员工人数
# @return int整型
#

class Solution:
    def leastTimeSum(self , tasks: List[List[int]], n: int) -> int:
        # write code here
        min_sum=0
        for task in tasks:
            if len(task)==n:
                min_sum+=min(task)
            else:
                task=sorted(task,reverse=True)
                avg_time=sum(task)/n
                
                for t_index in range(len(task)):
                    if task[t_index]<=avg_time:
                        employer_time=task[:t_index]+[0 for _ in range(n-t_index)]
                        task=task[t_index:]
                        break
                for t in task:
                    index_min=employer_time.index(min(employer_time))
                    employer_time[index_min]+=t

                min_sum+=min(employer_time)
        return min_sum

2. 安全厂 算法

第一道题大概意思是输入一堆数字,然后从这堆数字中找出现频率最低的7个数字(如果有超过7个数字,就选最小的),顺序排列:

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param nums int整型二维数组 一段时间内的中奖号码数组
# @return int整型一维数组
#
class Solution:
    def getLuckyNum(self , nums: List[List[int]]) -> List[int]:
        number_count=[0 for _ in range(33)]  #1-33每个数字出现的次数
        for number_list in nums:
            for number in number_list:
                number_count[number-1]+=1
        now_least_time=0  #从出现0次的数字开始
        result_list=[]
        appended_set=set()
        while len(result_list)<7 and now_least_time<=len(nums):
            now_numbers=[]
            for number in range(33):
                if number_count[number]==now_least_time and number not in appended_set:
                    now_numbers.append(number+1)
                    appended_set.add(number)
            if len(result_list)+len(now_numbers)<=7:
                result_list.extend(now_numbers)
            else:
                appended_list=sorted(now_numbers)[:(7-len(result_list))]
                result_list.extend(appended_list)
            now_least_time+=1
        return sorted(result_list)[:7]

3. 大厂 算法

第一题

就是一个简单的加法题

import sys

line_number=0
for line in sys.stdin:
    if line_number==0:
        competition_number=int(line)
        line_number+=1
    else:
        competitions=[int(x) for x in line.split()]
result=0
for competition_index in range(competition_number):
    if competitions[competition_index]==1:
        if competition_index>0 and competitions[competition_index-1]==1:
            result+=2
        else:
            result+=1
print(result)

第二题

打靶算分,之所以直接if-else是因为比较简洁的写法不知道为什么会有边界情况过不去,我直接大力出奇迹:

import sys,math

for line in sys.stdin:
    zuobiao=[int(x) for x in line.split()]
    r=math.sqrt(zuobiao[0]**2+zuobiao[1]**2)
    if r<=1:
        print(10)
    elif r<=2:
        print(9)
    elif r<=3:
        print(8)
    elif r<=4:
        print(7)
    elif r<=5:
        print(6)
    elif r<=6:
        print(5)
    elif r<=7:
        print(4)
    elif r<=8:
        print(3)
    elif r<=9:
        print(2)
    elif r<=10:
        print(1)
    else:
        print(0)

4. 游戏厂 开发

第一道题:要求计算和为nNum的奇数序列(由一组连续奇数组成的序列)有多少个。
然后这道题如果直接暴搜(时间复杂度应该是 O ( n 2 ) O(n^2) O(n2))的话会超时,我这个算法大意来说是假设奇数序列的第一个值是 a a a,序列长度是 n − 1 n-1 n1,用等差数列求和公式易得 a ( n + 1 ) + n ( n + 1 ) = n N u m a(n+1)+n(n+1)=nNum a(n+1)+n(n+1)=nNum a = n N u m − n ( n + 1 ) n + 1 a=\frac{nNum-n(n+1)}{n+1} a=n+1nNumn(n+1),也就是说 n n n只会对应唯一的 a a a,这样只要遍历 n n n就能得到 a a a,如果 a a a是个奇数就符合题目要求。
另外,易得这个 a a a肯定会跟着 n n n的增加而减小的(这个不用证明了吧完全是直觉吧),所以如果 a < 1 a<1 a<1的话就说明后面的 n n n也都不用算了(如果不剪枝的话也过不了样例):

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 求奇序列数
# @param nNum int整型 指定的数字
# @return int整型
#
class Solution:
    def Calc(self , nNum: int) -> int:
        result=0
        for n in range(1,int(nNum/2),1):
            a=(nNum-n*(n+1))/(n+1)
            if a<1:
                break
            if ((nNum-n*(n+1))/(n+1))%2==1:
                result+=1
        return result

5. 游戏厂 开发

因为没有按样例给分,所以我也不知道我写的对不对捏

编程题一

已知一个按照递增顺序排列的整数数组nums和一个目标值target,找出给定目标值在数组中的开始位置和结束位置。

要求:

1.时间复杂度 O ( log ⁡ n ) O(\log n) O(logn)

2.空间复杂度 O ( 1 ) O(1) O(1)

示例:

输入:nums=[3,5,5,8,8,8,10],target=8

输出:[3,5]

输入:nums=[3,5,5,8,8,8,10],target=9

输出:[-1,-1]

答题模板

class Solution {

public:

    vector<int> searchRange(vector<int>& nums, int target) {

    }

};

我的答案:

class Solution():
    def searchRange(self,nums:list,target:int):
        #说了是顺序的那就直接二分查找,先找开头后找结尾,要看旁边的情况
        if nums[0]==target:
            search_pointer1=0
        elif nums[0]>target or nums[-1]<target:
            return [-1,-1]
        else:
            search_pointer1=int(len(nums)/2)
            while search_pointer1>=1:
                if nums[search_pointer1]==target and nums[search_pointer1-1]<target:
                    break
                search_pointer1=int(search_pointer1/2)
        
        if nums[-1]==target:
            search_pointer2=len(nums)-1
        else:
            search_pointer2=int(len(nums)/2)
            while search_pointer2<len(nums)-1:
                if nums[search_pointer2]==target and nums[search_pointer2+1]>target:
                    break
                search_pointer2=int((search_pointer2+len(nums))/2)
        
        if search_pointer1<=0 and search_pointer2>=len(nums)-1:
            return [-1,-1]
        
        return [search_pointer1,search_pointer2]

#solution=Solution()
#print(solution.searchRange([3,5,5,8,8,8,10],8))

编程题二

给你一个整数数组coins, 表示不同面额的硬币,以及一个整数amount,表示总金额。
计算并返回可以凑成总金额所需的 最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回-1。
你可以认为每种硬币的数量是无限的。
要求:时间复杂度O(Sn), S是金额,n是面额数

数值范围:
1 <= coins.length <= 12
0 <= amount <= 10^4

【测试用例】
输入:coins = [1, 2, 5], amount = 11
输出:3
输入:coins = [2], amount = 3
输出:-1
输入:coins = [1], amount = 0
输出:0

【参考函数】

int coinChange(vector<int>& coins, int amount) {

}

我的答案:

def coinChange(coins:list,amount:int):
    #当然比较直觉就容易想到,从最大的开始算余数
    if amount==0:
        return 0
    coins=sorted(coins)
    result=0
    now_amount=amount
    for now_max_coin in coins[-1::-1]:
        if now_max_coin<=now_amount:
            add_number=int(now_amount/now_max_coin)
            result+=add_number
            now_amount=now_amount-add_number*now_max_coin
    if not now_amount==0:
        return -1
    return result

编程题三

你参与了一个微信小游戏的研发,策划同学计划给你发布n项任务,每项任务会有一个 发布时间点r 和 预估处理时长p ,你需要等待任务发布后才能开始编码实现,同时每项任务都会有一位测试同学跟进测试工作,你需要合理安排工作,让所有测试同学等待的时间之和最少,此外你作为一个资深的程序员,多项任务可以交替进行。
输入:n r1 p1 … rn pn
输出:各项任务的任务id和完成时间,任务id从下标1开始,按完成时间升序排列
比如
输入:2 1 4 3 1
即发布2项任务,任务1的发布时间点r=1,处理时长p=4;任务2的发布时间点r=3,处理时长p=1,合理的工作安排如下图所示:
(图片没法复制)

输出:
2 4
1 6
测试同学等待的总时长为10
image.png

【测试用例】
输入:2 1 4 3 1
输出:
2 4
1 6
输入:3 3 3 4 1 1 7
输出:
2 5
1 7
3 12
输入:2 5 2 3 1
输出:
2 4
1 7

【题目1】请简要阐述解题思路(12分)

【题目2】编写相应的程序实现(24分)
【参考函数】

struct Task {
    int i;          // 任务id
    int r, p;       // 发布时间,处理时长
};

vector<vector<int>> processTasks(vector<Task>& tasks) {

}

我的答案:

#任务目标是要让结束时间的和最短,按照小学奥数的知识我们容易想到,我们应该让先跑完的先跑
#如果当前时间只有一个任务,那没啥可说的就直接运行这个任务
#如果当前时间可选多个任务,那先运行运行时间短的

import copy

class Task():
    def __init__(self,i,r,p):
        self.i=i
        self.r=r
        self.p=p

def processTask(tasks:list):
    sorted_tasks=sorted(tasks,key=lambda x:x.r)  #按照开始时间排序
    time=0
    max_time=max([x.r for x in tasks])+sum([x.p for x in tasks])
    now_in_line_tasks=[]  #[i,剩余时间]
    now_out_line_tasks=copy.copy(sorted_tasks)
    
    result=[]
    
    for time in range(0,max_time+1):
        while(len(now_out_line_tasks)>0 and now_out_line_tasks[0].r==time):
            the_task=now_out_line_tasks.pop(0)
            now_in_line_tasks.append([the_task.i,the_task.p])
        if len(now_in_line_tasks)>0:
            min_p=now_in_line_tasks[0][1]
            min_p_corresponding_task=0
            for i in range(1,len(now_in_line_tasks)):
                if now_in_line_tasks[i][1]<=min_p:
                    min_p=now_in_line_tasks[i][1]
                    min_p_corresponding_task=i
            now_in_line_tasks[min_p_corresponding_task][1]-=1
            if now_in_line_tasks[min_p_corresponding_task][1]==0:
                result.append([now_in_line_tasks[min_p_corresponding_task][0],time+1])
                now_in_line_tasks.pop(min_p_corresponding_task)
        if len(now_out_line_tasks)==0 and len(now_in_line_tasks)==0:
            break
    
    return result

input_task=[int(x) for x in input().split()]
task_number=input_task[0]
input_Task=[]
for task_id in range(task_number):
    input_Task.append(Task(task_id+1,input_task[task_id*2+1],input_task[task_id*2+2]))
output_list=processTask(input_Task)
for l in output_list:
    print(" ".join([str(x) for x in l]))

6. 传统制造业 算法

大意来说就是将一个矩阵逆时针旋转90°

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param mat int整型二维数组 
# @param n int整型 
# @return int整型二维数组
#
from typing import List

class Solution:
    def rotateMatrix(self , mat: List[List[int]], n: int) -> List[List[int]]:
        new_mat=[[] for _ in range(n)]
        for i in range(n):
            #填充new_mat中索引为i的行
            mat_index=n-1
            for _ in range(n):
                new_mat[i].append(mat[mat_index][i])
                mat_index-=1
        return new_mat

7. 大厂

第一题:好像是统计数字的位数之类的

import sys

n=0
for line in sys.stdin:
    if n==0:
        n=int(line)
    else:
        a=[int(x) for x in line.split()]  #a_i必须是整数吗?有说这事吗?

count=0
for ai in a:
    while not ai==0:
        count+=1
        if ai<10:
            break
        str_ai=str(ai)
        jinwei=str_ai[1:]
        ai=int(jinwei)

print(count)

8. 大厂 算法

是面试手撕,所以不确定正确性。

大致逻辑是有一个从上到下递增、从左到右递增的矩阵,我们现在希望知道,某一整数是否出现在了这个矩阵中(算是查找问题吧)
解决问题的逻辑是,从右上角开始检索,如果整数小于该数就往左检索,如果大于该数就往下检索,这样就能够保证是一个线性的检索顺序,最大的时间复杂度应该是 O ( m + n ) O(m+n) O(m+n) m m m是矩阵行数, n n n是矩阵列数)

#coding=utf-8
import sys

matrix=[[1, 4, 7, 11, 15],[2, 5, 8, 12, 19],[3, 6, 9, 16, 22],[10, 13, 14, 17, 24],[18, 21, 23, 26, 30]]
target = int(input())

n=len(matrix)
m=len(matrix[0])

now_line=0
now_column=n-1

result=False
while now_line<=m-1 and now_column>=0:
    #print(str(now_line)+" "+str(now_column))
    if matrix[now_line][now_column]==target:
        result=True
        break
    elif matrix[now_line][now_column]>target:
        now_column-=1
    else:
        now_line+=1
print(result)

9. 银行

第一题

给出每次存款的数目和每次取款的数目,要求单次取款数<存款数时才能取款,取款数有上限(limit),要求计算总的存款数-取款数

from typing import List

def calculateDeposit(deposits: List[int], withdrawals: List[int], limit: int) -> int:
    """
    @param deposits 存款金额
    @param withdrawals 取款金额
    @param limit 净存款总额
    @return 整型
    """
    # 如果意思是取款数仅不能大于当前存款数
    deposit_sum = sum(deposits)
    now_deposit = 0
    now_withdral = 0
    for i in range(len(withdrawals)):
        if i < len(deposits):
            now_deposit += deposits[i]
        if withdrawals[i] <= deposits[i] and now_withdral+withdrawals[i] <= limit:
            now_deposit -= withdrawals[i]
            now_withdral += withdrawals[i]

    return deposit_sum-now_withdral

第二题

大意是给出节点(港口)和无向边(港口之间的航线),要求找出不能连通的节点(无法互相通达的港口)。
当然是直接DFS求孤岛,直接递归就可以。

from typing import List

def check_i_j(i: int, j: int, already_bianlied: List[int], node_list: dict):
    """检查i到j之间是否存在航线"""
    if j in node_list[i]:
        return True
    else:
        for node in node_list[i]:
            if node in already_bianlied:
                continue
            if check_i_j(node, j, already_bianlied+[node], node_list):
                return True
    return False


def count_pairs(route_map: List[List[int]], n: int) -> int:
    """
    @param route_map 港口之间的航线图
    @param n 港口数量
    @return 整型
    """
    isolated_line_number = 0

    # 先整理为双向图node list的形式
    bi_node_list = {k: set() for k in range(n)}
    for node_pair in route_map:
        bi_node_list[node_pair[0]].add(node_pair[1])
        bi_node_list[node_pair[1]].add(node_pair[0])
    for p in bi_node_list:
        bi_node_list[p] = sorted(list(bi_node_list[p]))

    for i in range(n):
        for j in range(i+1, n):
            if len(bi_node_list[i]) == 0:
                isolated_line_number += 1
            elif not check_i_j(i, j, [], bi_node_list):
                isolated_line_number += 1

    return isolated_line_number

第三题

这道题题目还挺复杂的,总之就是说,有一个矩阵grid,机器人要从左上角走到右下角,只能往右或者往下走。每一个格子可能是水域(0)或者陆地(1),机器人一次最多跨k个水域,也就是在机器人行走的路线上,最多存在k个连续的0。
问题是求机器人能不能走到右下角。
因为样本量超小(应该就是100×100的样子),所以我直接上暴力遍历就能过所有样例了。
也算是过了,怎么不能算AC呢,暴力也是AC。

from typing import List

def go2final_step(grid, now_x, now_y, k, already_jumped):
    """
    迭代辅助函数
    @param grid 原始grid
    @param now_x 当前的横坐标
    @param now_y 当前的纵坐标
    @param k 最大水域数量
    @param already_jumped 已经跨越过的水域数量
    @return bool
    """
    if now_x == len(grid)-1 and now_y == len(grid[0])-1:
        return True

    # 向右移动
    if now_y+1 < len(grid[0]):
        if grid[now_x][now_y+1] == 1:
            if go2final_step(grid, now_x, now_y+1, k, 0):
                return True
        elif already_jumped+1 <= k:
            if go2final_step(grid, now_x, now_y+1, k, already_jumped+1):
                return True

    # 向下移动
    if now_x+1 < len(grid):
        if grid[now_x+1][now_y] == 1:
            if go2final_step(grid, now_x+1, now_y, k, 0):
                return True
        elif already_jumped+1 <= k:
            if go2final_step(grid, now_x+1, now_y, k, already_jumped+1):
                return True

    return False

def solution(grid: List[List[int]], k: int) -> bool:
    """
    @param grid 表示地形的二维数组
    @param k 机器人每次移动能够跨越的最大水域数量
    @return 布尔
    """
    # 暴力迭代,启动!
    if go2final_step(grid, 0, 0, k, 0):
        return True

    return False

10. 手机厂 算法

第二题:
大意是说有一个books数组表示对每本书的喜好,从books中排列组合出一个新数组,然后和当前总阅读时间(就是代码里的那个time_list)相乘得到效用值,要求总的效用值最高。
我直接就是一个贪心。

def accumulate_list(book_list,time_list):
    return sum([(time_list[i]+1)*book_list[i] for i in range(len(book_list))])

def func():
    books=[int(x) for x in input().split(",")]
    #越大的正数放到越后面越好,负数要不要留下主要考虑能不能放在最前面顶一些时间
    books=sorted(books)
    zhengshu_begin=-1
    for i in range(len(books)):
        if books[i]>=0:
            zhengshu_begin=i
            break
    
    if zhengshu_begin==-1:
        print(0)  #别读了,浪费时间
    elif zhengshu_begin==0:
        print(accumulate_list(books,list(range(len(books)))))  #全读
    else:
        #有一些正数,也有一些负数
        #直接遍历试一下会不会导致时间复杂度过高
        max_result=accumulate_list(books[zhengshu_begin:],list(range(len(books)-zhengshu_begin)))
        for fushu_index in range(zhengshu_begin,-1,-1):
            temp_result=accumulate_list(books[fushu_index:],list(range(len(books)-fushu_index)))
            if temp_result>max_result:
                max_result=temp_result
        print(max_result)

if __name__ == "__main__":
    func()

第三题:稀疏存储
大致来说就是设计一套迷惑的稀疏存储思路,允许用户进行读-写-清除内存操作。如果直接用数组来储存所有数据会炸。然后我的解决方案是设计了一个字典来存储当前的数据,键是起始地址,值是数据。
然后主要是情况太多了我懒得想了我吃得好饱我就只考虑了一部分情况就交卷了。
工程题是这样的,其实也不难就是边边角角特别多。

11. 游戏厂 全栈

全部AC,美滋滋

第一题

大意就是输入二进制的两个字符串,输出二进制格式的字符串和

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# public String solve (String str1, String str1)
# @param str1 string字符串
# @param str2 string字符串
# @return string字符串
#
class Solution:
    def solve(self, str1: str, str2: str) -> str:
        int1 = int(str1, 2)
        int2 = int(str2, 2)
        return str(bin(int1 + int2))[2:]

第二题

遍历二叉搜索树(所有节点都是非负整数),找节点差的最小值

# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param root TreeNode类
# @return int整型
#

def minDiff(root: TreeNode) -> int:
    min_diff = 10 ** 9
    if root.left:
        min_diff = min(min_diff, root.val - root.left.val)
        min_diff = min(min_diff, minDiff(root.left))
    if root.right:
        min_diff = min(min_diff, root.right.val - root.val)
        min_diff = min(min_diff, minDiff(root.right))
    return min_diff


class Solution:
    def minDifference(self, root: TreeNode) -> int:
        # 这是个二叉搜索树嘛,然后还全是非负数,那么我就应该找相邻的这种父子关系……因为非父子关系的节点的差值无论如何都有比之更小的……
        return minDiff(root)

第三题

大意是判断数组nums(元素都是非负整数)能否被分割为k个和相同的数组

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param nums int整型一维数组
# @param k int整型
# @return bool布尔型
#

def rearange(now_sum, other_nums, subsum):
    """从other_nums中找出能够与now_sum拼拼拼出subsum的索引,如果存在将返回这个索引,如果不存在直接返回False"""
    for index in range(len(other_nums)):
        if other_nums[index] + now_sum == subsum:
            return [index]
        if other_nums[index] + now_sum > subsum:
            continue
        cp = other_nums[index + 1 :].copy()
        diedai = rearange(other_nums[index] + now_sum, cp, subsum)
        if diedai:
            return [index] + [x + index + 1 for x in diedai]

    return False

class Solution:
    def candivide(self, nums: List[int], k: int) -> bool:
        # 每个非空子集的和一定是nums和/k,这得是个整数
        subsum = sum(nums) / k

        if not subsum % 1 == 0:
            return False

        for num in nums:
            if num > subsum:
                return False

        # 把上面这些情况去掉剩下的全置True居然就已经可以跑出80%了,神奇的,感觉意思是这3道题不全AC这笔试就不用过了呗
        # 试一下暴力遍历
        sum_res = sorted(nums, reverse=True)

        while sum(sum_res) > subsum:
            now_sum = sum_res.pop(0)
            if now_sum == subsum:
                continue

            diedai = rearange(now_sum, sum_res, subsum)
            if diedai:
                values = [sum_res[i] for i in diedai]
                for v in values:
                    sum_res.remove(v)
            else:
                return False

        if len(sum_res) == 0 or sum(sum_res) == subsum:
            return True
        else:
            return False

12. 金融科技厂 算法

空气中漂浮的都是我的无语。只写出了一道MySQL题。
挺复杂的,总之大致来说是根据分钟K线来计算5分钟K线

select
    finance_mic,
    prod_code,
    trade_date,
    max(data_timestamp) as data_timestamp,
    sum(business_count) as business_count,
    sum(business_amount) as business_amount,
    sum(business_balance) as business_balance
from
    `hq_kline_1min`
where
    finance_mic = 'XSHG'
    and prod_code = '600570'
    and trade_date = 20230703
    and data_timestamp < 103000000
    and data_timestamp > 93000000
group by
    floor((data_timestamp -93000000) / 1000 / 500),
    finance_mic,
    prod_code
order by
    max(data_timestamp)

13. 大厂(和第7家是同一家)

我也不知道为什么我做过一次还要我再做一次。可能是上一次做太差了发了张复活卡

第一题

我第一题AC了。

import sys

gifts = []
for line in sys.stdin:
    gifts.append(line)

# 感觉是检验两个字符串的相同子串。因为问题要求不是很复杂,所以直接用双指针遍历实现
max_length = 0
for pointer1 in range(len(gifts[0])):
    for pointer2 in range(pointer1 + 1, len(gifts[0])):
        if gifts[0][pointer1:pointer2] in gifts[1]:
            max_length = max(max_length, pointer2 - pointer1)
        else:
            break
print(max_length * 2)

第二题

这道题是洛谷上的“教主的花园”题,我这种解法只能过80%,我以后再学学正确解法

import sys

line_number = 1
trees = []
for line in sys.stdin:
    if line_number == 1:
        n = int(line)
    else:
        trees.append([int(x) for x in line.split()])
    line_number += 1

# 第一棵树
value_matrix = [trees[0][0], trees[0][1], trees[0][2]]
height_matrix = [[0], [1], [2]]

# 我寻思了一下,好像每一步在规划的过程中只要保证前面的不冲突就行,直到最后一步才需要验证和第一棵树冲不冲突
for i in range(1, n):  # 树的索引
    temp_value = []
    temp_height = []
    for occasions in range(len(value_matrix)):
        before_height = height_matrix[occasions]
        for height in range(3):  # 新树的高度
            if (not height == before_height[-1]) and (
                (i == 1)
                or (
                    before_height[-1] < before_height[-2] and before_height[-1] < height
                )
                or (
                    before_height[-1] > before_height[-2] and before_height[-1] > height
                )
            ):
                temp_value.append(value_matrix[occasions] + trees[i][height])
                if i > 1:
                    temp_height.append([before_height[0], before_height[-1], height])
                else:
                    temp_height.append([before_height[0], height])
    value_matrix = []
    height_matrix = []
    for i in range(len(temp_value)):
        if temp_height[i] in height_matrix:
            value_matrix[height_matrix.index(temp_height[i])] = max(
                value_matrix[height_matrix.index(temp_height[i])], temp_value[i]
            )
        else:
            value_matrix.append(temp_value[i])
            height_matrix.append(temp_height[i])


max_result = 0
for occasions in range(len(value_matrix)):
    heights = height_matrix[occasions]
    if (heights[-1] < heights[-2] and heights[-1] < heights[0]) or (
        heights[-1] > heights[-2] and heights[-1] > heights[0]
    ):
        max_result = max(max_result, value_matrix[occasions])

print(max_result)

第三题

尼玛,手写维特比算法,我只剩5分钟了实在是干不动了,下次学学吧。

14. 大厂 算法

第一题

总之大致就是根据第二个数组来将第一个数组的数值压缩到对应间隔的索引上

import sys

line_number=1
ip_list=[]
for line in sys.stdin:
    if line_number==1:
        ip_list.append([int(x) for x in line.split()])
    else:
        break

print_result=""
for number in ip_list[0]:
    if number<=ip_list[1][0]:
        print_result+="0"
    else:
        in_list=False
        for index in range(len(ip_list[1])-1):
            if ip_list[1][index]<number and number<=ip_list[1][index+1]:
                print_result+=str(index+1)
                in_list=True
                break
        if not in_list:
            print_result+=str(len(ip_list[1]))
    print_result+=" "
print(print_result[:-1])

第二题

给新人匹配导师。很简单的,直接贪心就完了。

import sys

line_number=1
new_birds=[]
tutors=[]
for line in sys.stdin:
    if line_number==1:
        new_bird_number,tutor_number=[int(x) for x in line.split()]
        if new_bird_number==0 or tutor_number==0:
            print(0)
            exit()
    elif line_number<new_bird_number+2:
        new_birds.append(int(line))
    elif line_number<new_bird_number+tutor_number+2:
        tutors.append(int(line))
    else:
        break
    line_number+=1

#我的直觉告诉我,直接上贪心
new_birds.sort()
tutors.sort()

max_result=0
for tutor in tutors:
    for new_bird_index in range(len(new_birds)):
        new_bird=new_birds[new_bird_index]
        if tutor>=new_bird:
            new_birds.pop(new_bird_index)
            max_result+=1
            break

print(max_result)

15. 国企 算法

两道题我都感觉我没问题,但是不知道为什么没有全部AC。因为太饿了而且赶着做下一套题所以没时间研究了就交了。

第一题

大概来说就是给出一个字符串,认为这个字符串是首尾相连的,然后要求算出所有字符相同的子串里面最长的长度

import sys

for x in sys.stdin:
    # 感觉简单,直接遍历应该就可以
    line = x.strip()

max_length = 0
now_sequence = line[0]
for i in range(1, len(line)):  # 先从前往后遍历
    if line[i] == now_sequence[0]:
        now_sequence += line[i]
    else:
        max_length = max(max_length, len(now_sequence))
        now_sequence = line[i]

# 然后考虑首部的情况
for i in range(len(line) - max_length):  # 不能遍历到之前的尾巴那里了
    if line[i] == now_sequence[0]:
        now_sequence += line[i]
    else:
        break

max_length = max(max_length, len(now_sequence))
max_length = min(len(line), max_length)  # 想不到别的情况了,撤退!

print(max_length)

第二题

给出一个环形键盘,每次需要先移动到下一个键,再点击确定。魔法键可以选择用也可以选择不用,魔法键是直接跳到下一个键,限制魔法键必须连续m次使用

import sys

for line in sys.stdin:
    line = line.strip().split(" ")

S = line[0]
m = int(line[1])

guangbiao = S[0]  # 将光标放在S[0]
result = []  # result列表储存的是从第一个键到第二个键开始,每一次需要的移动步数。确定键不用记了反正是固定值
keyboard = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
keyboard_number = {keyboard[v]: v for v in range(26)}

for k in S[1:]:
    if guangbiao < k:
        result.append(
            min(
                (keyboard_number[k] - keyboard_number[guangbiao]),
                (26 - keyboard_number[k] + keyboard_number[guangbiao]),
            )
        )
    elif guangbiao > k:
        result.append(
            min(
                (keyboard_number[guangbiao] - keyboard_number[k]),
                (26 - keyboard_number[guangbiao] + keyboard_number[k]),
            )
        )
    else:
        result.append(0)
    guangbiao = k

no_magic = sum(result)

# 直接遍历在哪一步可以用魔法键
magic_index = 0
now_sum = no_magic
for i in range(len(result) - m):
    # 从第i次移动开始使用魔法键
    now_sum = min(now_sum, no_magic - sum(result[i : i + m]) + m)

print(now_sum + len(S))

16. 安全厂 算法

第一题

没有完全AC
我觉得我基本就是按照题目愿意写的代码,不能AC是为什么呢我也很好奇

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param arr int整型一维数组
# @return int整型
#
class Solution:
    def count_peaks(self, arr: List[int]) -> int:
        # 应该可以直接遍历
        peak_number = 0
        for i in range(1, len(arr) - 1):
            if arr[i] >= arr[i - 1] and arr[i] >= arr[i + 1]:
                peak_number += 1
        return peak_number

第二题

大致来说就是给出一个矩阵,返回最长加权路径和。我的解法是直接迭代遍历求解。

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param grid int整型二维数组
# @return int整型
#
directions = [[-1, 0], [1, 0], [0, -1], [0, 1]]

def dig(grid, now_x, now_y, direction_index, bianlied, m, n, already_bianlied):
    if not bianlied[now_x][now_y][direction_index] == 0:
        return bianlied[now_x][now_y][direction_index]

    direction = directions[direction_index]
    new_x = now_x + direction[0]
    new_y = now_y + direction[1]

    if new_x < 0 or new_x >= m or new_y < 0 or new_y >= n or grid[new_x][new_y] == 0:
        bianlied[now_x][now_y][direction_index] = grid[now_x][now_y]
        return grid[now_x][now_y]

    max_path = 0
    for new_direction_index in range(4):
        tp = (new_x, new_y)
        s = set()
        s.add(tp)

        direction = directions[new_direction_index]

        if (new_x + direction[0], new_y + direction[1]) not in already_bianlied:
            max_path = max(
                max_path,
                dig(
                    grid,
                    new_x,
                    new_y,
                    new_direction_index,
                    bianlied,
                    m,
                    n,
                    already_bianlied.union(s),
                ),
            )
    bianlied[now_x][now_y][direction_index] = max_path + grid[now_x][now_y]


class Solution:
    def getMaxOil(self, grid: List[List[int]]) -> int:
        max_path = 0

        m = len(grid)
        if m < 1:
            return 0  # 应该不会有这种事情发生吧
        n = len(grid[0])

        bianlied = [
            [[0 for _ in range(4)] for _ in range(n)] for _ in range(m)
        ]  # bianlied[i][j][d]指的是从(i,j)往d方向出发的最长加权路径
        for i in range(m):
            for j in range(n):
                if not grid[i][j] == 0:
                    # 以当前节点为起点计算最长加权路径

                    now_max_path = 0
                    for new_direction_index in range(4):
                        tp = (i, j)
                        s = set()
                        s.add(tp)
                        now_max_path = max(
                            now_max_path,
                            dig(grid, i, j, new_direction_index, bianlied, m, n, s),
                        )

                    max_path = max(now_max_path, max_path)
        return max_path

第三题

我在前两道题上花的时间太久了。现在想一下,第三题应该也不难,就是直接动态规划应该就可以解决。

17. 银行 开发

SQL题无法调试。
两道编程题都只给了很少的样例,没有大规模调试结果,所以也不知道做得怎么样┓( ´∀` )┏

第一题

大意来说就是将缩写的ipv6路径写全

def count_maohao(ipv6:str)->int:
    result=0
    for c in ipv6:
        if c==":":
            result+=1
    return result

def FullIpv6(ipv6 : str) -> str:
    ipv6_list=[]
    temp_str=""
    for c in ipv6:
        if c==":":
            if temp_str=="":
                ipv6_list.extend([""]*(8-count_maohao(ipv6)))
            else:
                ipv6_list.append(temp_str)
                temp_str=""
        else:
            temp_str+=c
    ipv6_list.append(temp_str)
    result=[]
    for segment in ipv6_list:
        result.append("0"*(4-len(segment))+segment)
        
    return ":".join(result)

if __name__ == '__main__':
    ip : str = input()
    full_ipv6 : str = FullIpv6(ip)
    print(full_ipv6)

第二题

括号合法性。这道题应该在力扣上就有,用栈做就可以。(Python list很万能的所以全靠它了)

if __name__ == '__main__':
    input : str = input()
    zhan=[]
    score=0
    for iterater_index in range(len(input)):
        c=input[iterater_index]
        if c=="(":
            zhan.append(c)
        elif c==")":
            if len(zhan)>0 and zhan[-1]=="(":
                zhan=zhan[:-1]
                score+=1
            else:
                score=-1
                break
        elif c=="[":
            if len(zhan)==0 or zhan[-1]=="{":
                zhan.append(c)
            else:
                score=-1
                break
        elif c=="]":
            if len(zhan)>0 and zhan[-1]=="[":
                zhan=zhan[:-1]
                score+=5
            else:
                score=-1
                break
        elif c=="{":
            if len(zhan)==0:
                zhan.append(c)
            else:
                score=-1
                break
        elif c=="}":
            if len(zhan)>0 and zhan[-1]=="{":
                zhan=zhan[:-1]
                score+=3
            else:
                score=-1
                break
    print(score)

18. 传统能源公司 算法

编程题简单得我大吃一惊

第一题

输出倒金字塔

import sys

for line in sys.stdin:
    N = int(line)
    for i in range(N, -1, -1):
        print(str(N) * i)

第二题

输出输入的1后面有多少个3(如果不止有3或者没有3就返回-1)

import sys

for line in sys.stdin:
    Ei = line[1:].strip()
    if len(Ei) == 0 or not set(Ei) == set(["3"]):
        print(-1)
    else:
        print(len(Ei))

第三题

每天工作增加压力值A,工作B天后休息,休息每天减少压力值1,问多少天后压力值归零(怎么会有这么真实的题,扎心了)

import sys

line_number = 1
for line in sys.stdin:
    line = line.strip()
    if line_number == 1:
        T = int(line)
    else:
        A, B = [int(x) for x in line.split()]
        stress = A * B
        days = B + stress
        print(days)
    line_number += 1

第四题

对给定字符串进行解密

import sys

yuanyin = "aeiou"
alphabet = "abcdefghijklmnopqrstuvwxyz"

mingwen = ""
miwen = ""
for line in sys.stdin:
    miwen = line.strip()
    for c in miwen:
        mingwen += c
        if not c in yuanyin:
            alphabet_index = alphabet.find(c)

            yuanyin_pointer1 = alphabet_index - 1
            yuanyin_pointer2 = alphabet_index + 1
            while True:
                if yuanyin_pointer1 >= 0 and alphabet[yuanyin_pointer1] in yuanyin:
                    mingwen += alphabet[yuanyin_pointer1]
                    break
                else:
                    yuanyin_pointer1 -= 1

                if yuanyin_pointer2 < 26 and alphabet[yuanyin_pointer2] in yuanyin:
                    mingwen += alphabet[yuanyin_pointer2]
                    break
                else:
                    yuanyin_pointer2 += 1

            if c == "z":
                mingwen += "z"
            else:
                fuyin_pointer = alphabet_index + 1
                while True:
                    if not alphabet[fuyin_pointer] in yuanyin:
                        mingwen += alphabet[fuyin_pointer]
                        break
                    fuyin_pointer += 1

print(len(mingwen) - len(miwen))

19. 国企 算法

第一题

全部AC
大意来说就是输入2个二进制数,输出二进制格式的和(跟11那家游戏厂第一题一样)

import sys

for line in sys.stdin:
    if len(line.strip())>0:
        a,b=[int(x,2) for x in line.strip().split(",")]
        print(str(bin(a+b)[2:]))

第二题

过了67%,WA
大意来说就是给定起点找到所有节点的最短路径长度。我也不知道为啥会有答案错误,我觉得没问题啊

import sys

line_number=1
for line in sys.stdin:
    if line_number==1:
        times=eval(line)
    elif line_number==2:
        node_number=int(line)
    elif line_number==3:
        begin_node=int(line)
    line_number+=1

if node_number==1:
    print(-1)
    exit()

#DFS应该就可以
zhan=[begin_node]  #其实不是栈,是队列……
sum_times=sum([sum(x) for x in times])+100
every_distance=[sum_times+1 for _ in range(node_number+1)]  #从begin_node到每个节点的最短路径
every_distance[begin_node]=0

while len(zhan)>0:
    this_node=zhan.pop(0)
    for pair in times:
        if pair[0]==this_node:
            if not every_distance[pair[1]]:
                zhan.append(pair[1])
            every_distance[pair[1]]=min(every_distance[pair[1]],every_distance[pair[0]]+pair[2])
            

no_reach=False
for d in every_distance[1:]:
    if d==sum_times+1:
        no_reach=True
        break

if no_reach:
    print(-1)
else:
    print(max(every_distance[1:]))

你可能感兴趣的:(普通野生程序员的求职与职场之旅,算法,python,开发语言)