剑指offer(34~36)第一个只出现一次的字符--数组中的逆序对--找两个链表的公共结点
第一个只出现一次的字符
在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).
笨方法
无论你有多少字符,所有字符都会有对应的ASCLL码值,在0~255区间。所以我开辟一个255的数组大小,元素初始值都为0,遍历字符串,将字符的ASCLL码值对应下标的值++,用来统计该字符的次数。
class Solution {
public:
int FirstNotRepeatingChar(string str) {
int hash[256]={0};
for(int i=0;i<str.size();i++)
hash[str[i]]++;
for(int i=0;i<str.size();i++)
{
if(hash[str[i]]==1)
return i;
}
return -1;
}
};
效率更高的做法
我们要统计字符的次数,每个字符对应存在其出现次数,如果采用KV结构来统计,的复杂度就可以实现。
class Solution {
public:
int FirstNotRepeatingChar(string str) {
unordered_map<char, int> mymap;
int The_Once = 0;
for (int i = 0; i < str.size(); ++i)
{
++mymap[str[i]];//统计字符出现次数,
//如果之前map中没有str[i]作为key的键值对,这一操作实现插入和++
//统计同时去判断str出现字符出现次数是否>1,如果>1,肯定不是第一次出现,下标++
while(mymap[str[The_Once]] > 1 && The_Once < str.size())
++The_Once;
}
return The_Once == str.size() ? -1 : The_Once;
}
};
数组中的逆序对
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
输入描述:
题目保证输入的数组中没有的相同的数字
数据范围:
对于%50的数据,size<=10^4
对于%75的数据,size<=10^5
对于%100的数据,size<=2*10^5
示例1
输入:1,2,3,4,5,6,7,0
输出:7
思路分析:归并排序在合并有序数组的同时统计逆序对数
看到这道题,我也想到的直接遍历法,可是这样的效率确实是低,都通不过OJ测试。
归并排序:
统计逆序对的过程:统计逆序次数在(c)(d)过程中,简要分析一下(d)过程,因为已经有序,所以如果,data[left]<data[right],那么以data[left]为逆序对的首元素的逆序对不存在,此时data[left]是两个数组中最小的数,将其放置到辅助数组copy内,否则,data[right]为两个数组最小值,以data[right]为逆序对的尾元素存在逆序对个数等于mid-left+1个。
class Solution {
public:
long long nums = 0;
int InversePairs(vector<int> data) {
vector<int> copy = data;
MSort(data, copy, 0, data.size() - 1);
return nums % 1000000007;
}
void Merge(vector<int> &data, vector<int> ©, int begin, int mid, int end)
{
int start = begin;//记录开始位置
int left = begin;
int right = mid + 1;
while (left <= mid && right <= end)
{
if (data[left] < data[right])
{
copy[begin++] = data[left++];
}
else
{
copy[begin++] = data[right++];
nums += mid - left + 1;
}
}
while (left <= mid)
{
copy[begin++] = data[left++];
}
while (right <= end)
{
copy[begin++] = data[right++];
}
while (start <= end)//让两个数组数据保持一致
{
data[start] = copy[start];
start++;
}
}
void MSort(vector<int> &data, vector<int> ©, int begin, int end)
{
int mid;
if (begin < end)
{
mid = (begin + end) / 2;
MSort(data, copy, begin, mid);
MSort(data, copy, mid + 1, end);
Merge(data, copy, begin, mid, end);
}
}
};
输入两个链表,找出它们的第一个公共结点。
输入两个链表,找出它们的第一个公共结点。
- 计算两个链表的长度差sub,让较长的链表先走sub个节点。
- 然后两个链表同时向后走,直到找到重合的节点。
/*
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;
while(p1)
{
len1++;
p1=p1->next;
}
while(p2)
{
p2=p2->next;
len2++;
}
int sub=abs(len1-len2);
if(len1>len2)
{
while(sub)
{
pHead1=pHead1->next;
sub--;
}
}
else
{
while(sub)
{
pHead2=pHead2->next;
sub--;
}
}
while(pHead1)
{
if(pHead1==pHead2)
return pHead1;
pHead1=pHead1->next;
pHead2=pHead2->next;
}
return nullptr;
}
};