【36-40】剑指offer

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;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值