1.二叉树的最近公共祖先
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree
示例 1:
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出: 3
解释: 节点 5 和节点 1 的最近公共祖先是节点 3。
示例 2:
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出: 5
解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身
思路:利用递归,如果当前结点 root等于NULL,则直接返回NULL;如果 root 等于 p 或者 q ,那这棵树一定返回p 或者q;然后递归左右子树,因为是递归,使用函数后可认为左右子树已经算出结果,用left 和 right表示;此时若left为空,那最终结果只要看 right;若 right 为空,那最终结果只要看 left;如果 left 和 right都非空,因为只给了 p 和 q 两个结点,都非空,说明一边一个,因此 root 是他们的最近公共祖先如果 left 和 right 都为空,则返回空。
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { if(root==nullptr) return nullptr; if(root==p||root==q) return root; TreeNode* left=lowestCommonAncestor(root->left,p,q); TreeNode* right=lowestCommonAncestor(root->right,p,q); if(left==nullptr) return right; if(right==nullptr) return left;//一个为空的话,另一个就是公共祖先 if(left&&right) { return root;//都非空的话,此时p,q分别位于最大的左右子树 } return nullptr; } };
2.字符串的序列
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
思路:循环里套递归,得到所有排列组合,注意当放入一个字符串时,要判断当前结果数组里有没有这个字符串。
class Solution { public: vector<string> Permutation(string str) { vector<string> result; if(str.empty()) return result; exChange(str,result,0); sort(result.begin(),result.end()); return result; } void exChange(string str,vector<string> &result,int begin) { if(begin==str.size()-1) { if(find(result.begin(),result.end(),str)==result.end()) { result.push_back(str);//不重复的放进去 } } else { for(int i=begin;i<str.size();i++) { swap(str[i],str[begin]); exChange(str,result,begin+1);//递归排列剩下的序列 swap(str[i],str[begin]);//换回来再换回去 } } } void swap(char &x,char &y) { char z; z=x; x=y; y=z; } };
3.数组中出现次数超过一半的数字
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
思路:从头开始遍历,首先记录第一个数,记出现次数为1,如果下一个数等于它,则次数++,如不等于,则次数--。当次数为0时,开始设置记录下一个数,扔记出现次数为1.最后计算剩下的数字在数组中出现的次数,如大于1/2数组长度,返回这个数;否则,数组内没有出现次数超过一半的数字。
class Solution { public: int MoreThanHalfNum_Solution(vector<int> numbers) { int len=numbers.size(); if(len==0) return 0; int res=numbers[0]; int count=1; for(int i=1;i<len;i++) { if(numbers[i]==res) { count++;//相等,次数+1 } else { count--;//不等,次数-1 } if(count==0) { res=numbers[i]; count=1;//重新记录下一个数 } } count=0; for(int i=0;i<len;i++) { if(numbers[i]==res) { count++;//记录最后剩下的数在数组中出现的总次数 } } return count*2>len?res:0; } };
4.最小的K个数
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
思路:基于快速排序。随机生成一个index,如果这个index等于k-1,说明此数包括前面的数正好是最小的k个数。(因为快排,index前面的数都小于它,后面的数都大于它)。
class Solution { public: vector<int> GetLeastNumbers_Solution(vector<int> input, int k) { vector<int> res; int len=input.size(); if(len<=0||k<=0||k>len) return res; int start=0; int end=len-1; int index=Partition(input,len,start,end); while(index!=k-1) { if(index>k-1)//说明最小的k个数字在前面 { end=index-1; index=Partition(input,len,start,end); } else//说明最小的k个数字在后面 { start=index+1; index=Partition(input,len,start,end); } }//直到index为k时,此时前k个数就是最小的k个数 for(int i=0;i<k;i++) res.push_back(input[i]); return res; } int Partition(vector<int> &numbers,int length,int start,int end)//快排核心函数 { if(length<=0||start<0||end>=length) return false; int index=RandomInRange(start,end); Swap(&numbers[index],&numbers[end]);//随机生成一个点,与尾结点互换 int small=start-1; for(index=start;index<end;index++) { if(numbers[index]<numbers[end]) { ++small; if(small!=index) Swap(&numbers[index],&numbers[small]);//说明small与index之间有大于end下标的数字,把小于数组尾的数放到前面 } } ++small; Swap(&numbers[small],&numbers[end]); return small;//small前面,都小于它,后面都大于它 } int RandomInRange(int start,int end) { srand (time(NULL)); return rand() % (end-start+1) + start;//随机数函数 } void Swap(int *a,int *b) { int temp=*a; *a=*b; *b=temp; } };
PS:快速排序代码
void QuickSort(int data[],int length,int start,int end) { if(start==end) return;//终止条件 int index=Partition(data,length,start,end); if(index>start) { QuickSort(data,length,start,index-1); } if(index<end) { QuickSort(data,length,index+1,end); } }