36.题目描述
输入两个链表,找出它们的第一个公共结点。
思路:1.求出两个链表的长度;2.将长的链表移动(两链表长度之差个结点);3.同时移动两个链表,如果发现两个链表有相交的点,则返回交点的位置,否则返回NULL。具体实现见代码:
#include<iostream>
usingnamespace std;
structListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
classSolution {
public:
ListNode* FindFirstCommonNode( ListNode*pHead1, ListNode *pHead2) {
//如果链表为NULL,则返回NULL
if(pHead1 == NULL || pHead2 ==NULL)
return NULL;
//获取链表的长度
int nLengthHead1 =GetLength(pHead1);
int nLengthHead2 = GetLength(pHead2);
//求取两个链表长度的差值
int nLengthDif = nLengthHead1 -nLengthHead2;
ListNode *ph1 = pHead1;
ListNode *ph2 = pHead2;
//移动链表
if(nLengthDif < 0)
{
int i = 0;
nLengthDif *= -1;
while(i < nLengthDif)
{
ph2 = ph2->next;
i++;
}
}
else if(nLengthDif > 0)
{
int i = 0;
while(i < nLengthDif)
{
ph1 = ph1->next;
i++;
}
}
while(ph2 != NULL && ph1 !=NULL && ph1 != ph2)
{
ph1 = ph1->next;
ph2 = ph2->next;
}
ListNode *pFirstCommonNode = ph1;
return pFirstCommonNode;
}
int GetLength(ListNode *head)
{
if(head == NULL)
return 0;
int count = 0;
ListNode *temp = head;
while(temp != NULL)
{
count++;
temp = temp->next;
}
return count;
}
};
intmain()
{
ListNode node1(1);
ListNode node2(2);
ListNode node3(3);
ListNode node4(6);
ListNode node5(7);
ListNode node6(4);
ListNode node7(5);
node1.next = &node2;
node2.next = &node3;
node3.next = &node4;
node4.next = &node5;
node6.next = &node7;
node7.next = &node4;
Solution s;
cout<<s.FindFirstCommonNode(&node1,&node6)->val<<endl;
return 0;
}
37.题目描述
统计一个数字在排序数组中出现的次数。
思路:采用二分查找法,找出关键字第一次以及最后一次出现的位置,然后计算出现的次数。
#include<iostream>
#include<vector>
usingnamespace std;
classSolution {
public:
int GetNumberOfK(vector<int> data,int k) {
//如果数组为NULL,则返回-1
if(data.size() == 0)
return -1;
//如果数组不为NULL,则求取k出现的次数
//获取k第一次出现和最后一次出现的位置
int first = GetFistIndex(data, k,0, data.size()-1);
int last = GetLastIndex(data, k,0, data.size()-1);
int number = 0;
if(first > -1 && last> -1)
{
//计算出现的次数
number = last - first + 1;
}
return number;
}
int GetFistIndex(vector<int>&data, int k, int start, int end)
{
if(start > end)
{
return -1;
}
int mid = (start + end)/2;
int midData = data[mid];
//如果mid位置对应的值刚好为k,且mid的前一个位置数据不为k,则找到第一次出现的位置
if(midData == k)
{
if(((mid > 0) &&data[mid-1] != k) || mid == 0)
return mid;
else
{
end = mid - 1;
}
}
else if(midData > k)
{
end = mid - 1;
}
else
{
start = mid + 1;
}
return GetFistIndex(data, k, start, end);
}
int GetLastIndex(vector<int>&data, int k, int start, int end)
{
if(start > end)
{
return -1;
}
int mid = (start + end)/2;
int midData = data[mid];
//如果mid位置对应的值刚好为k,且mid的后一个位置数据不为k,则找到最后一次出现的位置
if(midData == k)
{
if(((mid <data.size()-1) && data[mid+1] != k) || mid == data.size()-1)
return mid;
else
{
start = mid + 1;
}
}
else if(midData > k)
{
end = mid - 1;
}
else
{
start = mid + 1;
}
return GetLastIndex(data, k, start, end);
}
};
intmain()
{
vector<int> data(8);
freopen("data.txt","r",stdin);
vector<int>::iterator ite =data.begin();
for(; ite != data.end(); ite++)
{
cin>>*ite;
}
Solution s;
cout<<s.GetNumberOfK(data,3)<<endl;
return 0;
}
38. 题目描述
输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
思路:采用递归的方式。1.递归终止条件:结点为NULL,返回深度0.
2.递归左子树和右子树,获得左子树和右子树的深度
3.返回当前结点的深度:深度为左右子树的深度的最大值+1
该程序还是先了各种二叉树的遍历,尤其要注意层序遍历,他需要借助于队列来实现。具体实现见代码:
#include <iostream>
#include <queue>
using namespace std;
struct TreeNode {
intval;
structTreeNode *left;
structTreeNode *right;
TreeNode(intx) :
val(x),left(NULL), right(NULL) {
}
};
class Solution {
public:
//树的深度
int TreeDepth(TreeNode* pRoot)
{
if(pRoot== NULL)
return0;
intleft = TreeDepth(pRoot->left);
intright = TreeDepth(pRoot->right);
return(left > right) ? (left+1) : (right + 1);
}
//树的平衡判断(重复遍历结点的方式)
boolIsBalanced(TreeNode* pRoot)
{
if(pRoot== NULL)
returntrue;
intleft = TreeDepth(pRoot->left);
intright = TreeDepth(pRoot->right);
intdiff = left - right;
if(diff< -1 || diff > 1)
returnfalse;
else
returnIsBalanced(pRoot->left) && IsBalanced(pRoot->right);
}
//树的平衡判断(只遍历结点一次的方式)
boolIsBalanced_1(TreeNode* pRoot)
{
intdepth;
returnIsBalanced_1(pRoot, &depth);
}
boolIsBalanced_1(TreeNode* pRoot, int *pDepth)
{
if(pRoot== NULL)
{
*pDepth= 0;
returntrue;
}
intleft, right;
if(IsBalanced_1(pRoot->left,&left) && IsBalanced_1(pRoot->right, &right))
{
intdiff = left - right;
if(diff>= -1 && diff <= 1)
{
*pDepth= (left > right) ? (left + 1) : (right + 1);
returntrue;
}
}
returnfalse;
}
//创建二叉树
TreeNode* Createtree()
{
TreeNode*root = NULL;
intval;
//cout<<"请输入结点数据,若结点数据为NULL,则输入-1:";
cin>>val;
if(val== -1)
returnNULL;
TreeNode*node = new TreeNode(val);
root= node;
root->left= Createtree();
root->right= Createtree();
returnroot;
}
//前序遍历
voidPreOrder(TreeNode *tree)
{
if(tree== NULL)
return;
cout<<tree->val<<"";
PreOrder(tree->left);
PreOrder(tree->right);
}
//中序遍历
voidMidOrder(TreeNode *tree)
{
if(tree== NULL)
return;
MidOrder(tree->left);
cout<<tree->val<<"";
MidOrder(tree->right);
}
//后序遍历
voidPostOrder(TreeNode *tree)
{
if(tree== NULL)
return;
PostOrder(tree->left);
PostOrder(tree->right);
cout<<tree->val<<"";
}
//层序遍历
voidLevelOrder(TreeNode *tree)
{
if(tree== NULL)
return;
queue<TreeNode*> que;
que.push(tree);
while(!que.empty())
{
cout<<que.front()->val<<"";
if(que.front()->left!= NULL)
{
que.push(que.front()->left);
}
if(que.front()->right!= NULL)
{
que.push(que.front()->right);
}
que.pop();
}
}
};
int main()
{
freopen("data.txt","r", stdin);
Solutions;
TreeNode* tree = s.Createtree();
cout<<"前序:";
s.PreOrder(tree);
cout<<endl;
cout<<"中序:";
s.MidOrder(tree);
cout<<endl;
cout<<"后序:";
s.PostOrder(tree);
cout<<endl;
cout<<"层序:";
s.LevelOrder(tree);
cout<<endl;
cout<<"深度:"<<s.TreeDepth(tree);
cout<<endl;
if(s.IsBalanced(tree))
{
cout<<"平衡:"<<"Yes"<<endl;
}
else
{
cout<<"平衡:"<<"No"<<endl;
}
if(s.IsBalanced_1(tree))
{
cout<<"平衡:"<<"Yes"<<endl;
}
else
{
cout<<"平衡:"<<"No"<<endl;
}
return0;
}
39.题目描述
输入一棵二叉树,判断该二叉树是否是平衡二叉树。
思路:平衡二叉树的定义—左右子树的深度之差的绝对值不超过1二叉树。
只要分别获取左右子树的深度,并且判断是否满足平衡二叉树的定义,即可。若不满足则返回false,否则递归左右子树进行判断。可以采用两种方式实现:1.重复访问结点的方式;2.只访问一个结点的方式。建议采用只访问一个结点的方式实现。具体实现见如下代码:
#include <iostream>
#include <queue>
using namespace std;
struct TreeNode {
intval;
structTreeNode *left;
structTreeNode *right;
TreeNode(intx) :
val(x),left(NULL), right(NULL) {
}
};
class Solution {
public:
//树的深度
int TreeDepth(TreeNode* pRoot)
{
if(pRoot== NULL)
return0;
intleft = TreeDepth(pRoot->left);
intright = TreeDepth(pRoot->right);
return(left > right) ? (left+1) : (right + 1);
}
//树的平衡判断(重复遍历结点的方式)
boolIsBalanced(TreeNode* pRoot)
{
if(pRoot== NULL)
returntrue;
intleft = TreeDepth(pRoot->left);
intright = TreeDepth(pRoot->right);
intdiff = left - right;
if(diff< -1 || diff > 1)
returnfalse;
else
returnIsBalanced(pRoot->left) && IsBalanced(pRoot->right);
}
//树的平衡判断(只遍历结点一次的方式)
boolIsBalanced_1(TreeNode* pRoot)
{
intdepth;
returnIsBalanced_1(pRoot, &depth);
}
boolIsBalanced_1(TreeNode* pRoot, int *pDepth)
{
if(pRoot== NULL)
{
*pDepth= 0;
returntrue;
}
intleft, right;
if(IsBalanced_1(pRoot->left,&left) && IsBalanced_1(pRoot->right, &right))
{
intdiff = left - right;
if(diff>= -1 && diff <= 1)
{
*pDepth= (left > right) ? (left + 1) : (right + 1);
returntrue;
}
}
returnfalse;
}
//创建二叉树
TreeNode* Createtree()
{
TreeNode*root = NULL;
intval;
//cout<<"请输入结点数据,若结点数据为NULL,则输入-1:";
cin>>val;
if(val== -1)
returnNULL;
TreeNode*node = new TreeNode(val);
root= node;
root->left= Createtree();
root->right= Createtree();
returnroot;
}
//前序遍历
voidPreOrder(TreeNode *tree)
{
if(tree== NULL)
return;
cout<<tree->val<<"";
PreOrder(tree->left);
PreOrder(tree->right);
}
//中序遍历
voidMidOrder(TreeNode *tree)
{
if(tree== NULL)
return;
MidOrder(tree->left);
cout<<tree->val<<"";
MidOrder(tree->right);
}
//后序遍历
voidPostOrder(TreeNode *tree)
{
if(tree== NULL)
return;
PostOrder(tree->left);
PostOrder(tree->right);
cout<<tree->val<<"";
}
//层序遍历
voidLevelOrder(TreeNode *tree)
{
if(tree== NULL)
return;
queue<TreeNode*> que;
que.push(tree);
while(!que.empty())
{
cout<<que.front()->val<<"";
if(que.front()->left!= NULL)
{
que.push(que.front()->left);
}
if(que.front()->right!= NULL)
{
que.push(que.front()->right);
}
que.pop();
}
}
};
int main()
{
freopen("data.txt","r", stdin);
Solutions;
TreeNode* tree = s.Createtree();
cout<<"前序:";
s.PreOrder(tree);
cout<<endl;
cout<<"中序:";
s.MidOrder(tree);
cout<<endl;
cout<<"后序:";
s.PostOrder(tree);
cout<<endl;
cout<<"层序:";
s.LevelOrder(tree);
cout<<endl;
cout<<"深度:"<<s.TreeDepth(tree);
cout<<endl;
if(s.IsBalanced(tree))
{
cout<<"平衡:"<<"Yes"<<endl;
}
else
{
cout<<"平衡:"<<"No"<<endl;
}
if(s.IsBalanced_1(tree))
{
cout<<"平衡:"<<"Yes"<<endl;
}
else
{
cout<<"平衡:"<<"No"<<endl;
}
return0;
}
40. 题目描述
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
注意:异或运算的使用。当数组中只有一个数据出现的次数是1次,其他元素出现的次数是2次的时候,只需要采取异或运算就能够得到只出现1次的数据。当有两个元素出现的次数都为1次时,其实是要找分组的条件:只需要将数组元素全部求异或,然后由异或的结果右边第一位为1的位置为1或者为0作为数组分组的判别条件,见数组分为两组。最后对分组后的数组分别进行异或运算,即可得到两个只出现一次的数据。具体实现见代码(尤其要注意按位与预算与关系运算的优先顺序):
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
//如果数组元素的个数少于2个,则返回
if(data.size()< 2)
return;
//获取所有数组元素异或后的值
intresultBit = 0;
vector<int>::iteratorite = data.begin();
for(;ite != data.end(); ite++)
resultBit^= *ite;
//通过resultBit,寻找到右边第一个为1的位的位置
intbitPosition = getBitPosition(resultBit);
//通过找了的位置,将数组中的数据元素按照bitposition位为1或者为0分为两组
ite= data.begin();
*num1= 0;
*num2= 0;
for(;ite != data.end(); ite++)
{
//判断数组中的元素的bitPosition位为1还是为0
if(IsBitPoition1(*ite,bitPosition))
{
*num1^= *ite;
}
else
{
*num2^= *ite;
}
}
}
intgetBitPosition(int val)
{
intbitPosition = 0;
while((val& 1) == 0 && bitPosition < 8*sizeof(int))
{
val= val>>1;
bitPosition++;
}
returnbitPosition;
}
boolIsBitPoition1(int val, int bitPosition)
{
return((val>>bitPosition) & 1);
}
};
int main()
{
freopen("data.txt","r", stdin);
vector<int>data(8);
vector<int>::iteratorite = data.begin();
for(;ite != data.end(); ite++)
cin>>*ite;
intnum1, num2;
Solutions;
s.FindNumsAppearOnce(data,&num1, &num2);
cout<<"出现一次的数字为:"<<num1<<"和"<<num2<<endl;
return0;
}