算法设计与分析-习题4.5

目录

1.

[a.如果我们用第二个参数n的规模来度量m和n的最大公约数问题的实例规模,在用欧几里得算法计算 gcd(m,n)时,实例的规模会消减多少?](#a.如果我们用第二个参数n的规模来度量m和n的最大公约数问题的实例规模,在用欧几里得算法计算 gcd(m,n)时,实例的规模会消减多少?)

b.请证明,在欧几里得算法做了两次连续的迭代以后,实例的规模总是会至少消去一个大于2的因子。

[2. 应用快速选择算法求数列9,12,5,17,20,30,8的中位数。](#2. 应用快速选择算法求数列9,12,5,17,20,30,8的中位数。)

3.请写出非递归快速选择算法的伪代码。

4.推导插值查找算法的公式。

5.给出插值查找最差输入的一个例子,并说明该算法在最差情况下是线性的。

6.

[a. 为了使log₂log₂n+1大于6, n的最小值是多少?](#a. 为了使log₂log₂n+1大于6, n的最小值是多少?)

b.下列断言中哪些是正确的?

7.

a.描述一个在二叉查找树中寻找最大键的算法。你会把你的算法归类为减可变规模算法吗?

b.你的算法在最坏情况下的效率类型是哪一种?

8.

a.描述一个在二叉查找树中删除一个键的算法。你会把你的算法归类为减可变规模算法吗?

b.你的算法在最坏情况下的效率类型是哪一种?

9.对于所有顶点连通度都是偶数的连通图,给出构造其欧拉回路的减可变规模算法。

[10.另类单堆拈游戏 请考虑这个另类的单堆拈游戏,它规定谁拿走最后一个棋子就输了。该游戏的其他条件都不变,即该堆棋子有n个,每次每个玩家最多拿走m个,最少拿走 1 个棋子。请指出该游戏的胜局和败局(对于接下来要走的玩家来说)是怎样的?](#10.另类单堆拈游戏 请考虑这个另类的单堆拈游戏,它规定谁拿走最后一个棋子就输了。该游戏的其他条件都不变,即该堆棋子有n个,每次每个玩家最多拿走m个,最少拿走 1 个棋子。请指出该游戏的胜局和败局(对于接下来要走的玩家来说)是怎样的?)

11.

[a.坏巧克力 两个玩家轮流掰一块m×n格的巧克力,其中一块1×1的小块是坏的。每次掰只能顺着方格的边界,沿直线一掰到底。每掰一次,掰的人把两块中不含坏巧克力的那块吃掉,谁碰到最后那块坏巧克力就算输了。在这个游戏中,先走好还是后走好?](#a.坏巧克力 两个玩家轮流掰一块m×n格的巧克力,其中一块1×1的小块是坏的。每次掰只能顺着方格的边界,沿直线一掰到底。每掰一次,掰的人把两块中不含坏巧克力的那块吃掉,谁碰到最后那块坏巧克力就算输了。在这个游戏中,先走好还是后走好?)

[12.翻薄饼 有n张大小各不相同的薄饼,一张叠在另一张上面。允许大家把一个翻板插到一个薄饼下面,然后可以把板上面的这叠薄饼翻个身。我们的目标是根据薄饼的大小重新安排它们的位置,最大的饼要放在最下面。大家可以在网站"Interactive Mathematics Miscellany and Puzzles"(交互式的数学杂题和智力游戏)上找到该游戏的一个动态演示([Bogl)。设计一个算法来解这个谜题。](#12.翻薄饼 有n张大小各不相同的薄饼,一张叠在另一张上面。允许大家把一个翻板插到一个薄饼下面,然后可以把板上面的这叠薄饼翻个身。我们的目标是根据薄饼的大小重新安排它们的位置,最大的饼要放在最下面。大家可以在网站“Interactive Mathematics Miscellany and Puzzles”(交互式的数学杂题和智力游戏)上找到该游戏的一个动态演示([Bogl)。设计一个算法来解这个谜题。)

13.假设需要在一个n×n矩阵中搜索一个给定数字,该矩阵每行每列都按升序排列。你能为这个问题设计一个O(n)算法吗?([Laa10])


1.

a.如果我们用第二个参数n的规模来度量m和n的最大公约数问题的实例规模,在用欧几里得算法计算 gcd(m,n)时,实例的规模会消减多少?

规模从 n 变成 m mod n,

m mod n < n规模至少减少到n-1。

b.请证明,在欧几里得算法做了两次连续的迭代以后,实例的规模总是会至少消去一个大于2的因子。

在前一个m%n=r的前提下,我们假设两种情况:

1.r<=n/2,则此时已经消去了至少2的因子

2.r>n/2,此时情况下,进行下一步取模,有r1=n%r,因为r>n/2,所以r1=n-r<n/2。此时也消减了2的因子

2. 应用快速选择算法求数列9,12,5,17,20,30,8的中位数。

数组:[9,12,5,17,20,30,8],pivot = 9

分区过程:

一:s=l,i=l+1;

12>9,则i+1

5<9,s+1, 然后A[s]与A[i]交换

随后的17,20,30都大于9,直到8小于9,s再+1,交换A[s]与A[i]

最后交换A[s]与A[l]

此时s=2,并不是中位数,因此从右边继续找第1个(4-(2+1))

第二轮后,s=4,则找左边的第1个

最终找到中位数12,s=3

3.请写出非递归快速选择算法的伪代码。

复制代码
算法:IterativeQuickSelect(A[0..n-1], k)
// 输入:数组A,整数k(1 ≤ k ≤ n)
// 输出:数组中第k小的元素
// 非递归快速选择,使用Lomuto划分

low ← 0
high ← n - 1

while low ≤ high do
    // 1. Lomuto 划分
    pivot ← A[high]         // 选最右侧元素为基准
    i ← low - 1             // 小于区指针
    
    for j ← low to high-1 do
        if A[j] ≤ pivot then
            i ← i + 1
            交换 A[i] 和 A[j]
    
    // 把基准放到正确位置
    交换 A[i+1] 和 A[high]
    pos ← i + 1             // 基准最终下标
    
    // 2. 判断目标位置
    if pos == k - 1 then    // 找到第k小
        return A[pos]
    else if pos > k - 1 then  // 目标在左半区
        high ← pos - 1
    else                    // 目标在右半区
        low ← pos + 1

// 理论上不会执行到这里
return -1

4.推导插值查找算法的公式。

通过两点之间直线:

代入给定y=v:移项求出x

5.给出插值查找最差输入的一个例子,并说明该算法在最差情况下是线性的。

数组元素呈指数增长 / 极小值在前,极大值在后

数组 A = [1, 2, 4, 8, 16, 32, 64, ..., 2ⁿ⁻¹],查找的 key = 2(数组里第二个元素)

此时:

从效果来看和顺序遍历没有区别了',每次计算出的 mid非常靠近 low ,查找区间每次只缩小 1 ,必须执行 n 次 比较。因此,最差时间效率为线性阶 O (n)

6.

a. 为了使log₂log₂n+1大于6, n的最小值是多少?

n>2^32

b.下列断言中哪些是正确的?

i. loglogn∈o(logn) ii. loglogn∈Θ(logn) iii. loglogn∈Ω(logn)

只有第一个是正确的,可以用极限得出差距

7.

a.描述一个在二叉查找树中寻找最大键的算法。你会把你的算法归类为减可变规模算法吗?

  • 从根节点出发。
  • 如果当前节点的右孩子不为空 ,就一直向右走
  • 当右孩子为空时,当前节点的键就是最大键

显然是减可变规模的,

  • 每一步都抛弃左子树 + 根 ,只保留右子树继续处理。
  • 问题规模每次都在减小,但减小多少不固定(取决于树的形状)。
  • 符合 ** 减可变规模(decrease-by-variable)** 算法的定义。

b.你的算法在最坏情况下的效率类型是哪一种?

树退化成一条右斜链(链表)。此时需要一直向右子树遍历,效率达到了Θ(n)

8.

a.描述一个在二叉查找树中删除一个键的算法。你会把你的算法归类为减可变规模算法吗?

设要删除节点为 p,其父节点为 parent

  1. **情况 1:p 是叶子节点(无孩子)**直接将父节点指向它的指针置空。
  2. **情况 2:p 只有一个孩子(左或右)**用其唯一孩子替代 p 的位置。
  3. 情况 3:p 有两个孩子
    • 找到 p 左子树的最大值(或右子树最小值)
    • 用这个值替换 p 的值
    • 再删除那个被复制的节点

是减可变规模的,

  • 删除操作每一步都会减少节点总数 1 个
  • 但查找节点、找前驱 / 后继的过程中,问题规模减小量不固定
  • 因此属于 减可变规模(decrease-by-variable)算法

b.你的算法在最坏情况下的效率类型是哪一种?

二叉查找树退化成斜树(链表)。

  • 查找要删除的节点:Θ(n)
  • 若有两个孩子,找前驱 / 后继:Θ(n)

9.对于所有顶点连通度都是偶数的连通图,给出构造其欧拉回路的减可变规模算法。

  • 任意顶点 出发,沿着未使用的边行走,直到回到起点,形成一个回路 C
  • 如果回路 C 包含了所有边,算法结束,C 就是欧拉回路。
  • 否则,在回路 C 中找到一个还有未使用边的顶点 u
  • 从 u 出发,用剩余边 构造一个新的回路 D
  • 把 D 插入到 C 中 u 的位置,合并成一个更大的回路。
  • 重复步骤 2--5,直到所有边都被使用。

显然是减可变规模的:

  • 每一步都删除已使用的边,问题规模(剩余边数)不断减小。
  • 每次减小的边数不固定(取决于找到的回路长度)。
  • 属于减可变规模(decrease-by-variable)

10.另类单堆拈游戏 请考虑这个另类的单堆拈游戏,它规定谁拿走最后一个棋子就输了。该游戏的其他条件都不变,即该堆棋子有n个,每次每个玩家最多拿走m个,最少拿走 1 个棋子。请指出该游戏的胜局和败局(对于接下来要走的玩家来说)是怎样的?

也就是把题目理解成n-1个,最后拿不到棋子的就输了,则n-1=k(m+1)时,先手必输,只要n!=k(m+1)+1则必赢

11.

a.坏巧克力 两个玩家轮流掰一块m×n格的巧克力,其中一块1×1的小块是坏的。每次掰只能顺着方格的边界,沿直线一掰到底。每掰一次,掰的人把两块中不含坏巧克力的那块吃掉,谁碰到最后那块坏巧克力就算输了。在这个游戏中,先走好还是后走好?

只有一种情况后手必胜:坏巧克力在左上角(1,1),且巧克力是正方形 m×m。 其余所有情况,先手都有必胜策略。

  • 坏巧克力把巧克力分成左 / 上 两条边:x(左边距离)、y(上边距离)
  • 游戏等价于取石子游戏 :两个堆 xy
  • 先手必胜:x ≠ y
  • 后手必胜:x = y(正方形且坏角在左上)

12.翻薄饼 有n张大小各不相同的薄饼,一张叠在另一张上面。允许大家把一个翻板插到一个薄饼下面,然后可以把板上面的这叠薄饼翻个身。我们的目标是根据薄饼的大小重新安排它们的位置,最大的饼要放在最下面。大家可以在网站"Interactive Mathematics Miscellany and Puzzles"(交互式的数学杂题和智力游戏)上找到该游戏的一个动态演示([Bogl)。设计一个算法来解这个谜题。

每次将当前最大的饼先翻到最上面,再翻到当前最底部,重复此过程,每次使问题规模减 1,直到全部有序。

  • 最多翻转次数:2n − 3
  • 时间效率:O(n²)

13.假设需要在一个n×n矩阵中搜索一个给定数字,该矩阵每行每列都按升序排列。你能为这个问题设计一个O(n)算法吗?([Laa10])

  • 设当前位置为 最右上角row = 0,col = n-1
  • row < n 且 col ≥ 0
    • 如果 当前值 == key → 找到,返回位置
    • 如果 当前值 > key向左走一列(排除当前列)
    • 如果 当前值 < key向下走一行(排除当前行)
  • 越界仍未找到 → 不存在

最多走 n 步向下 + n 步向左,最多是2n,效率为线性

相关推荐
样例过了就是过了2 小时前
LeetCode热题100 全排列
数据结构·c++·算法·leetcode·dfs
2401_898075122 小时前
分布式系统监控工具
开发语言·c++·算法
程序员夏末2 小时前
【LeetCode | 第六篇】算法笔记
笔记·算法·leetcode
OKkankan3 小时前
撕 STL 系列:封装红黑树实现 mymap 和 myset
java·c++·算法
xh didida3 小时前
数据结构--实现链式结构二叉树
c语言·数据结构·算法
ab1515173 小时前
3.15二刷基础90、105、106、110
数据结构·c++·算法
C蔡博士3 小时前
最近点对问题(Closest Pair of Points)
java·python·算法
白太岁3 小时前
算法:链表:指针变化与环
数据结构·算法·链表
寻寻觅觅☆3 小时前
东华OJ-进阶题-10-分解质因数(C++)
数据结构·c++·算法