HNUCM-2022年秋季学期《算法分析与设计》练习4

python版本答案,非递归。

目录

问题 A: 字符识别?

问题 B: 小波的金字塔

问题 C: 外观数列

问题 D: 2的个数

问题 E: 互异字符串

 问题 F: 二分搜索(非递归)

问题 G: 二分搜索升级版

问题 H: 好老师


问题 A: 字符识别?

题目描述:

你的任务是写一个程序进行字符识别。别担心,你只需要识别1, 2, 3,如下:

.*.  ***  ***

.*.  ..*  ..*

.*.  ***  ***

.*.  *..  ..*

.*.  ***  ***

思路:找三个字符不同的关键点,即可简化检测,1:第二行中间为*,2:第四行左侧为*,3:第四行右侧为*。

while True:
    try:
        n = int(input())
        maze = [input() for _ in range(5)]
        # print(maze)
        for i in range(1, 4 * n + 1, 4):
            if maze[1][i] == '*':
                print(1, end='')
            elif maze[3][i - 1] == '*':
                print(2, end='')
            elif maze[3][i + 1] == '*':
                print(3, end='')
        print()
    except:
        break

问题 B: 小波的金字塔

题目描述:

继2019高考数学卷的维纳斯之后,2020高考卷的胡夫金字塔又引起了一股热议,5G冲浪的小波立马去看了看全国一卷胡夫金字塔那道题。于是小波突发奇想,在此基础上改编为了一道编程题。
埃及胡夫金字塔是古代世界建筑奇迹之一,它的形状可视为一个正四棱锥,以该四棱锥的高h为边长的正方形面积等于该四棱锥一个侧面三角形的面积。给出该四棱锥的高h,求该四棱锥体积v。

思路:利用变量解出底面边长的关系式,设底面边长为2x,可得 

x ** 2 = h ** 2 * (-1 + (5 ** 0.5)) / 2 

 注意输入可能为小数。

t = (-1 + 5 ** 0.5) / 2
h = float(input())
x = t * (h ** 2)
res = (4 * x * h) / 3
print("%.2f" % res)

问题 C: 外观数列

题目描述:

给定一个正整数 n ,请设计一个递归算法输出外观数列的第 n 项,「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。
前五项如下:
 
1.     1
2.     11
3.     21
4.     1211
5.     111221
第一项是数字 1
描述前一项,这个数是 1 即 “ 一 个 1 ”,记作 "11"
描述前一项,这个数是 11 即 “ 二 个 1 ” ,记作 "21"
描述前一项,这个数是 21 即 “ 一 个 2 + 一 个 1 ” ,记作 "1211"
描述前一项,这个数是 1211 即 “ 一 个 1 + 一 个 2 + 二 个 1 ” ,记作 "111221"

思路:数数字,边数边计。数到不一样的就描述之前数了多少个一样的,以此类推。

def say(string: str):
    length = len(string)
    cnt = 1
    res = ''
    for i in range(length):
        if i == length - 1 or string[i] != string[i + 1]:
            res = res + f'{cnt}{string[i]}'
            cnt = 1
        else:
            cnt += 1
    # print(res)
    return res


strings = ['-', '1', '11', '21', '1211', '111221']
for _ in range(6, 31):
    strings.append(say(strings[-1]))
while True:
    try:
        n = int(input())
        print(strings[n])
    except:
        break

问题 D: 2的个数

题目描述:

请编写一个程序,输出0到n(包括n)中数字2出现了几次。

思路:简单的遍历一下数字中有多少2就行

def cnt(x: int):
    res = 0
    while x > 0:
        if x % 10 == 2:
            res += 1
        x = x // 10
    return res


while True:
    try:
        n = int(input())
        cc = 0
        for i in range(n + 1):
            cc += cnt(i)
        print(cc)
    except:
        break

问题 E: 互异字符串

题目描述:

请实现一个算法,确定一个字符串的所有字符是否全都不同。

给定一个字符串,请返回一个True代表所有字符全都不同,False代表存在相同的字符。

思路:利用集合的特性,快速判断。

while True:
    try:
        strings = input()
        check = set(list(strings))
        print(True) if len(check) == len(strings) else print(False)
    except:
        break

 问题 F: 二分搜索(非递归)

题目描述:

使用非递归算法,实现二分搜索。

思路:利用index函数简单的实现查找

while True:
    try:
        nums = list(map(int, input().split()))
        n, x = nums.pop(0), nums.pop()
        # print(n, x)
        print(nums.index(x) + 1) if x in nums else print(-1)
    except:
        break

问题 G: 二分搜索升级版

题目描述:

设a[0:n-1]是已排好序的数组。请改写二分搜索算法,使得当待搜索元素x不在数组中时,返回小于x的最大元素的位置i和大于x的最小元素的位置j;当待搜索元素x在数组中时,返回的i和j相同,均为x在数组中的位置

思路:经典的二分查找,注意下标加一

def half(s: int, start: int, last: int):
    if start <= last:
        mid = (start + last) // 2
        if nums[mid] > s:
            return half(s, start, mid - 1)
        if nums[mid] < s:
            return half(s, mid + 1, last)
        if nums[mid] == s:
            return mid + 1, mid + 1
    if last == -1:
        return -1, start + 1
    if start >= n:
        return start, -1
    return last + 1, start + 1


while True:
    try:
        nums = list(map(int, input().split()))
        n, x = nums.pop(0), nums.pop()
        i, j = half(x, 0, n - 1)
        print(i, j)
    except:
        break

问题 H: 好老师

题目描述:

我想当一个好老师,所以我决定记住所有学生的名字。可是不久以后我就放弃了,因为学生太多了,根本记不住。但是我不能让我的学生发现这一点,否则会很没面子。所以每次要叫学生的名字时,我会引用离他最近的,我认得的学生。比如有10个学生:

A ? ? D ? ? ? H ? ?

想叫每个学生时,具体的叫法是: 

思路:从叫到的同学开始,如果记得名字就直接输出名字,否则就向左右遍历,直到找到认识的同学。

def find(x: int):
    i, j = x, x
    while i >= 0 or j < n:
        i, j = i - 1, j + 1
        if i >= 0 and j < n and names[i] != '?' and names[j] != '?':
            return f"middle of {names[i]} and {names[j]}"
        if i >= 0 and names[i] != '?':
            return "right of " * (x - i) + names[i]
        if j < n and names[j] != '?':
            return "left of " * (j - x) + names[j]


n = int(input())
names = input().strip().split()
# print(names)
for _ in range(int(input())):
    p = int(input())
    if names[p - 1] != '?':
        print(names[p - 1])
    else:
        print(find(p - 1))
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值