1.获取第index个丑数
一般方法不再论述,使用简便方法的思路是:
使用空间对换时间,不再去管不是丑数的数字,而是用一个数组,只针对丑数来进行判别和运算
丑数应该是另一个丑数乘以2,3或者5的结果,因此我们可以创建一个数组,里面的数字是排好序的丑数,每一个丑数都是前面的丑数乘以2,3,5得到的
int Min(int number1, int number2, int number3)
{
int min = (number1 < number2) ? number1 : number2;
min = (min < number3) ? min : number3;
return min;
}
///获取第index个丑数
int GetUglyNumber_Solution2(int index)
{
if (index <= 0)
{
return 0;
}
int *pUglyNumbers = new int[index];
pUglyNumbers[0] = 1;//1是默认的第一个丑数,先放进去
int nextUglyIndex = 1;//设置下一个丑数的坐标
int* pMultiply2 = pUglyNumbers;
int* pMultiply3 = pUglyNumbers;
int* pMultiply5 = pUglyNumbers;
while (nextUglyIndex < index)
{
int min = Min(*pMultiply2 * 2, *pMultiply3 * 3, *pMultiply5 * 5);
pUglyNumbers[nextUglyIndex] = min;
//三个while移动他们各自的坐标记录,有的数乘以相应倍数小于目标值则忽略
while (*pMultiply2 * 2 <= pUglyNumbers[nextUglyIndex])
{
++pMultiply2;
}
while (*pMultiply3 * 3 <= pUglyNumbers[nextUglyIndex])
{
++pMultiply3;
}
while (*pMultiply5 * 5 <= pUglyNumbers[nextUglyIndex])
{
++pMultiply5;
}
++nextUglyIndex;
}
int ugly = pUglyNumbers[nextUglyIndex - 1];
delete[] pUglyNumbers;//回收空间资源
return ugly;
}
2.第一个只出现一次的字符
个人思路:
1.使用一个map,将数组遍历一遍然后将出现的字符和相应字符的出现次数放在map里面
2.从头查找map中只出现一次的字符,第一个便是我们需要的字符
书上思路:
自己用一个哈希表,对应256个字符,然后开始遍历字符串,为相应的字符加加次数
两者比较:
书上的思路封装性更好,但是我的把map放进函数里创建达到一样效果,map的缺点是在放入字符进去的时候要一次O(n)而哈希表是O(1)经分析还是书上的效率更高,但是map的空间效率肯定相对更好
用哈希表来表示字符的方法要牢记,因为只需256个空间就可以表示所有的字符,空间效率O(1)
代码如下:
//将字符正确的放入map
void inMap(map<char, int>& myMap, char a)
{
if (myMap.empty())
{
myMap.insert(pair<char, int>(a, 1));
return;
}
map<char, int>::iterator it = myMap.begin();
for (it; it != myMap.end(); ++it)
{
if (it->first == a)
{
(it->second)++;
return;
}
}
//表示在map里面没有字符a
myMap.insert(pair<char, int>(a, 1));
}
char getChar(map<char, int>& myMap)
{
map<char, int>::iterator it = myMap.begin();
for (it; it != myMap.end(); ++it)
{
if (it->second == 1)
{
return it->first;
}
}
return '\0';//表示没有一个字符只出现过一次
}
char getFirOneChar(char* arr, int len, map<char, int>& myMap)
{
if (arr == NULL)
{
return '\0';
}
for (int i = 0; i < len; ++i)
{
inMap(myMap, arr[i]);
}
return getChar(myMap);
}
//使用
int main()
{
map<char, int> myMap;
char arr[] = "abaccdeff";
cout << getFirOneChar(arr, 9, myMap) << endl;
}
3.数组中出现的逆序对
复杂度为O(n^2)的不讲
直接来看改进模式
要点:运用归并排序
时间O(nlogn)
int InversePairsCore(int* data, int *copy, int start, int end)
{
if (start == end)//参数检验,若数组中只有一个数字
{
copy[start] = data[start];
return 0;
}
int length = (end - start) / 2;//1
int left = InversePairsCore(copy, data, start, start + length);//一半
int right = InversePairsCore(copy, data, start + length + 1, end);//一半
//i初始化为前半段最后一个数字的下标
int i = start + length;//1
//j出事换位后半段最后一个数字的下标
int j = end;//3
int indexCopy = end;//3
int count = 0;
while (i >= start&&j >= start + length + 1)
{// 0 2
if (data[i] > data[j])
{
copy[indexCopy--] = data[i--];
count += j - start - length;
}
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;
}
int InversePairs(int* data, int length)
{
if (data == NULL || length < 0)
{
return 0;
}
int *copy = new int[length];///辅助数组
for (int i = 0; i < length; ++i)
{
copy[i] = data[i];
}
int count = InversePairsCore(data, copy, 0, length - 1);
delete[] copy;
return count;
}
4.两个链表的第一个公共结点
1.Y型,注意问的是第一个”公共”结点,也就是一段过后两个链表就一致变成了一条,那么我们可以找到O(M+N)的方法,也就是先找到长的那条,M,短的N,从长的第M-N个结点以及短的第一个结点一起向后遍历,遍历到一个相同的结点那么那个结点就是第一个公共结点
2.从后向前遍历,用两个栈存储两个链表,然后出栈查看,直到两个相同的结点