牛客剑指offer刷题记录(六)

来源:互联网 发布:如何防范网络陷阱 编辑:程序博客网 时间:2024/05/21 04:01

连续子数组最大和

动态规划的题目,定义dp(i)是以第i个数字结尾的子数组的最大和,那么有如下动态规划方程:
dp(i)=num(i),i=0dp(i1)<=0
dp(i)=dp(i1)+num(i),i>0dp(i1)>0

class Solution {public:    int FindGreatestSumOfSubArray(vector<int> array) {        if (array.size() == 0)            return 0;        vector<int>dp(array.size());        int cur = numeric_limits<int>::min();        for (int i = 0; i < array.size(); ++i)        {            if (i == 0 || dp[i-1] <= 0)                dp[i] = array[i];            if (i>0 && dp[i-1] > 0)                dp[i] = dp[i - 1] + array[i];            if (dp[i] > cur)                cur = dp[i];        }        return cur;    }};

当然也可以用局部最优和全局最优的方式来做,局部最优保证以当前数字结尾,的最大值那么有:
local(i)=max(local(i1)+num(i),num(i))
然后求全局最优:
global(i)=max(local(i),global(i1))

class Solution {public:    int FindGreatestSumOfSubArray(vector<int> array) {        vector<int>a;        a.swap(array);        vector<int>local(a.size());        vector<int>global(a.size());        local[0] = a[0];        global[0] = a[0];        for (int i = 1; i<a.size(); ++i)        {            local[i] = max(a[i], local[i - 1] + a[i]);            global[i] = max(local[i], global[i - 1]);        }        return global[a.size() - 1];    }};

从1到n整数中1出现的次数

剑指offer上面讲的不清楚。
参考:http://blog.csdn.net/yi_afly/article/details/52012593

class Solution {public:    int NumberOf1Between1AndN_Solution(int n)    {        if (n < 0)            return 0;        int count = 0;        int weight = 0;        int round = 0;        int base = 1;        int origin = n;        while (n > 0)        {            weight = n % 10;            round = n / 10;            if (weight == 1)            {                count += round*base;                count += ((origin%base) + 1);            }            else if (weight == 0)            {                count += round*base;            }            else            {                count += round*base;                count += base;            }            base *= 10;            n /= 10;        }        return count;    }};

把数组排成最小的数

希望较高位出现较小的数,需要找到一个合适的排序规则,能够在这些全排列里面筛选出最小的数。直接排序肯定是不行的,比如12,333,9直接排序后9出现在最高位,是不符合要求的。

给出两个数字a和b需要判断哪个数在前面就要比较ab和ba

整型的拼接先转成string,然后再比较a+b和b+a的大小

把上述规则写成比较函数,利用sort很容易:

class comp{public:    bool operator()(string a, string b)    {        return a + b < b + a;    }};class Solution {public:    string PrintMinNumber(vector<int> numbers) {        if (numbers.size() == 0)            return string();        vector<string>n;         n.reserve(numbers.size());        for(auto num : numbers)        {            n.push_back(to_string(num));        }        sort(n.begin(), n.end(), comp());        string r;        for (auto i : n)        {            r += i;        }        return r;    }};

丑数

2、3、5为因数,可以写一个判断丑数的代码:

int judgeUgly(int n)    {        while (n % 2==0)            n /= 2;        while (n % 3 == 0)            n /= 3;        while (n % 5 == 0)            n /= 5;        return (n == 1) ? true : false;    }

然后利用这个函数,统计n个丑数,这个办法效率较低原因在于每个数字都要进行判断一遍:

class Solution {private:    bool judgeUgly(int n)    {        while (n % 2==0)            n /= 2;        while (n % 3 == 0)            n /= 3;        while (n % 5 == 0)            n /= 5;        return (n == 1) ? true : false;    }public:    int GetUglyNumber_Solution(int index) {        int i = 1;        int count = 0;        while (true)        {            if (judgeUgly(i))            {                ++count;            }            if (count == index)                break;            ++i;        }        return i;    }};

最终超时。

效率更高的办法叫做筛选法:
首先需要一个容器,假定里面就是存放所有1-Index的丑数,第一个个丑数是1,后面所有的丑数都是前面的丑数乘上2、3、5得来的。

class Solution {public:    int GetUglyNumber_Solution(int index) {        vector<int>ugly(index);        ugly[0] = 1;        int i, j, k;        i = j = k = 0;        for (int count = 1; count < index; ++count)        {            ugly[count] = min(ugly[i] * 2, min(ugly[j] * 3, ugly[k] * 5));            if (ugly[count] == ugly[i] * 2)++i;            if (ugly[count] == ugly[j] * 3)++j;            if (ugly[count] == ugly[k] * 5)++k;        }        return ugly[index - 1];    }};

第一个只出现一次的字符

hash是最简单的解法了:

class Solution {public:    int FirstNotRepeatingChar(string str) {        unordered_map<char,int>m;        for(int i=0;i<str.size();++i){            ++m[str[i]];        }        for(int i=0;i<str.size();++i){            if(m[str[i]]==1){                return i;            }        }        return -1;    }};
原创粉丝点击