从上往下打印二叉树(算法23)

问题:实现一个函数,输入二叉树,从上往下打印出二叉树的每个结点,同一层的结点按从左到右的顺序打印。 这道题有别于前序、中序、后序遍历二叉树的方法,该题是按层遍历二叉树。 原理: 不难理解,使用一个辅助空间,FIFO容器可以解决该问题。当遍历根结点后,分别把根结点的左右子树的根结点放到队列容器中。由于队列有FIFO特性,下次从队列中取出的元素一定是左子树的根结...

阅读全文

两个链表的第一个公共结点(算法37)

问题:已知两个单链表,它们公共部分,编程找出它们的第一个公共结点。 原理: 解决这个问题的一个直接的思路是遍历。对于第一个链表L1,每遍历一个结点,在第二个链表L2中从头到尾查找是否存在相等(is)的结点。这种方法的时间复杂度为O(mn)。并不是一种好的算法,这里不实现这种算法。 由于两个单链表有公共部分,不难理解,它们的结构是Y型的,如果是X型,那么不符合...

阅读全文

两个栈实现队列(算法7)

问题:用两个栈实现队列,要求队列包括方法:从尾部入队(插入元素);从头部出队(删除元素)。 原理: 首先要理解一点,栈操作具有对称性。正确地说,栈操作具有½对称性。如何理解这一点?例如,把以字符串压人栈,然后弹出,会得带得到原先字符串序列的反序列。如果该反序列在进行上述的压栈出栈操作,就会得带字符串的最初序列。这个操作过程就像:把以平面图案,先旋转180°后...

阅读全文

两个队列实现栈(算法7+)

该算法推广自两个栈实现队列(算法7)。 问题:使用两个队列实现栈。 原理: 队列具有自身对称性。怎么理解?例如,你把一字符串按顺序把每个字符放到队列中,然后取出队列中的所有字符组合成新的字符串,该新字符串和旧的字符串相等。这样我们可以把队列看作是一个容器。如果有两个这样的队列queue1和queue2做容器,那么栈的操作过程如下:(1)压栈:把元素加入到队列...

阅读全文

二叉树的深度(算法39)

问题:输入二叉树的根结点,求该树的深度。 从根结点到叶结点依次经过的结点形成树的一条路径,最长的路径长度为树的深度(深度为该路径的结点数)。 原理: 为了找到以根结点为树的根结点的深度需要找到左右子树的深度,依次递归下去不难写出如下代码。 1234567891011def tree_depth(tree): if not tree: re...

阅读全文

二进制中1的个数(算法10)

问题:实现一个函数,统计输入数字中一的个数 原理: 如果你知道位运算中的一个特点,这道题就简单了。 数字666的二进制形式是1010011010,注意到(666-1)的二进制为1010011000,观察发现,就是666消去了一个数字1。那么666在消去一个数字1后剩下的部分可以通过位运算留下:666&(666-1)。利用这种特性,添加一个计数器,计算...

阅读全文

判断集合相等的高效算法

集合是数学上的概念,具有无序、唯一性。两个集合相等是指两个集合中的元素分别相等。那么如何判断集合相等?下面给出四种思路,其中最后一种思路的效率是最高的。 思路一:最直接的蛮力方法。对集合中的元素逐一比较。时间复杂度为O(n^2)。 12345678910111213def is_same_set(s1, s2): if len(s1) != len(s...

阅读全文

包含min函数的栈(算法21)

包含min函数的栈(算法21)

阅读全文

反转链表(算法16)

经典的反转链表三种解决思路。

阅读全文

合并两(多)个排序的链表(算法17)

问题:输入两个递增排序的链表,合并这两个链表并使新链表中的结点仍然是按照递增排序的。 原理: 不难想出一个递归思路。先比较两链表首结点大小。较小的结点称为新合拼链表的首结点,同时,该结点所在的链表指针向前移动一位,我们称该链表尾子链表。这样,下一步就是子链表和较大结点所在的链表的比较和操作。和第一个类似,以此递归下去,直到两链表指针指向None。 根据递归版...

阅读全文

数值的整数次方(算法11)

问题:实现一个求数值的整数次方函数。求base(double type)的exponent(int type)次方。 原理和讨论: 如果使用Python,哈哈哈,直接了当: 12def power(base, exponent): return base**exponent 这里**运算符触发数值对象(int,float)的__pow__方法。 考虑边...

阅读全文

链表中倒数第k个结点(算法15)

问题:实现一个函数,输入k,返回给定链表中的倒数第k个结点。 原理: 不难看出,链表的倒数第k个结点就是链表的第(n-k+1)个结点(前提是k<=n)。第(n-k+1)个结点可以表示如下: n-k+1 = n-(k-1) 因此,就可以把倒数第k个结点和尾结点的举例(k-1),如果你觉得不够直观可以画图理解。这样,我们在遍历链表时可以使用一_sentin...

阅读全文

斐波那契数列的多种实现方法(算法9)

问题:实现一函数,输入整数你,输出斐波那契数列的第n行。 原理: 这个问题很容易实现。有三种种思路: (1)递归思路根据斐波那契数列的定义不难写出递归形式的实现。但该递归实现会重复计算数列的各项,效率低。为此,可以添加缓存,保存已经计算过的项,但因此增加了空间复杂度。 (2)动态规划根据斐波那契数列的地推形式,采用循环的方式实现 (3)利用数学定理在数学上有...

阅读全文

Actor并发模式实现

Pythonic的Actor并发模式实现

阅读全文

从尾到头打印链表(算法5)

问题:输入一个链表的头结点,从尾到头反过来打印出每个结点。 原理: 这道题的一个明显的思路是采用栈在遍历时保存每个结点,然后分别弹出栈的元素打印,由于栈具有FILO特性,以此达到从尾到头打印链表。注意,由于是打印链表(只读),不能修改输入链表的结构。 实现: 先实现栈结构 12345678910111213141516class Stack: ...

阅读全文

基于epoll实现的I/O复用HTTP服务器

I/O复用HTTP服务器

阅读全文

基于asyncio的异步模式生产者/消费者模式

使用Python实现基于asyncio的生产者/消费者模式。

阅读全文

Go语言实现链表

go保留的指针特性,但出于安全开来指针不支持位移运算。利用指针可以轻易实现高性能的链表数据结构。 定义结点双链表的结点指针是递归定义,分别是next、prev。 12345type Node struct { next, prev *Node list *List Value interface{}}...

阅读全文

不用加减乘除做加法运算(算法47)

问题:实现一个函数,在不使用+、-、×、÷的情况下求两个或多个整数的和。 原理: 很明显,没有四则运算只能使用位运算。关键是通过位运算规律找到规律实现位运算对两个整数进行相加。通过分析位运算进位特点不难解决问题。但这里使用一种更新的思路:函数式的解决方案。 123456789101112import functoolsimport operatordef s...

阅读全文

Go语言Socket编程

大部分底层网络的编程都离不开socket编程。HTTP编程、Web开发、IM通信、视频流传输的底层都是socket编程。关于socket编程的基础知识参考TCP/IP协议栈的相关知识。

阅读全文