第一章 引论

在豆瓣上有读者评论说这本书虽然数据结构在前,但实际上讲的更多的是算法分析。我也这么认为,这一章就在上来就先点明:

An important concept is that, in many problems, writing a working program is not good enough.

写出一个可以工作的程序并不够

 读到这里我就觉得这本书可能不是很适合我,在我目前的工作生涯中我没有过多的运用数据结构和算法分析的知识,而且如今ChatGPT工具的出现,很大的简化了应用层面开发的问题——在日常编程中只需要提问,就可以解决日常开发的的一般需求,而且高级的数据结构和算法已经都有很成熟的库可以很方便的调用。再去花时间来研读这些学生时期可以细细读的书性价比不是很大了。

我无比赞成我这个分析,但是还是准备来做这件事,目前还是挺有兴趣的。


🟦 引子

1.选择问题

Suppose you have a group of n numbers and would like to determine the kth largest. This is known as the selection problem.

两种解决方式:

  •  One way to solve this problem would be to read the n numbers into an array, sort the array in decreasing order by some simple algorithm such as bubblesort, and then return the element in position k
    解决这个问题的一种方法是将这 n 个数字读入一个数组中,使用一种简单的算法(如冒泡排序)将数组按降序排序,然后返回数组中第 k 个位置上的元素。

  • A somewhat better algorithm might be to read the first k elements into an array and sort them (in decreasing order). Next, each remaining element is read one by one. As a new element arrives, it is ignored if it is smaller than the kth element in the array. Otherwise, it is placed in its correct spot in the array, bumping one element out of the array. When the algorithm ends, the element in the kth position is returned as the answer.
    一个稍微更好的算法可能是将前 k 个元素读入一个数组中,并对它们进行排序(按照递减顺序)。接下来,逐个读取每个剩余的元素。当一个新元素到达时,如果它小于数组中第 k 个元素,则将其忽略。否则,它将被放置在数组中的正确位置,并将一个元素从数组中移出。当算法结束时,返回数组中第 k 个位置上的元素作为答案。

 书中首先diss这两个方法不是很好,当数据超过50万,这两个算法就很慢了。说在第七章介绍的算法可以在几秒中内解决这个问题。(真是吊足了胃口啊)

 2.字谜问题

A second problem is to solve a popular word puzzle.

The input consists of a two-dimensional array of letters and a list of words. The object is to find the words in the puzzle. These words may be horizontal, vertical, or diagonal in any direction. As an example, the puzzle shown in Figure 1.1 contains the words this, two, fat, and that. The word this begins at row 1, column 1 (1,1) and extends to (1, 4); two goes from (1, 1) to (3, 1); fat goes from (4, 1) to (2, 3); and that goes from (4, 4) to (1, 1)

仍然提供两种解决方式,并且提出这些解决方式随着数据量的增加效率会变得原来越慢。引出了上边的话:

Writing a working program is not good enough.


🟦 数学知识复习

 我想可以慢慢来写一下这些数学知识。数学公式在CSDN的编辑器上太难敲了

1.指数

X^{A}X^{B} = X^{A+B}

\frac{X^{A}}{X^{B}} = X^{A-B}

 (X^{A})^{B} = X^{AB}

X^{N}+X^{N}=2X^{N}\neq X^{2N}

2^{N}+2^{N}= 2^{N+1}

2.对数

在计算机这边除非特别声明,对数都是以2为底的。

对数这么定义的:

X^{A}=B当且仅当  \log_{X}B=A

由这个式子可以推出几个方便的等式:

\log_{A}B=\frac{\log_{C}A}{\log_{C}B};C>0

\log AB = \log A + \log B

\log A/B = \log A - \log B

\log( A^{B} )=B \log A

\log X < X (对所有的X>0成立)

\log 1 = 0,\log 2 = 1,\log 1024 = 10,\log 1 048 576 = 20

3.级数

由这个公式开始

S = \sum_{i=0}^{N} 2^i = 2^{N+1}-1

由2的级数再引入更一般的式子:

\sum_{i=0}^{N} A^i = \frac{A^{N+1}-1}{A-1}

在第二个公式中,如果0<A<1,则

\sum_{i=0}^{N} A^i \leqslant \frac {1}{1-A}

