时间效率与空间效率的平衡

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.从后向前遍历,用两个栈存储两个链表,然后出栈查看,直到两个相同的结点

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值