编程题——时间空间效率的平衡

目录

 

丑数(剑指欧肥儿)

连续子数组的最大和(剑指欧肥儿,动态规划)


  • 丑数(剑指欧肥儿)

题目描述:把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。

解题代码一(效率不高但容易想到):

class Solution {
public:
    int GetUglyNumber_Solution(int index) {
        //排除不可能
        if(index <= 0)
            return 0;
        
        int num = 0;
        int count = 0;
        
        while(count < index){
            ++num;
            if(IsUgly(num))
                ++count;
            
        }
        return num;
    }
    
private:
    bool IsUgly(int num){
        while(num % 2 == 0)
            num /= 2;
        while(num % 3 == 0)
            num /= 3;
        while(num % 5 == 0)
            num /= 5;
        
        return (num == 1) ? true : false;
    }
};

解题思路:

  1. 这个代码,逻辑上没有任何问题,但是如果笔试或者面试拿出来,那就只有GG的份。因为这个算法的时间效率不高,一个数字即使不是丑数,我们也要对它执行求余和除法的操作。
  2. 所以我们要另想方法,找一个时间效率高的,下一个代码就是解决方案。·

解题代码二(空间换时间,推荐!):

class Solution {
public:
    int GetUglyNumber_Solution(int index) {
        //排除不可能
        if(index <= 0)
            return 0;
        
        int uglyArray[index];
        int* index2 = uglyArray;
        int* index3 = uglyArray;
        int* index5 = uglyArray;
        int count = 1;
        uglyArray[0] = 1;
        
        while(count < index){
            int x = min(*index2*2, *index3*3, *index5*5);
            uglyArray[count] = x;
            
            while( *index2*2 <= x )
                index2++;
            while( *index3*3 <= x )
                index3++;
            while( *index5*5 <= x )
                index5++;
            count++;
        } 
        
        return uglyArray[count - 1];
    }
    
private:
    int min(int x, int y, int z){
        int result;
        result = x < y ? x : y;
        result = result < z ? result : z;
        return result;
    }
};

解题思路:

  1. 这个算法,是深入思考了丑数的规律的。利用数组的空间来换取时间,它需要用数组保存每次生成的丑数。如果要求第1500个丑数,那么就要创建能容纳1500个数字的数组,占据了6KB空间,用较小的空间消耗换取了时间效率的提升。
  2. 这个算法思路,就是自己生成丑数,放在数组里。
  3. 怎么生成丑数呢,非常巧妙的思维,每个丑数(除1外)都是通过丑数乘上2,3,5来产生的,后面的思路就要看代码才能懂了。

  • 连续子数组的最大和(剑指欧肥儿,动态规划)

题目描述:HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)

解题代码:

class Solution {
public:
    int FindGreatestSumOfSubArray(vector array) {
        int mx = array[0];
        int res = array[0];
        for(int i = 1; i < array.size(); i++){
            mx = max(mx+array[i], array[i]);
            res = max(mx, res);
        }
        return res;
    }
};

解题思路:

这道题需要用到动态规划。mx用来存储当前子数组的最大和,res用来存储整个数组中最大的子数组和。注意:这里面max函数可以直接调用的,不需要引用库函数和头文件

引用来自牛客的分析:

使用动态规划

F(i):以array[i]为末尾元素的子数组的和的最大值,子数组的元素的相对位置不变

F(i)=max(F(i-1)+array[i] , array[i])

res:所有子数组的和的最大值

res=max(res,F(i))

 

如数组[6, -3, -2, 7, -15, 1, 2, 2]

初始状态:

    F(0)=6

    res=6

i=1:

    F(1)=max(F(0)-3,-3)=max(6-3,3)=3

    res=max(F(1),res)=max(3,6)=6

i=2:

    F(2)=max(F(1)-2,-2)=max(3-2,-2)=1

    res=max(F(2),res)=max(1,6)=6

i=3:

    F(3)=max(F(2)+7,7)=max(1+7,7)=8

    res=max(F(2),res)=max(8,6)=8

i=4:

    F(4)=max(F(3)-15,-15)=max(8-15,-15)=-7

    res=max(F(4),res)=max(-7,8)=8

以此类推

最终res的值为8


 

你可能感兴趣的:(剑指欧肥儿,算法题,时间空间效率的平衡)