华为OD机试真题C卷-篇3

查找一个有向网络的头节点和尾节点

  • 在一个有向图中,有向边用两个整数表示,第一个整数表示起始节点,第二个整数表示终止节点;
  • 图中只有一个头节点,一个或者多个尾节点;
  • 图可能存在环,有环则输出-1;
  • 输出图中的头节点(入度为0)、尾节点(出度为0),如图头节点为1,尾节点为4。
    在这里插入图片描述
    输入描述:
    第一行输入n,n >=0
    第二行为n个数对,表示n条边;
    输出描述:
    输出一行,头节点、尾节点以空格隔开,多个尾节点则从大到小输出。
     
    示例1
    输入:
    4
    1 2 1 3 2 4 3 4
    输出:
    1 4
     
    示例2
    输入:
    3
    1 2 1 3 1 4
    输出:
    1 4 3 2
     
    示例3
    输入:
    4
    1 2 2 3 3 4 4 1
    输出:
    -1
     
    示例4
    输入:
    5
    1 2 2 3 3 4 4 5 4 2
    输出:
    -1
    思路:
  • 拓扑排序,判断有向图是否有环,有环则直接输出-1;
  • 只有一个起始点,一个或多个结尾点;
# __author__ = "laufing"


class GraphHeadTail:
    def solution(self, n, edges):
        # 所有的顶点和数目
        vertex = list(set(edges))
        vertex_num = len(vertex)
        # 统计每个顶点的入度
        in_degree = {}.fromkeys(vertex, 0)
        # 每个顶点的出度
        out_degree = {}.fromkeys(vertex, 0)
        for i in range(n):
            u, v = edges[i*2:(i+1)*2]
            out_degree[u] += 1
            in_degree[v] += 1

        # 找到入度为零的一个节点
        start_node = None
        for key in in_degree:
            if in_degree.get(key) == 0:
                start_node = key
                break

        if self.topology_sort(in_degree, start_node, edges, vertex_num):
            print(-1)
            return -1

        # 无环  输出头节点 + 尾节点
        # 找到所有的尾节点
        tails = []
        for key in out_degree:
            if out_degree.get(key) == 0:
                tails.append(key)
        tails.sort(reverse=True)
        result = str(start_node) + " " + " ".join(list(map(str, tails)))
        print(result)
        return result

    def topology_sort(self, in_degree, start_node, edges, vertex_num):
        in_degree = in_degree.copy() # 不影响原始数据
        if start_node is None:
            return True
        stack = []
        output_list = []
        stack.append(start_node)

        while stack:
            nodev = stack.pop()
            print("nodev:", nodev)
            output_list.append(nodev)
            # 删除边,对应的顶点入度-1
            for i in range(len(edges) // 2):
                u, v = edges[i*2:(i+1)*2]
                if u == nodev:
                    in_degree[v] -= 1
                    if in_degree[v] == 0:
                        stack.append(v)
        print(output_list)
        return len(output_list) < vertex_num


if __name__ == '__main__':
    graph_head_tail = GraphHeadTail()
    while True:
        try:
            n = int(input("n:").strip())
            edges = list(map(int, input("edges:").strip().split()))
            graph_head_tail.solution(n, edges)
        except KeyboardInterrupt:
            break

 

幼儿园篮球游戏

  • 有一个放倒的线性圆桶,可以从右边放入一个或者多个篮球,每个篮球有独立的编号;
  • 从右边和左边可以取出篮球,当只有一个篮球时,只能从左边取出;
  • 若依次放入1、2、3、4、5共五个编号的篮球,则可以依次取出1、2、3、4、5或者3、1、2、4、5;无法取出5 1 3 2 4编号的篮球;3 1 2 4 5 取出的场景为RLLLL,R表示右边取,L表示左边取;

输入描述:
第一行为依次放入的篮球编号;
第二行为依次取出的编号;
输出描述:
输出取的R/L序列;若无法取出,则输出No

示例1
输入:
4,5,6,7,0,1,2
6,4,0,1,2,5,7
输出:
RLRRRLL

示例2
输入:
4,5,6,7,0,1,2
6,0,5,1,2,4,7
输出:
No

示例3:
输入:
1,2,3,4
1,2,3,5
输出:
No
思路:

  • 遍历取出序列中的每个编号,在放入的序列中查找,找到后截取前半部分放入线性队列中;
  • 判断当前遍历的编号是否可以取出,可以取出则返回R or L;否则返回None
  • 最后将所有的字符拼接;
# __author__ = "laufing"


class FetchOrNot:
    def solution(self, in_seq, out_seq):
        result = ""
        deq = []
        for o in out_seq:
            try:
                if o in deq:
                    r = self.can_fetch_out(o, deq)
                    if r[0]:
                        result += r[0]
                        deq = r[1]
                        continue
                    else:
                        print("No")
                        return "No"
                idx = in_seq.index(o)
            except ValueError:
                print("No")
                return "No"
            else:
                pre = in_seq[:idx+1]
                in_seq = in_seq[idx+1:]
                deq.extend(pre)
            r = self.can_fetch_out(o, deq)
            if r[0]:
                result += r[0]
                deq = r[1]
            else:
                print("No")
                return "No"
        print(result)
        return result

    def can_fetch_out(self, char, deq):
        if char in deq:
            if len(deq) == 1:
                deq.pop(0)
                return "L", deq
            elif deq[0] == char:
                deq.pop(0)
                return "L", deq
            elif deq[-1] == char:
                deq.pop(-1)
                return "R", deq
            else:
                return None, None

        return None, None


if __name__ == '__main__':

    fetch_or_not = FetchOrNot()
    while True:
        try:
            in_seq = list(map(int, input("in:").strip().split(",")))
            out_seq = list(map(int, input("out:").strip().split(",")))
            fetch_or_not.solution(in_seq, out_seq)

        except KeyboardInterrupt:
            break

双指针;

nums = [int(x) for x in input().split(",")]
target_nums = [int(x) for x in input().split(",")]
 
arr = [float('inf') for i in range(300)]
 
left = 0
right = 0
target_pos = 0
 
result = ""
i=0
while(True):
    if(i>=len(nums)):
        break
    else :
        arr[right] = nums[i]
        right+=1
        while (True) :
            if(right <= left):
                break
            else :
                if (arr[left] == target_nums[target_pos]) :
                  result += "L"
                  left += 1
                  target_pos += 1
                  continue
                elif (arr[right-1] == target_nums[target_pos]) :
                  result += "R"
                  right -= 1
                  target_pos += 1
                  continue
                 
                break
    i+=1
 
if (left != right) :
  print("NO")
else :
  print(result)
 

 

Wonderland游乐园

在这里插入图片描述

import functools
import sys
import copy
import re
import math
 
costs =  [int(x) for x in input().split(" ")]
days =  [int(x) for x in input().split(" ")]
 
dp = [float('inf') for x in range(400)]
dp[0] = 0
j = 0
for i in range(1, 366):
    if (j<len(days) and i == days[j]) :
        dp[i] = min(dp[i], dp[max(0, i - 1)] + costs[0])
        dp[i] = min(dp[i], dp[max(0, i - 3)] + costs[1])
        dp[i] = min(dp[i], dp[max(0, i - 7)] + costs[2])
        dp[i] = min(dp[i], dp[max(0, i - 30)] + costs[3])
        j+=1
    else:
        dp[i] = dp[i - 1]
print(dp[365])

 

项目排期/最少交付时间

  • m个独立的需求,由n个开发者完成;
  • 每个任务都是独立的,只能由一个人完成;
  • 计算最少交付时间;

输入描述:
第一行输入m个需求的工作量(天数),m在(0,30)之间,每个需求的天数<200
第二行输入人员数量n

示例1
输入:
6 2 7 7 9 3 2 1 3 11 4
2
输出:
28

示例2
输入:
2 3 4 2 5
3
输出:
6

示例3
输入:
100 50 30 10
3
输出:
100

思路:

  • 二分求解
    • 需求的工作量升序排序;
    • 取完成需求的最小天数,计为low;
    • 取n个人完成的平均天数+1,计为high;
    • 取mid = (low + high) // 2,判断在这个mid上限以内是否能够在n个人之间完成需求的分配(每个人完成需求的天数<=mid);
      • 若可以完成分配,则进一步减少天数,令high = mid; 否则 low=mid+1;
      • 需求的分配则是从需求天数最小开始,依次分配给n个人,若给一个人分配后,其完成天数超出mid阈值,则将当前需求分配给下一个人
      • 最后求得的low值与需求的最大工作量对比


class MinimumTime:
    def solution(self, req_days, n):
        # 总天数
        total = 0
        self.m = len(req_days)
        self.req_days = req_days
        for i in range(self.m):
            total += req_days[i]

        # 分配需求的数组
        self.jobs = [0 for i in range(n)]

        # 需求工作量 排序
        req_days.sort()

        # 最小天数
        low = req_days[0]
        # 最大天数
        high = total / n + 1

        # 依次求解
        while True:
            if low >= high:
                break
            else:
                mid = int((low + high) / 2)

                # 是否可以成功分配
                if self.align_req(0, mid):
                    high = mid
                else:
                    low = mid + 1

        # low与最大的需求天数对比
        print(low if low > req_days[-1] else req_days[-1])

    def align_req(self, days_idx, threshold):
        # 递归分配任务

        if days_idx >= self.m:
            # 分配完成
            return True

        i = 0  # 依次分配给n个人
        while True:
            if i >= n:
                break
            else:
                total_v = self.req_days[days_idx] + self.jobs[i]
                if total_v > threshold:
                    if self.jobs[i] == 0: # 还没分配 就超出阈值
                        break
                else:
                    # 需求到开发 成功分配
                    self.jobs[i] += self.req_days[days_idx]

                    # 按照当前阈值,继续分配下一个需求
                    if self.align_req(days_idx + 1, threshold):
                        return True

                    # 下一个需求无法完成分配,当前分配撤销
                    self.jobs[i] -= self.req_days[days_idx]
            i += 1

        return False


if __name__ == '__main__':
    mini_time = MinimumTime()
    while True:
        try:
            req_days = list(map(int, input("days:").strip().split()))
            n = int(input("n:").strip())
            mini_time.solution(req_days, n)
        except KeyboardInterrupt:
            break


 

灰度图存储

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


 
nums1 = [int(x) for x in input().split(" ")]
nums2 = [int(x) for x in input().split(" ")]
target_position = nums2[0]*nums1[1] + nums2[1] + 1
total_sum = 0
i=3
while(True):
    if(i>=len(nums1)):
        break
    else :
        if (total_sum + nums1[i] < target_position) :
            total_sum += nums1[i]
        else :
            print(nums1[i - 1])
            break
    i+=2

 

精准核酸检测

在这里插入图片描述
在这里插入图片描述

 
n = int(input())
target = [int(x) for x in input().split(",")]
visited = [0 for x in range(n)]
matrix = []
for i in range(n):
    matrix.append([int(x) for x in input().split(",")])
 
def dfs(index) :
    visited[index] = 1
    i=0
    while(True):
        if(i>=n):
            break
        else :
            if (matrix[index][i] == 1 and visited[i]==0) :
                dfs(i) 
        i+=1
            
        
 
for i in range(len(target)):
    dfs(target[i])
 
result = 0
i=0
while(True):
    if(i>=n):
        break
    else :
        if (visited[i]==1) :
            flag = False
            for j in range(len(target)):
                if(target[j] == i):
                    flag = True
                    break
            
            if(not flag) :
                result += 1
    i+=1
print(result)

 

寻找最优的路测线路

  • 给定一个m行、n列的数组(路线网络),每个值代表当前位置的信号质量,越大信号越好;
  • 从 [0, 0] 到 [m-1, n-1]位置的路线中,最小值代表当前路线的评分,如8->4->5->9的评分为4;
  • 每个位置可以走向上下左右四个方向,不能对角;
  • 找出一个网络中的最优路线的评分;
    输入描述:
    第一行输入行数m;
    第二行输入列数n;
    第三行开始,每行为信号值s;
    1< m,n <20
    1 < s <65535
    输出描述:
    最优路线的评分

示例1
输入:
3
3
5 4 5
1 2 6
7 4 6
输出:
4

示例2
输入:
6
5
3 4 6 3 4
0 2 1 1 7
8 8 3 2 7
3 2 4 9 8
4 1 2 0 0
4 6 5 4 3
输出:
3

思路: 关注每条路线的最小值

  • s值从最小值(1)开始,深度优先遍历数组;
  • 若能找到信号质量均大于等于s的路线(深度优先返回True),即存在评分为当前s值的路线,则s+1 继续下一轮的深度优先遍历(查找是否有s+1评分的路线);
  • 否则,即不存在评分为s值的路线,停止循环;
  • 输出此时的s-1
    每次s+1的方式也可使用二分法,取值(low+high)// 2

class OptimizePath:
    def solution(self, m, n, arr):
        """
        :param m: 行数
        :param n: 列数
        :param arr: 二维数组
        :return:
        """
        s_val = 1 # 从信号质量最小值开始
        visited = [[0 for j in range(n)] for i in range(m)]
        while True:
            # 每次 深度优先遍历,重置访问标记
            for i in range(m):
                for j in range(n):
                    visited[i][j] = 0

            # 搜索评分为s_val的路线
            if self.dfs(0, 0, m, n, s_val, arr, visited):
                s_val += 1
            else:
                print("miss:", s_val)
                break
        print(s_val-1)

    def dfs(self, start_row, start_col, row, col, s_val, arr, visited):
        """
        :param start_row: 起始位置的行
        :param start_col: 起始位置的列
        :param row: 总行数
        :param col: 总列数
        :param s_val: 当前信号质量
        :param arr: 网络数据,二维数组
        :param visited: 访问标记, 二维数组
        :return:
        """
        # 起始点为最后一个位置,直接返回True
        if start_row == row - 1 and start_col == col - 1:
            return True
        elif s_val > arr[start_row][start_col]:
            # 搜索失败,直接返回False
            return False

        # 正常开始搜索
        visited[start_row][start_col] = 1 # 标记当前位置为已访问
        # 从四个方向开始搜索
        directions = [(start_row, start_col-1), (start_row, start_col+1), (start_row-1, start_col), (start_row+1, start_col)]
        for next_row, next_col in directions:
            # 当前位置有效且未访问
            if next_row >= 0 and next_row < row and next_col >= 0 and next_col < col and \
                visited[next_row][next_col] == 0 and arr[next_row][next_col] >= s_val:
                if self.dfs(next_row, next_col, row, col, s_val, arr, visited):
                    return True # 表示可以搜索到当前s_val评分的路线

        # 未搜索到s_val评分的路线
        return False


if __name__ == '__main__':
    op_path = OptimizePath()
    while True:
        try:
            m = int(input().strip())
            n = int(input().strip())
            arr = []
            for i in range(m):
                arr.append(list(map(int, input().strip().split())))

            op_path.solution(m, n, arr)
        except KeyboardInterrupt:
            break

 

运输时间

  • m辆车要在一条不能超车的单行道行驶,距离长度为n;
  • 速度快的车追上前车后,以前车速度继续行驶;
  • 每辆车固定间隔1小时触发,如第一辆0时出发,第二辆1时出发,依次类推;
  • 求最后一辆车到达终点的花费时间;
    输入描述:
    第一行输入m,n 分别表示车辆数、终点距离,空格隔开
    1<m<20
    1<n<400
    0<s<30
    第二行开始,每行为一辆车的速度值;
    输出描述:
    最后一辆车到达终点花费的时间

示例1
输入:
2 11
3
2
输出:
5.5

示例2
输入:
3 11
3
2
4
输出:
4.5

示例3
输入:
3 20
4
5
6
输出:
3.3333

思路:

  • 在前一辆车到达终点前,后一辆车能否追上?
    • 能追上,则 t = t_前 - 1
    • 不能追上,则 t = s/v
  • 动态规划
# __author__ = "laufing"


class TransmitTime:
    def solution(self, speeds, n):
        """
        :param speeds: m辆车的速度列表
        :param n: 总距离
        :return:
        """
        m = len(speeds)
        result = 0
        for i in range(m):
            if i == 0: # 第一辆车不受影响
                result = n / speeds[i]
            elif n / speeds[i] > result - 1: # 追不上
                result = n / speeds[i]
            else: # 在一辆车到达终点前,后一辆追得上
                result -= 1
        print(result)


if __name__ == '__main__':
    transmit_time = TransmitTime()
    while True:
        try:
            m, n = list(map(int, input().strip().split()))
            speeds = []
            for i in range(m):
                speeds.append(int(input().strip()))
            transmit_time.solution(speeds, n)
        except KeyboardInterrupt:
            break

 

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
华为OD机试-2023真题主要考察了以下几个方面的知识点: 1. 数据结构与算法:题目涉及了常见的数据结构和算法,如数组、链表、树、图、排序、搜索等。要求考生熟悉这些数据结构的基本操作和常用算法的实现方法。 2. 编程语言:题目要求使用C++或Java语言完成编程任务,要求考生熟悉相应语言的语法和常用的库函数使用方法。 3. 网络通信:题目涉及了网络通信相关的知识点,如TCP/IP协议、HTTP协议、socket编程等。要求考生了解网络通信的基本概念和实现方式。 4. 操作系统:题目要求考生熟悉操作系统相关的知识,如进程管理、内存管理、文件系统等。要求考生了解操作系统的基本功能和实现原理。 5. 数据库:题目涉及了数据库相关的知识点,如SQL语句的编写、数据库的设计和优化等。要求考生具备数据库的基本操作和设计能力。 6. 设计模式:题目要求考生能够根据给定的需求设计相应的对象和类,并且符合设计模式的原则。要求考生熟悉常见的设计模式和其应用场景。 7. 系统设计与架构:题目要求考生从整体上设计和实现一个系统,并考虑系统的性能、可扩展性等因素。要求考生了解系统设计的基本原则和方法。 以上是华为OD机试-2023真题的一些考点分类。考生在复习备考时,可以根据这些考点有针对性地进行学习和练习,提升自己的应试能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

laufing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值