华为机试-算法一

文章讲述了如何使用Python编写函数,根据身高差对小学生身高进行排序,并在围棋问题中计算黑棋和白棋的气数。涉及连续自然数之和的表达式计算。
摘要由CSDN通过智能技术生成

寻找身高相近的小朋友

小明今年升学到了小学1年纪来到新班级后,发现其他小朋友身高参差不齐
然后就想基于各小朋友和自己的身高差,对他们进行排序请帮他实现排序
输入描述
第一行为正整数 h和n
0<h<200 为小明的身高
0<n<50 为新班级其他小朋友个数
第二行为n各正整数
h1 ~ hn分别是其他小朋友的身高
取值范围0<hi<200
且n个正整数各不相同
输出描述
输出排序结果,各正整数以空格分割
和小明身高差绝对值最小的小朋友排在前面
和小明身高差绝对值最大的小朋友排在后面
如果两个小朋友和小明身高差一样
则个子较小的小朋友排在前面

    示例一
    输入
    100 10
    95 96 97 98 99 101 102 103 104 105
    输出
    99 101 98 102 97 103 96 104 95 105

    说明  小明身高100
    班级学生10个  身高分别为95 96 97 98 99 101 102 103 104 105,
    按身高差排序后结果为:99 101 98 102 97 103 96 104 95 105。

    输入
    100 10
    101 102 103 104 105 96 97 95 99 98
def sort_children_by_height_diff(h, n, children_heights):  
    # 将小明的身高加入到小朋友的身高列表中  
    children_heights.append(h)  
      
    # 根据身高差对小朋友进行排序  
    sorted_heights = sorted(children_heights, key=lambda x: abs(x - h) if x != h else float('inf'))  
      
    # 移除小明的身高  
    sorted_heights.remove(h)  
      
    # 将排序后的身高列表转换为字符串,以空格分隔  
    sorted_str = ' '.join(map(str, sorted_heights))  
      
    return sorted_str  
  
# 读取输入  
h, n = map(int, input().split())  
children_heights = list(map(int, input().split()))  
  
# 输出排序结果  
print(sort_children_by_height_diff(h, n, children_heights))

解释:

  1. sort_children_by_height_diff函数接收三个参数:小明的身高h,小朋友的个数n,以及小朋友的身高列表children_heights。
    首先将小明的身高加入到小朋友的身高列表中,以便一起进行排序。
    使用sorted函数对小朋友的身高进行排序,排序的关键在于计算每个小朋友与小明的身高差,并按照身高差进行排序。如果身高差相同,则按照身高本身进行排序(身高较小的排在前面)。这里使用lambda表达式来定义排序的关键字。
    排序完成后,从排序后的身高列表中移除小明的身高。
    最后将排序后的身高列表转换为字符串,以空格分隔,并返回该字符串作为排序结果。
    在主程序中,首先读取输入的小明身高、小朋友个数和小朋友身高列表。然后调用sort_children_by_height_diff函数进行排序,并输出排序结果。

围棋的气

围棋棋盘由纵横各19条线垂直相交组成,棋盘上一共19x19=361个交点,对弈双方一方执白棋,一方执黑棋,落子时只能将棋子置于交点上。
“气”是围棋中很重要的一个概念,某个棋子有几口气,是指其上下左右方向四个相邻的交叉点中,有几个交叉点没有棋子,由此可知:
1、在棋盘的边缘上的棋子最多有3口气(黑1),在棋盘角点的棋子最多有2口气(黑2),其它情况最多有4口气(白1)
2、所有同色棋子的气之和叫作该色棋子的气,需要注意的是,同色棋子重合的气点,对于该颜色棋子来说,只能计算一次气,比如下图中,黑棋一共4口气,而不是5口气,因为黑1和黑2中间红色三角标出的气是两个黑棋共有的,对于黑棋整体来说只能算一个气。
3、本题目只计算气,对于眼也按气计算,如果您不清楚“眼”的概念,可忽略,按照前面描述的规则计算即可。
现在,请根据输入的黑棋和白棋的坐标位置,计算黑棋和白起一共各有多少气?
输入描述:
输入包括两行数据,如:
0 5 8 9 9 10
5 0 9 9 9 8
1、每行数据以空格分隔,数据个数是2的整数倍,每两个数是一组,代表棋子在棋盘上的坐标;
2、坐标的原点在棋盘左上角点,第一个值是行号,范围从0到18;第二个值是列号,范围从0到18。
3、举例说明:第一行数据表示三个坐标(0,5)、(8,9)、(9,10)
4、第一行表示黑棋的坐标,第二行表示白棋的坐标。
5、题目保证输入两行数据,无空行且每行按前文要求是偶数个,每个坐标不会超出棋盘范围。
输出描述:
8 7
两个数字以空格分隔,第一个数代表黑棋的气数,第二个数代表白棋的气数。
补充说明:
示例1
输入:
0 5 8 9 9 10
5 0 9 9 9 8
输出:
8 7
说明:
如果将输入数据放到棋盘上,数数黑棋一共8口气:
数数白棋一共7口气:

解题思路
解题思路:

