力扣每日一题:1006. 笨阶乘

题目:1006. 笨阶乘

难度: 中等

题目
通常,正整数 n 的阶乘是所有小于或等于 n 的正整数的乘积。例如,factorial(10) = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1。

相反,我们设计了一个笨阶乘 clumsy:在整数的递减序列中,我们以一个固定顺序的操作符序列来依次替换原有的乘法操作符:乘法(*),除法(/),加法(+)和减法(-)。

例如,clumsy(10) = 10 * 9 / 8 + 7 - 6 * 5 / 4 + 3 - 2 * 1。然而,这些运算仍然使用通常的算术运算顺序:我们在任何加、减步骤之前执行所有的乘法和除法步骤,并且按从左到右处理乘法和除法步骤。

另外,我们使用的除法是地板除法(floor division),所以 10 * 9 / 8 等于 11。这保证结果是一个整数。

实现上面定义的笨函数:给定一个整数 N,它返回 N 的笨阶乘。

示例1

输入:4
输出:7
解释:7 = 4 * 3 / 2 + 1

示例2

输入:10
输出:12
解释:12 = 10 * 9 / 8 + 7 - 6 * 5 / 4 + 3 - 2 * 1

提示

  • 1 <= N <= 10000
  • -2^31 <= answer <= 2^31 - 1

来源:力扣(LeetCode)
链接https://leetcode-cn.com/problems/clumsy-factorial
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。



解题思路

  (1)依据题意,从 ‘*’ ‘/’ ‘+’ ‘-’ 四则运算代替原来的阶乘运算。可以看出,对于乘法和除法是可以直接运算的,而加和减运算优先级没有乘法和除法,还需要看后面的数。但是,因为加减乘除的顺序是固定的,加法后面就是减法,两者优先级一直。所以加法可以直接加在定义好的返回值res里,而除法可以看做分割符,计算好除法间的每一段,然后段间在进行减法或加法即可。时间复杂度O(N)。
  (2)加减乘除的存储基于栈,所以用栈解决该类题目会很轻松,都是后入先出的特点。该题需要一个栈直接记录运算结果,注意在遇到减法的时候往栈顶push一个负数来代替负号。时间复杂度O(N)。
  (3)数学法。找出其中的数学规律,直接求解。时间复杂度O(N)。

解题代码

(1)朴素法

class Solution {
private:

public:
    int clumsy(int N) {

        int res = 0;
        int now;
        int count = 0;
        int flag = 1;

        if(N == 1)
            return 1;
        for(int i = N; i > 1; i--)
        {

            switch(count % 4)
            {
                case 0:
                    now = i * (i - 1);
                    break;
                case 1:
                    now = now / (i - 1);
                    break;
                case 2:
                    res += (i - 1);
                    break;
                case 3:
                    if(flag)
                    {
                        res += now;
                        flag = 0;
                    }
                    else
                    {
                        res -= now;
                    }
                    now = 0;
                    break;
            }
            count++;
        }
        
        if(N % 4 == 1)
            now = 1;
        if(now != 0)
        {
            if(flag)
            {
                res += now;
            }
            else
            {
                res -= now;
            }
        }

        return res;
    }
};

(2)栈解法

class Solution {
private:

public:
    int clumsy(int N) {

        int res = 0;
        stack<int> stk;
        int count = 0;
        stk.push(N);//先传入一个数据

        for(int i = N - 1; i >= 1; i--)
        {
            if(count % 4 == 0)
            {
                stk.top() *= i;
            }
            else if(count % 4 == 1)
            {
                stk.top() /= i;
            }
            else if(count % 4 == 2)
            {
                stk.push(i);
            }
            else if(count % 4 == 3)
            {
                stk.push(-i);
            }
            count++;
        }

        while(!stk.empty())
        {
            res += stk.top();
            stk.pop();
        }
        return res;


    }
};

(3)数学法

class Solution {
public:
    int clumsy(int N) {
        if (N == 1) {
            return 1;
        } else if (N == 2) {
            return 2;
        } else if (N == 3) {
            return 6;
        } else if (N == 4) {
            return 7;
        }

        if (N % 4 == 0) {
            return N + 1;
        } else if (N % 4 <= 2) {
            return N + 2;
        } else {
            return N - 1;
        }
    }
};

解题感悟

  关于数值计算类的题目,使用栈会是不错的选择。类似的,150.逆波兰表达式求值224.基本计算器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暗夜无风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值