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

目录

问题 A: 二分搜索(递归)

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

问题 C: 例题6-3 冒泡排序

问题 D: 随机数

问题 E: 快速排序

 问题 F: 随机化快速排序

问题 G: 二分搜索升级版

问题 H: Strange function


问题 A: 二分搜索(递归)

题目描述:
使用递归算法,实现二分搜索。

输入:
多组数据输入,每组第一个数字为数组的长度n,然后输入n个整数,最后输入待查询的值。

输出:

输出待查询值所在的位置,如果没有找到,则返回-1。

思路:经典的二分,模板。

def half(x: int, start: int, end: int):
    if start <= end:
        mid = (start + end) // 2
        if nums[mid] == x:
            return mid + 1
        elif nums[mid] < x:
            return half(x, mid + 1, end)
        else:
            return half(x, start, mid - 1)
    return -1


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

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

题目描述:

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

输入:
多组数据输入,每组第一个数字为数组的长度n,然后输入n个整数,最后输入待查询的值。

输出:

输出待查询值所在的位置,如果没有找到,则返回-1。

思路:二分搜索很容易改成非递归,因为二分搜索根本上就是区间的迭代和中间值的判断。

def half(x: int, start: int, end: int):
    while start <= end:
        mid = (start + end) // 2
        if nums[mid] == x:
            return mid + 1
        elif nums[mid] < x:
            start = mid + 1
        else:
            end = mid - 1
    return -1


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

问题 C: 例题6-3 冒泡排序

题目描述:

从键盘上输入10个整数,用冒泡法对这10个数进行排序(由小到大)。【必须使用冒泡排序实现】

输入:

以空格分隔的10个整数 

输出:

依次输出排好序的10个整数,每个数占一行。

每日一偷鸡:

nums = [int(i) for i in input().split()]
nums.sort()
for num in nums:
    print(num)

思路:经典的冒泡排序,利用标签flag,当提前排好的时候及时退出。

nums = [int(i) for i in input().split()]
for i in range(9):
    flag = True
    for j in range(10 - i - 1):
        if nums[j] > nums[j + 1]:
            nums[j], nums[j + 1] = nums[j + 1], nums[j]
            flag = False
    if flag:
        break
for num in nums:
    print(num)

问题 D: 随机数

题目描述:

有一个rand(n)的函数,它的作用是产生一个在[0,n)的随机整数。现在有另外一个函数,它的代码如下:

int random(int n, int m)

{

         return rand(n)+m;

}

显而易见的是函数random(n,m)可以产生任意范围的随机数。现在问题来了,如果我想要产生范围在[a,b)内的一个随机数,那么对应的n,m分别为多少?

输入:

输入的第一行为一个正整数T (T<=1000),表示一共有T组测试数据。

对于每组测试数据包含两个整数a,b (a<=b)。

输出:

对于每组测试数据,输出一行包含两个整数n和m,两个整数中间有一个空格分隔。

 思路:找规律,很简单,a就是m的值,a、b区间的大小就是n的值。

t = int(input())
while t > 0:
    a, b = map(int, input().split())
    print(b - a, a)
    t -= 1

问题 E: 快速排序

题目描述:

编程实现快速排序算法,深入理解快速排序算法的基本思想。

输入:

多组输入,每组第一个数字为数组长度,然后输入一个一维整型数组。

输出:

输出快速排序之后的一维整型数组(升序)

思路:了解快速排序的思想,稍微背一背应用不难。

def quick(start: int, end: int):
    if start <= end:
        i, j = start, end
        res = nums[start]   # 选择基准
        while True:
            while j > i and nums[j] >= res:
                j -= 1
            while i < j and nums[i] <= res:
                i += 1
            if i < j:
                nums[i], nums[j] = nums[j], nums[i]
            else:
                nums[start], nums[j] = nums[j], nums[start]
                break
        quick(start, j - 1)
        quick(j + 1, end)


while True:
    try:
        nums = [int(i) for i in input().split()]
        n = nums.pop(0)
        quick(0, n - 1)
        for i in range(n):
            print("", nums[i], end='') if i != 0 else print(nums[i], end='')
        print()
    except:
        break

 问题 F: 随机化快速排序

题目描述:

使用Java或C++等语言中内置的随机函数实现随机化快速排序,在数组中随机选择一个元素作为分区的主元(Pivot)。

输入:

多组样例输入,每组由一个一维整型数组组成。

输出:

随机化快速排序之后的一维整型数组(升序排列)。