创建一个19x19的二维数组表示棋盘,初始化为0,表示空点。
根据输入,将黑棋和白棋的坐标放入棋盘,并标记为1表示黑棋,2表示白棋。
遍历棋盘,对于每个非空点,检查其上下左右四个方向的相邻点,计算该点的气数。
统计黑棋和白棋的总气数。
输出结果。
题解代码
Python题解代码

def counting(alias, enemy):
    count = set(alias)
    for a in alias:
        x, y = map(int, a.split("_"))
        if x > 0:
            count.add(f"{x - 1}_{y}")
        if x < maxSide:
            count.add(f"{x + 1}_{y}")
        if y > 0:
            count.add(f"{x}_{y - 1}")
        if y < maxSide:
            count.add(f"{x}_{y + 1}")

    res = len(count) - len(alias)
    for e in enemy:
        if e in count:
            res -= 1
    return res


locBlacks = input().split()
locWhites = input().split()
blacks = [f"{locBlacks[i]}_{locBlacks[i + 1]}" for i in range(0, len(locBlacks), 2)]
whites = [f"{locWhites[i]}_{locWhites[i + 1]}" for i in range(0, len(locWhites), 2)]
maxSide = 18
print(counting(blacks, whites), counting(whites, blacks))

Python题解代码讲解
函数定义:

counting(alias, enemy): 该函数用于计算棋子的气数。

alias: 表示当前颜色(黑或白)的棋子坐标列表。

enemy: 表示对方颜色的棋子坐标列表。

函数首先将当前颜色的棋子坐标添加到count集合中,然后遍历每个棋子,根据其上下左右四个方向的相邻点,将相邻点的坐标添加到count中。最后,通过计算集合的大小减去当前颜色棋子的个数,得到当前颜色棋子的总气数。

输入处理:

通过input().split()读取输入,得到黑棋和白棋的坐标字符串数组locBlacks和locWhites。

将坐标字符串数组转换为坐标列表blacks和whites,其中每个坐标使用{row}_{col}的格式表示。

调用counting函数计算黑棋和白棋的总气数,并输出结果。

用连续自然数之和来表达整数

一个整数可以由连续的自然数之和来表示。给定一个整数,计算该整数有几种连续自然数之和的表达式,且打印出每种表达式。
注意!答案仅作为参考(实际考试中下列代码通过用例100%,但不代表最优解)
一个整数可以由连续的自然数之和来表示给定一个整数计算该整数有几种连续自然数之和的表达式并打印出每一种表达式。

输入描述
一个目标整数t 1<= t <=1000

输出描述
1.该整数的所有表达式和表达式的个数
如果有多种表达式,自然数个数最少的表达式优先输出
2.每个表达式中按自然数递增输出

具体的格式参见样例
在每个测试数据结束时,输出一行"Result:X"
其中X是最终的表达式个数
输入
9

输出
9=9
9=4+5
9=2+3+4
Result:3

说明 整数9有三种表达方法:

示例二
输入
10
输出
10=10
10=1+2+3+4
Result:2

题目解析

本题可以考虑使用滑动窗口 比如输入 9,则生成一个数组 arr = [1,2,3,4,5,6,7,8,9].然后用 left、right 指针同时指向 arr 的索引 0,并取 arr[O]为初始 sum 值 left 指针和 right 指针的移动逻辑如下
在这里插入图片描述
right 指针从左向右开始移动,每移动一次就计算 left~right 之间的子数组和赋值给 sum, 并且判断:

sum > target 若 true,则 left++,sum-=arr[left]

sum === target,若true,则保存此时的子数组到res中,然后right++,计算sum+=arr[right]。

sum < target,若 true,则 right++,计算 sum+=arr[right]

当 right 和 left 都移动到数组尾部时,结束

输入
t = int(input())
print(t)
输出
def result():
    arr = [i+1 for i in range(t)]
    ans = []
    l = 0
    r = 1
    total = arr[l]
    while l < t:
        if total > t:
            total -= arr[l]
            l += 1
        elif total == t:
            ans.append(arr[l:r])
            # 然后挪动指针
            total -= arr[l]
            l += 1
            if r>=t:
                # 单个都大
                break
            else:
                total += arr[r]
                r += 1
        else:
            total += arr[r]
            r += 1
    ans.sort(key=lambda x:len(x))
    for i in ans:
        print(f"{t}={'+'.join(map(str,i))}")
    print(f"Result:{len(ans)}")
t = 9
result()
输出
9=9
9=4+5
9=2+3+4
Result:3
def find_continuous_sequences(target):
    result = []
    for i in range(target):
        nums = i + 1
        if 2 * target % nums == 0:
            left = 2 * target // nums - i
            if left <= 0:
                break
            if left % 2 == 0:
                result.append(list(range(left // 2, left // 2 + i + 1)))

    return result

def main():
    target = int(input())
    sequences = find_continuous_sequences(target)

    for seq in sequences:
        print(f"{target}={'+'.join(map(str, seq))}")

    print(f"Result:{len(sequences)}")

if __name__ == "__main__":
    main()

在这里插入图片描述

  • 31
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值