35、数组中的逆序对
题目描述
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
输入描述:
题目保证输入的数组中没有的相同的数字
数据范围:
对于%50的数据,size<=10^4
对于%75的数据,size<=10^5
对于%100的数据,size<=2*10^5
解题思路:
套路题目,利用归并排序中merge操作时会将逆序对变成正序的特点,在归并排序中加上一个计数即可。
代码
class Solution {
public:
int InversePairs(vector<int> data) {
int length=data.size();
if(length<=0)
return 0;
//vector<int> copy=new vector<int>[length];
vector<int> copy;
for(int i=0;i<length;i++)
copy.push_back(data[i]);
long long count=InversePairsCore(data,copy,0,length-1);
//delete[]copy;
return count%1000000007;
}
long long InversePairsCore(vector<int> &data,vector<int> ©,int start,int end)
{
if(start==end)
{
copy[start]=data[start];
return 0;
}
int length=(end-start)/2;
long long left=InversePairsCore(copy,data,start,start+length);
long long right=InversePairsCore(copy,data,start+length+1,end);
int i=start+length;
int j=end;
int indexcopy=end;
long long count=0;
while(i>=start&&j>=start+length+1)
{
if(data[i]>data[j])
{
copy[indexcopy--]=data[i--];
count=count+j-start-length; //count=count+j-(start+length+1)+1;
}
else
{
copy[indexcopy--]=data[j--];
}
}
for(;i>=start;i--)
copy[indexcopy--]=data[i];
for(;j>=start+length+1;j--)
copy[indexcopy--]=data[j];
return left+right+count;
}
};
36、两个链表的第一个公共节点
题目描述
输入两个链表,找出它们的第一个公共结点。
解题思路:
使用两个指针,先一起走一遍获得两个链表的长度,然后让长链表的指针先走两者的长度差,然后两个指针一起往前走,第一次相遇的点即为第一个公共节点。
代码
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
ListNode *p1=pHead1;
ListNode *p2=pHead2;
int len1=0,len2=0,diff=0;
while(p1!=NULL){
p1=p1->next;
len1++;
}
while(p2!=NULL){
p2=p2->next;
len2++;
}
if(len1>len2){
diff=len1-len2;
p1=pHead1;
p2=pHead2;
}
else{
diff=len2-len1;
p1=pHead2;
p2=pHead1;
}
for(int i=0;i<diff;i++){
p1=p1->next;
}
while(p1!=NULL && p2!=NULL){
if(p1==p2)
break;
p1=p1->next;
p2=p2->next;
}
return p1;
}
};
37、数字在排序数组中出现的次数
题目描述
统计一个数字在排序数组中出现的次数。
解题思路:
利用二分查找最快的找到目标数,再往它的两边找出出现的次数。
代码
class Solution {
public:
int BinarySearch(vector<int> data, int low, int high, int k)
{
while (low<=high)
{
int m = (high + low) / 2;
if (data[m] == k)return m;
else if (data[m] < k) low = m+ 1;
else high = m - 1;
}
return -1;
}
int GetNumberOfK(vector<int> data ,int k) {
if(data.empty())
return 0;
int res = 0, m =0;
int index = BinarySearch(data, 0, data.size() - 1, k);
if(index == -1)return 0;
m = index -1;
while(m>=0&&data[m] == k){
m--;
res++;
}
m = index +1;
while(m<data.size()&&data[m] == k){
m++;
res++;
}
return res+1;
}
};
38、二叉树深度
题目描述
输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
解题思路:
递归,每次求左右字树的较大者加上当前深度。
代码
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
int TreeDepth(TreeNode* pRoot)
{
if(pRoot == NULL)
return 0;
return 1 + max(TreeDepth(pRoot -> right), TreeDepth(pRoot -> left));
}
};
39、平衡二叉树
题目描述
输入一棵二叉树,判断该二叉树是否是平衡二叉树。
解题思路:
平衡二叉树定义是左右字数的深度差不超过1,因此定义一个结构体来返回是否是平衡二叉树和其深度,之后利用递归分别判断①左树是否为平衡二叉树②右树是否为平衡二叉树③左右树深度差是否小于1,全部为真即为平衡二叉树,然后递归此过程。
代码
class Solution {
public:
struct ReturnData{
public:
bool isB;
int height;
ReturnData(bool _isB, int _height):isB(_isB), height(_height){};
};
ReturnData process(TreeNode* head){
if(head == nullptr)
return ReturnData(true, 0);
ReturnData leftdata = process(head->left);
if (!leftdata.isB)
return ReturnData(false, 0);
ReturnData rightdata = process(head->right);
if (!rightdata.isB)
return ReturnData(false, 0);
if (abs(leftdata.height-rightdata.height)>1)
return ReturnData(false, 0);
return {true, std::max(leftdata.height, rightdata.height) + 1};
}
bool IsBalanced_Solution(TreeNode* pRoot) {
return process(pRoot).isB;
}
};
40、数组中只出现一次的数字
题目描述
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
解题思路:
这题考的是位运算,因为异或操作后,相同的数会为0,与0异或后不变。利用这个性质,我们来看两个数(我们假设是AB)出现一次的数组。我们首先还是先异或,剩下的数字肯定是A、B异或的结果,这个结果的二进制中的1,表现的是A和B的不同的位。我们就取第一个1所在的位数,假设是第3位,接着把原数组分成两组,分组标准是第3位是否为1。如此,相同的数肯定在一个组,因为相同数字所有位都相同,而不同的数,肯定不在一组。然后把这两个组按照最开始的思路,依次异或,剩余的两个结果就是这两个只出现一次的数字。
代码:
class Solution {
public:
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
vector<int> res;
int temp = data[0];
for(int i = 1; i < data.size(); ++i){
temp = temp^data[i];
}
int index=0;
while((temp&1)==0){
temp=temp>>1;
++index;
}
*num1=*num2=0;
for(int i=0;i<data.size();i++){
if(IsBit(data[i],index))
*num1^=data[i];
else
*num2^=data[i];
}
}
bool IsBit(int num,int index)
{
num=num>>index;
return (num&1);
}
};