41、树中两个结点的最低共同父结点
题目:假设树是普通的树,结点中也没有指向父结点的指针。
struct TreeNode
{
int value;
vector<TreeNode*> children;
};
//获得树根到结点的路径
bool GetNodeParh(TreeNode* root, TreeNode* node,list<TreeNode*>& path)
{
if(root == node)
return true;
path.push_back(root);
bool found = false;
vector<TreeNode*>::iterator iter = root->children.begin();
while (!found && iter!=root->children.end())
{
found = GetNodeParh(*iter,node,path);
++iter;
}
if(!found)
path.pop_back();
return found;
}
//找出两个路径的最后一个公共结点
TreeNode* GetLastCommonNode(list<TreeNode*>& path1,list<TreeNode*>& path2)
{
list<TreeNode*>::const_iterator iter1 = path1.begin();
list<TreeNode*>::const_iterator iter2 = path2.begin();
TreeNode* ret = NULL;
while (iter1!=path1.end() && iter2 != path2.end())
{
if(*iter1 == *iter2)
ret = *iter1;
++iter1;
++iter2;
}
return ret;
}
//主程序,接口
TreeNode* GetLastCommonParent(TreeNode* root,TreeNode* node1,TreeNode* node2)
{
if(root == NULL || node1 == NULL || node2 == NULL)
return NULL;
list<TreeNode*> path1;
GetNodeParh(root,node1,path1);
list<TreeNode*> path2;
GetNodeParh(root,node2,path2);
return GetLastCommonNode(path1,path2);
}
42、检测单链表是否有环
给定单链表,检测是否有环。如果有环,则求出入环的第一个结点。
listNode* GetLoopNode(listNode* head)
{
//前置条件的判断
if (!head)
{
return NULL;
}
//定义一个快指针和一个慢指针
listNode* fast = head;
listNode* slow = head;
while (fast && (fast->next))
{
fast = fast->next->next;
slow = slow->next;
//如果有环,则返回环的第一个节点
if (fast == slow)
{
slow = head;
while (true)
{
fast = fast->next;
slow = slow->next;
if (fast == slow)
break;
}
return slow;
}
}
return NULL;
}
43、树的子结构
输入两棵二叉树A和B,判断树B是不是A的子结构。
例如,下图中的两棵树A和B,由于A中有一部分子树的结构和B是一样的,因此B就是A的子结构。
1 8
/ \ / \
8 7 9 2
/ \
9 2
/ \
4 7
分析:这是2010年微软校园招聘时的一道题目。二叉树一直是微软面试题中经常出现的数据结构。对微软有兴趣的读者一定要重点关注二叉树。
bool HasSubTree(BinaryTreeNode* root1,BinaryTreeNode* root2)
{
if(!root1 && root2)
return false;
if(!root2)
return true;
if(root1->value == root2->value)
return subtree(root1->left, root2->left) && subtree(root1->right, root2->right);
else
return subtree(root1->left, root2) || subtree(root1->right, root2);
}
44、判断二叉树是不是平衡
题目:输入一棵二叉树的根结点,判断该树是不是平衡二叉树。如果某二叉树中任意结点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。例如下图中的二叉树就是一棵平衡二叉树:
bool IsBalanced(BinaryTreeNode* pRoot, int* pDepth)
{
if(pRoot == NULL)
{
*pDepth = 0;
return true;
}
int left, right;
if(IsBalanced(pRoot->m_pLeft, &left)
&& IsBalanced(pRoot->m_pRight, &right))
{
int diff = left - right;
if(diff <= 1 && diff >= -1)
{
*pDepth = 1 + (left > right ? left : right);
return true;
}
}
return false;
}
bool IsBalanced(BinaryTreeNode* pRoot)
{
int depth = 0;
return IsBalanced(pRoot, &depth);
}
45、数对之差的最大值
题目:在数组中,数字减去它右边的数字得到一个数对之差。求所有数对之差的最大值。例如在数组{2, 4, 1, 16, 7, 5, 11, 9}中,数对之差的最大值是11,是16减去5的结果。int MaxDiff(int numbers[],int length)
{
if(numbers == NULL || length < 2)
return 0;
int max = numbers[0];
int maxDiff = max - numbers[1];
for(int i = 2; i < length; ++i)
{
if(numbers[i - 1] > max)
max = numbers[i - 1];
int currentDiff = max - numbers[i];
if(currentDiff > maxDiff)
maxDiff = currentDiff;
}
return maxDiff;
}
46、有序数组中找中位数
题目:两个有序数组A和B,大小都是n,寻找这两个数组合并后的中位数。中位数:如果数组有个数是奇数,那么中数的值就是有序时处于中间的数;如果数组个数是偶数的,那么就是有序时中间两个数的平均值。
分析:
在比较两个数组时候计数,当计数达到n时,就可以得到中位数,在归并的数组中,中位数为下标n-1和n的两个数的平均值。
题目描述:给定一个字符串,要求删除给定字符串中的重复字符。比如给定abcbbd,则转换成为abcd。
在比较两个数组时候计数,当计数达到n时,就可以得到中位数,在归并的数组中,中位数为下标n-1和n的两个数的平均值。
double FindMedian(int* a,int* b,int length)
{
if(a==NULL || b==NULL || length<1)
throw exception("parameter error!");
int* first = NULL;
int* second = NULL;
for(int i=0;i<=length;++i)
{
first=second;
if( *a < *b)
second=a++;
else
second=b++;
}
return double(*first+*second)/2;
}
47、等概率随机数的产生
题目:已知有个rand7()的函数,可以生成等概率的[1,7]范围内的随机整数,让利用这个rand7()构造rand10()函数,生成等概率的[1,10]范围内的随机整数。int rand_10()
{
int x = 0;
do
{
x = 7 * (rand7() - 1) + rand7()-1;
}while(x >= 40);
return x % 10 + 1;
}
48、删除给定字符串中的重复字符题目描述:给定一个字符串,要求删除给定字符串中的重复字符。比如给定abcbbd,则转换成为abcd。
char* DeleteRepeat(char* str)
{
if(str==NULL)
return NULL;
char* first = str;
char* second = str;
int hash[256]={0};
while (*second!='\0')
{
if(first==second && hash[*second]==0)
{
++hash[*second];
++first;
++second;
}
else if(hash[*second]!=0)
++second;
else
{
++hash[*second];
*first++ = *second++;
}
}
*first = '\0';
return str;
}
int main()
{
char test1[] = "abcbbd";
char test2[] = "aaaa";
char test3[] = "aabccc";
char test4[] = "";
DeleteRepeat(test1);
cout<<test1<<endl;
DeleteRepeat(test2);
cout<<test2<<endl;
DeleteRepeat(test3);
cout<<test3<<endl;
DeleteRepeat(test4);
cout<<test4<<endl;
return 0;
}
49、找数组中唯一出现两次的数
题目:假设一个由n个整数组成的数组,整数都在1到n之间。此外,除一个数字出现两次外,其他所有数字只出现一次。用一种算法找出重复的那个数字。int FindSameNumber(int* a,int length)
{
if(a==NULL || length<0)
return -1;
int* hash = new int[length+1];
for(int i=0;i!=length+1;++i)
*(hash+i) = 0;
for (int i=0;i!=length;++i)
{
if(*(hash+*(a+i))==0)
++*(hash+*(a+i));
else
return *(a+i);
}
}
50、动态申请二维数组
题目:动态申请一个二维数组并释放。方法一:
//第一步,先申请一个指针数组
int **ptr = new int *[4];
//第二步,对指针数组中的每个元素再动态申请一个一维数组
for(int i = 0; i < 4; i++)
{
*(ptr+i) = new int[3];
}
//注意这种方式申请的二维数组,在释放的时候,要注意顺序。
//先释放掉指针数组中指向的一维数组,然后再释放指针数组本身。
for(int i = 0; i < 4; i++)
{
delete[] *(ptr+i);
//或者写成
delete[] ptr[i];
}
//然后释放指针数组本身
delete[] ptr;
方法二:
//使用数组指针,只需动态申请一次内存空间。不过思路可能不如两次申请来的清晰。
//此时的ptr是一个指针,该指向的是一个一维数组,而且是3个元素的一维数组(被嵌套的那一个)
int (*ptr)[3] = new int[4][3];
//使用数组指针的方法申请二维数组,释放的时候比较简单,不用两次释放。
//(废话,因为申请的时候也是一次动态申请,不是两次动态申请哇。。。)
delete[] ptr;
//也可以是 delete[] (*ptr)
欢迎大家访问我的独立技术博客 道合|SameIdeal.com