思路:经典快速排序的小变异,为了简化问题,先后对随机选取的基准的右方和左方进行快速排序,所以只要对经典快速排序的算法进行小改变就行。

import random


def quick(start: int, end: int):
    if start <= end:
        mid = random.randint(start, end)  # 基准的下标
        res, small, big = nums[mid], end, mid  # 记录基准,为简化问题,分别对基准的左右进行快速排序,先对右边
        # print(res)
        while True:  # 对右边快速排序,先找比基准小的数
            while small > big and nums[small] >= res:
                small -= 1
            while big < small and nums[big] <= res:
                big += 1
            if big < small:
                nums[small], nums[big] = nums[big], nums[small]
            else:
                nums[mid], nums[small], mid, small, big = nums[small], res, small, small - 1, start
                break
        # print(nums)
        while True:  # 与右边快速排序类似,不过要先找比基准大的数
            while big < small and nums[big] <= res:
                big += 1
            while small > big and nums[small] >= res:
                small -= 1
            if big < small:
                nums[small], nums[big] = nums[big], nums[small]
            else:
                if nums[mid] < nums[big]:  # 与右边快速排序不同,左边只有满足最后一个数比基准大的时候才交换
                    nums[mid], nums[big], mid = nums[big], res, big
                break
        # print(nums)
        quick(start, mid - 1)
        quick(mid + 1, end)
    return


while True:
    try:
        nums = [int(i) for i in input().split()]
        n = nums.pop(0)
        quick(0, n - 1)
        for i in range(n):
            print("", nums[i], end='') if i != 0 else print(nums[i], end='')
        print()
    except:
        break

问题 G: 二分搜索升级版

题目描述:

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

输入:

多组数据输入,每组第一个数字为数组的长度n,然后输入n个整数,最后输入带查询的值x。

输出:

输出小于x的最大元素的位置i和大于x的最小元素的位置j;当待搜索元素x在数组中时,返回的i和j相同,均为x在数组中的位置

思路:想清楚下标的意义即可,注意下标加一。

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


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

问题 H: Strange function

题目描述:

Now, here is a function:
F(x) = 6 * x^7+8*x^6+7*x^3+5*x^2-y*x (0 <= x <=100)
Can you find the minimum value when x is between 0 and 100.

输入:

The first line of the input contains an integer T(1<=T<=100) which means the number of test cases. Then T lines follow, each line has only one real numbers Y.(0 < Y <1e10)

输出:

Just the minimum value (accurate up to 4 decimal places),when x is between 0 and 100.

def f(x: float):
    return 6 * (x ** 7) + 8 * (x ** 6) + 7 * (x ** 3) + 5 * (x ** 2) - x * y


def three():
    start, end = 0, 100
    while end - start > 0.0001:
        mid = (start + end) / 2
        midmid = (mid + end) / 2
        if f(mid) < f(midmid):
            end = midmid
        else:
            start = mid
    print("%.4f" % f(end))


t = int(input())
while t > 0:
    y, t = int(input()), t - 1
    three()
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我可以为您讲解一下 HNUCM 最小生成树(Prim)的算法过程。 首先,Prim 算法是一种贪心算法,用于求解带权无向连通图的最小生成树。下面是具体的算法过程: 1. 选取任意一个顶点作为起点,将其加入到生成树中。 2. 找到与已经加入到生成树中的顶点相邻的所有顶点,并计算它们与生成树的距离。 3. 从这些顶点中选取距离最小的顶点,将其加入到生成树中。 4. 重复步骤2和3,直到生成树中包含了所有的顶点。 在具体实现时,可以使用一个数组来记录每个顶点是否已经加入到生成树中,以及另一个数组来记录每个顶点与生成树的距离。每次选择距离最小的顶点时,可以使用一个最小堆来优化。 至于 HNUCM 最小生成树 Prim 算法的具体实现,可以参考以下代码: ```python import heapq def prim(graph): n = len(graph) visited = [False] * n distance = [float('inf')] * n distance[0] = 0 heap = [(0, 0)] result = 0 while heap: (d, u) = heapq.heappop(heap) if visited[u]: continue visited[u] = True result += d for v, weight in graph[u]: if not visited[v] and weight < distance[v]: distance[v] = weight heapq.heappush(heap, (weight, v)) return result ``` 这段代码实现了 HNUCM 最小生成树 Prim 算法的过程,其中 graph 是一个邻接表表示的带权无向连通图,每个元素是一个二元组 (v, w),表示从节点 u 到节点 v 有一条边权为 w 的边。算法的返回值是最小生成树的总权值。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值