牛客剑指offer刷题记录

Posted NearXDU

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了牛客剑指offer刷题记录相关的知识,希望对你有一定的参考价值。


连续子数组最大和

动态规划的题目,定义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;
    
;

以上是关于牛客剑指offer刷题记录的主要内容,如果未能解决你的问题,请参考以下文章

牛客剑指offer 剪绳子

牛客剑指offer 剪绳子

牛客剑指offer 机器人的运动范围

牛客剑指offer 机器人的运动范围

按知识点刷题

[Java刷算法]牛客—剑指offer第一天