当N趋于无穷的时候,这个和趋向于1./(1-A),这些公式是【几何级数】公式。

提问AI:什么是几何级数公式?

书中还对上述公式进行了简单的证明,使用的是错位相消,就是利用  S-AS=1得到 S=\frac{1}{1-A}

算术级数

调和数

欧拉常数

 

欧拉常数又称欧拉-马斯克若尼常数,近似值为

γ≈0.57721 56649 01532 86060 65120 90082 40243 10421 59335

 


🟦 递归简论

递归目前在我的印象中是代码简单但是很占空间,并且有一些编写规则,一般是不采用这个方式写代码。

书中总结了递归的两个规则:

  1. Base cases.
    You must always have some base cases, which can be solved without recursion.
     
  2. Making progress.
    For the cases that are to be solved recursively, the recursive call must always be to a case that makes progress toward a base case.

列举了一个字典的例子,我觉得很棒:

As an example of a nonmathematical use, consider a large dictionary. Words in dictionaries are defined in terms of other words. When we look up a word, we might not always understand the definition, so we might have to look up words in the definition. Likewise, we might not understand some of those, so we might have to continue this search for a while. As the dictionary is finite, eventually either we will come to a point where we understand all of the words in some definition (and thus understand that definition and retrace our path through the other definitions), or we will find that the definitions are circular and we are stuck, or that some word we need to understand a definition is not in the dictionary.

作为一个非数学用途的例子,考虑一个大型词典。词典中的单词是以其他单词来定义的。当我们查找一个单词时,我们可能并不总是理解它的定义,因此我们可能需要查找定义中的其他单词。同样,我们可能也不理解其中一些单词,因此我们可能需要继续这个搜索一段时间。由于词典是有限的,最终要么我们会到达一个点,在这个定义中我们理解了所有的单词(从而理解了这个定义,并重新追溯我们通过其他定义的路径),要么我们会发现定义是循环的,我们被困住了,或者我们需要理解定义的某些单词不在词典中。 

另外还有一个打印数字的递归例子:

#include <stdio.h>

// 打印一个数字的每一位
void PrintDigit(int number) {
    printf("%d", number);
}

// 递归打印一个整数的每一位数字
void PrintOut(int nums) {
    if (nums >= 10) {
        PrintOut(nums / 10);  // 递归调用自身,直到数字不再大于等于 10
    }
    PrintDigit(nums % 10);  // 打印数字的个位数
}

int main() {
    PrintOut(123);  // 测试函数
    return 0;
}

递归的四个规则

When writing recursive routines, it is crucial to keep in mind the four basic rules of recursion:

1. Base cases. You must always have some base cases, which can be solved without recursion.

2. Making progress. For the cases that are to be solved recursively, the recursive call must always be to a case that makes progress toward a base case.

3. Design rule. Assume that all the recursive calls work.

4. Compound interest rule.(合成效益法则) Never duplicate work by solving the same instance of a problem in separate recursive calls.

1. 基本情况。你必须始终有一些基本情况,可以在不使用递归的情况下解决。

2. 进展性。对于需要递归解决的情况,递归调用必须始终朝着基本情况的方向取得进展。

3. 设计原则。假设所有的递归调用都能正常工作。

4. 复利规则。永远不要通过在单独的递归调用中解决相同问题的同一个实例来重复工作。

第四点,没有理解,给我的感觉就是不要重复的去递归解决简单的问题。下边是AI的看法:

在递归这个部分,书中有几个提出的点:

  • 取余操作很耗费很大
  • 用递归解决斐波那契数的简单数学问题不是很好的选择

我没有深究,后边章节慢慢探索,先将问题记在这里。


🟫 小结

这一章基本上就总结到这里,编写还是挺考验耐心的,数学公式方面确实编辑起来很别扭,所以后边没什么必要不会再添加数学公式。书中内容我是中英文两本书对照着看,有感兴趣的地方我会用ChatGPT来翻译英文粘贴到这里。有时候我也会问他一下AI的理解。这样感觉有点作弊和敷衍,但确实帮我省了不少的力气,我的目的是先完成对这本书的整体学习,希望能够坚持下去。不管怎样,很感谢网友们的阅读,如果对您有帮助的话就更好了。

  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值