编程之美上的一道题。
给出两个单向链表的头指针,比如h1和h2,判断这两个链表是否相交。先假设链表不带环。
首先对于“链表相交”这个概念,要澄清一下,不是单点相交,而是如下这种:
其实也很好理解,相交在平面几何里面的概念是点重合。那么对于链表中某个结点重合,必然next指针也是一样的,于是就是上面这个样子了。
思路:如上分析后就很简单了,如果相交,那么肯定从h1找到尾部(NULL的前一个)和好
找到的尾部是重合的。如果不重合,肯定不相交,是重要条件。
代码如下[......]
有许多问题,可以利用试探和回溯的搜索技术求解。
求解的过程实际是先序遍历一棵“状态树”的过程。
例1:有集合A = {1, 2, ...n},求A的全部子集。
思路:从求全部子集(幂集)这个事情上,实际上对每个元素只有两个状态:要么在一个子集中,要么不在。
因此,可以逐一对A中每个元素进行“取”和“舍”,从而构造一棵完全二叉树。
算法如下:
注意这里是1~n,不是0~n
void mj(int n, int pos, int* flag)
{
i[......]
给定一个数组和一个k,输出最小的k个数字。
这个问题有多重解法,譬如:
1、sort, top K,时间复杂度O(nlogn)
2、小顶堆排序,pop+调整k次,时间复杂度O(n+klogn)。
3、选择排序,每次选min,swap到头部时间复杂度O(nk)。
这里写下选择排序这个。
#include <stdio.h>
void select_min(int* arr, int n, int k)
{
int i, j, tmp;
int min[......]
题目:输入一个整数和一棵二元树。
从树的根结点开始往下访问一直到叶结点所经过的所有结点形成一条路径。
打印出和与输入整数相等的所有路径。
例如:
10
/ \
5 12
/ \
4 7
输入整数22,输出如下路径:
10 12
10 5 7
解:就是最简单的先序遍历,只不过要记录路径,可以使用数组,我这里用的stl::vector。
注意left和right遍历后,要回退当前结点在path中状态。
算法:
v[......]
路径长度:从树中一个结点到另一个结点之间的分支构成这两个结点之间的路径,路径上的分支数目称作路径长度。
树的路径长度:从树根到每一个结点的路径长度之和。
结点的带全路径长度:从该结点到树根之间的路径长度与结点上权的乘积。
树的带全路径长度:树中所有叶子结点的带全路径长度之和,WPL = Σ (wi x li),其中wi是叶子结点的权重,li是从根到该叶子结点的路径长度,注意,带全路径长度只有叶子结点有权重!其他结点只计算长度无权重!。
来看书上三个树的WPL: