剑指offer刷题记录

  1. 连续子数组的最大值
    要求:例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和
class Solution {
public:
    int FindGreatestSumOfSubArray(vector<int> array) {
        int length = array.size();
        int nCurSum = 0;
        int nGreatSum = 0x80000000;//初始化和的最大值为负数
        for(int i = 0; i < length; i ++)
        {
            if(nCurSum <= 0)//只有当和小于0时,才重新给和赋值
                nCurSum = array[i];
            else
                nCurSum += array[i];
            if(nCurSum > nGreatSum)
                nGreatSum = nCurSum;
        }
        return nGreatSum;
    }
};

2.数组中出现次数超过一半以上的数字
要求:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

lass Solution {
public:
    int MoreThanHalfNum_Solution(vector<int> numbers) {
        int n = numbers.size();
        if(n == 0) return 0;
        int res = numbers[0], cnt = 1;
        for(int i = 1; i < n; i ++)
        {
            if(res == numbers[i])
                cnt ++;
            else
                cnt --;
            if(cnt == 0)//重点在这里,不用将i置为1开始了,因为之前已经比较过了,而且当cnt为0的时候,才会出现新出现的数字大于原来的数字的情况
            {
                res = numbers[i];
                cnt = 1;
            }
        }
        //确认一下选出来的数字确实是出现次数超过一半
        int cnt_v = 0;
        for(int i = 0; i < n; i ++)
        {
            if(res == numbers[i])
                cnt_v ++;
        }
        if(cnt_v * 2 > n) return res;
        return 0;

    }
};

3、丑数
描述:把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
思路:如果用暴力求解法,对每个数都判断是否被2,3,5整除,效率比较低下。我们应该试着只对本来是丑数的数进行判断,分别对第一个丑数*2,*3,*5操作,然后找出其最小的一个数,其必然就是第二个丑数,依次这样循环下去,就可以找到第N个丑数

class Solution {
public:
    int GetUglyNumber_Solution(int index) {
        if(index == 0)
            return 0;
        int *pUglyNumbers = new int[index];
        pUglyNumbers[0] = 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(*pMultiply2  * 2 <= pUglyNumbers[nextUglyIndex])
                ++pMultiply2;
            while(*pMultiply3  * 3 <= pUglyNumbers[nextUglyIndex])
                ++pMultiply3;
            while(*pMultiply5  * 5 <= pUglyNumbers[nextUglyIndex])
                ++pMultiply5;
            nextUglyIndex ++;
        }
        int uglyNumber = pUglyNumbers[nextUglyIndex - 1];
        delete[] pUglyNumbers;
        return uglyNumber;
    }
    int MIN(int a, int b, int c)
    {
        int min = (a < b)? a : b;
        min = (min < c)? min : c;
        return min;
    }
};

3、第一个只出现一次的字符
描述:在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1.
思路:想必很多人跟我一样,看到这种题就是暴力法,一个一个比较,如下

int FirstNotRepeatingChar(string str) {
    char str_c;
    int length = str.size();
    int k = 1;
    for(int i = 0; i < length; i ++)
    {
        str_c = str[i];
        while(str[k] != str_c || k == i)
        {

            if(k == length - 1)
                return i;
            k++;
        }
        k = 0;
    }
    return -1;
}

这种时间复杂度为o(n2),显然不太合适。而哈希表正好可以派上用场,它的作用就是在记录的储存位置和它的关键字之间建立一个确定的对应关系,使得每个关键字对应一个存储位置。
在这里,是一个char类型的字符,8个字节,因此总共只有256个字符。可以建立一个256大小的数组,用来存放每个字符出现的次数。第二次循环则来寻找出现次数为1 的那个关键字。

//找到字符串第一个不重复出现的字符
char FirstNotRepeatingChar(char* str) {
    const int tablesize = 256;
    unsigned int hasTable[tablesize ];
    for(int i = 0; i < tablesize; i ++)
        hasTable[i] = 0;
    //存储每个关键字出现的次数
    char *pHashKey = str;
    while(*(pHashKey) != '\0')
    {
        hadTable[*(pHashKey++)] ++;
    }
    //储存结束
    //找到关键字出现次数为1 的关键字
    while(*(pHashKey) != '\0')
    {
        if(hadTable[*pHashKey] == 1)
        {
            return *pHashKey;
        }
        pHashKey ++;
    }
    return '\0';
}

4、两个链表的第一个公共结点
描述:输入两个链表,找出它们的第一个公共结点。
这里写图片描述

所以,不要忽略他们有长有短,先要将起点设为一致,可以将长的一个链表让其先走多的N步。
class Solution {
public:
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
        unsigned long length1 = GetListLong(pHead1);
        unsigned long length2 = GetListLong(pHead2);
        long nLengthDif = length1 - length2;
        if(nLengthDif > 0)
        {
            for(int i = 0; i < nLengthDif; i ++)
                pHead1 = pHead1->next;
        }
        else
        {
             for(int i = 0; i < (-nLengthDif); i ++)
                pHead2 = pHead2->next;
        }
        while(pHead1 != pHead2&& pHead1 != NULL && pHead2!= NULL)
        {
            pHead1 = pHead1->next;
            pHead2 = pHead2->next;     
        }
        ListNode* pNode = pHead1;
        return pNode;
    }
    unsigned long GetListLong(ListNode* pNode)
    {
        int cnt = 1;
        while(pNode != NULL)
        {
            cnt++;
            pNode = pNode->next;
        }
        return cnt;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值