第25题 二叉树中和为某一值的路径
题目:输入一棵二叉树和一个整数,打印出二叉树中结点值的和为 输入整数的所有路径。从树的根结点开始往下一直到叶结点所经过 的结点形成一条路径。二叉树结点定义如下:
题目中的解法还可以进一步优化,即在查找路径上的和是否与输入的整数相等时,如果还没有到叶结点,而此时路径上的和已经超过输入的整数,就可以直接返回上一结点,不用再判断后续的子结点了。
void FindPath
(
BinaryTreeNode* pRoot,
int expectedSum,
std::vector<int>& path,
int& currentSum
)
{
currentSum += pRoot->m_nValue;
/*
在此判断currentSum是否大于输入的值,如果大于,就直接跳回父结点
if(currentSum > expectedSum)
return;
*/
path.push_back(pRoot->m_nValue);
// 如果是叶结点, 并且路径上结点的和等于输入的值
// 打印出这条路径
bool isLeaf = pRoot->m_pLeft == NULL && pRoot->m_pRight == NULL;
if(currentSum == expectedSum && isLeaf)
{
printf("A path is found: ");
std::vector<int>::iterator iter = path.begin();
for(; iter != path.end(); ++ iter)
printf("%d\t", *iter);
printf("\n");
}
// 如果不是叶结点,则遍历它的子结点
if(pRoot->m_pLeft != NULL)
FindPath(pRoot->m_pLeft, expectedSum, path, currentSum);
if(pRoot->m_pRight != NULL)
FindPath(pRoot->m_pRight, expectedSum, path, currentSum);
// 在返回到父结点之前,在路径上删除当前结点,
// 并在currentSum中减去当前结点的值
currentSum -= pRoot->m_nValue;
path.pop_back();
}
第26题 复杂链表的复制
题目:请实现函数ComplexListNode* Clone(ComplextListNode* pHead),复制一个复杂链表。 在复杂链表中,每个结点除了有一个m_pNext指针指向下一个结点外,还有一个m_pSibling指向链表中 的任意结点或是NULL。
结点定义如下:
下图为一个复杂链表
解法
- 一般解法:
- 复制原始链表上的每个结点,用m_pNext链接起来;
- 设置每个结点的m_pSibling指针。假设原始链表中的某个结点N的m_pSibling指向结点S,由于S的位置可能在N的前面也可能在N的后面,因此要从原始链表的头结点开始找。沿着m_pNext经过s步找到S,所以在复制的链表中对应的N‘也要从头结点沿着m_pNext经过s步。这样就可以设置m_pSibling指针。
- 分析,在设置m_pSibling时都要从头结点开始查找,时间复杂度为O(n^2)
- 用空间换时间解法:
- 还是按照方法1中的第一步复制链表,用m_pNext链接起来,复制的同时将<N, N’>的配对信息放到一个哈希表中;
- 设置结点的m_pSibling。如果原始链表结点N的m_pSibling指向结点S,那么在复制链表中,对应的N‘应该指向S’。
- 通过哈希表可以在O(1)时间内找到m_pSibling,因此时间复杂度为O(n)。
- 不用辅助空间的解法:
- 按照原始链表的每个结点N复制结点N‘,把N’链接到N的后面。如图所示
- 设置复制的结点的m_pSibling指针。从上图可以看出复制结点N‘的m_pSibling就是N的m_pSibling的m_pNext。
- 分拆成两个链表,偶数的是新复制的结点,奇数的是原始的链表。
- 时间复杂度是O(n),而且不需要辅助空间。
- 按照原始链表的每个结点N复制结点N‘,把N’链接到N的后面。如图所示
第29题
O(n)算法得到数组中任意第K大的数字。
第40题
题目:写一个函数,求两个整数之和,要求在函数体内不得使用+,-,*,/四则运算符号。
利用位操作:
int add(int num1, int num2)
{
int sum, carry;
do
{
sum = num1 ^ num2;
carry = (num1 & num2) << 1;
num1 = sum;
num2 = carry;
}while(num2 != 0);
return num1;
}
不使用新变量,交换两个变量的值:
基于加减法 | 基于异或运算 |
---|---|
a = a + b | a = a ^ b |
b = a - b | b = a ^ b |
a = a - b | a = a ^ b |
第50题
树中两个结点的最低公共祖先