LeetCode-553 最优除法

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/optimal-division

题目描述

给定一组正整数,相邻的整数之间将会进行浮点除法操作。例如, [2,3,4] -> 2 / 3 / 4 。

但是,你可以在任意位置添加任意数目的括号,来改变算数的优先级。你需要找出怎么添加括号,才能得到最大的结果,并且返回相应的字符串格式的表达式。你的表达式不应该含有冗余的括号。

示例:

输入: [1000,100,10,2]
输出: "1000/(100/10/2)"
解释:
1000/(100/10/2) = 1000/((100/10)/2) = 200
但是,以下加粗的括号 "1000/((100/10)/2)" 是冗余的,
因为他们并不影响操作的优先级,所以你需要返回 "1000/(100/10/2)"。

其他用例:
1000/(100/10)/2 = 50
1000/(100/(10/2)) = 50
1000/100/10/2 = 0.5
1000/100/(10/2) = 2
说明:

输入数组的长度在 [1, 10] 之间。
数组中每个元素的大小都在 [2, 1000] 之间。
每个测试用例只有一个最优除法解。

解题思路

 首先,需要求数值最大,那么需要分子最大分母最小,由于数组中所有数都大于1,并且所有运算均为除法,所以当第一个数为分子的时候,分子最大,接下来需要分母最小,在分母的位置,同样,由于除数均大于0,所以一直连除分母最小,那么将第一个数之后的数全部使用括号括起来就好了。

此题同样也可用动态规划来做,dp[i][j] 中,表示 i 到 j 中所有的信息,包括最大值,最小值,和括号情况,通过一个结构体来记录。状态转移方程为 dp[i][j].max = max(dp[i][k].max / dp[k + 1][j].min) 和 dp[i][j].min= max(dp[i][k].min/ dp[k + 1][j].max ),其中k是i和j之间的数。

代码展示

数学方法:

复制代码
class Solution {
public:
    string optimalDivision(vector<int>& nums) {
        int n = nums.size();
        if(n == 1) return to_string(nums[0]);
        else if(n == 2) return to_string(nums[0]) + "/" + to_string(nums[1]);
        else
        {
            string strRet;
            strRet += to_string(nums[0]) + "/(" + to_string(nums[1]);
            for(int i = 2; i < n; i++)
            {
                strRet += "/" + to_string(nums[i]);
            }
            strRet += ")";
            return strRet;
        }
    }
};
复制代码

动态规划:

复制代码
class Solution {
public:
    struct node
    {
        string mstrMax, mstrMin;
        double mdMax = DBL_MIN, mdMin = DBL_MAX;
    };
    string optimalDivision(vector<int>& nums) {
        int n = nums.size();
        vector<vector<node>> dp(n, vector<node>(n));
        
        for(int i = 0; i < n; i++)
        {
            dp[i][i].mdMax = dp[i][i].mdMin = nums[i];
            dp[i][i].mstrMax = dp[i][i].mstrMin = to_string(nums[i]);
        }
        for(int i = 1; i < n; i++)
        {
            for(int j = 0; j + i < n; j++)
            {
                for(int k = j; k < i + j; k++)
                {
                    if(dp[j][i + j].mdMax < dp[j][k].mdMax / dp[k + 1][i + j].mdMin)
                    {
                        dp[j][i + j].mdMax = dp[j][k].mdMax / dp[k + 1][i + j].mdMin;
                        if(k + 1 == i + j)
                        {
                           dp[j][i + j].mstrMax =  dp[j][k].mstrMax + "/" + dp[k + 1][i + j].mstrMin;
                        }
                        else
                        {
                            dp[j][i + j].mstrMax =  dp[j][k].mstrMax + "/(" + dp[k + 1][i + j].mstrMin + ")";
                        }
                    }
                    if(dp[j][i + j].mdMin > dp[j][k].mdMin / dp[k + 1][i + j].mdMax)
                    {
                        dp[j][i + j].mdMin = dp[j][k].mdMin / dp[k + 1][i + j].mdMax;
                        if(k + 1 == i + j)
                        {
                           dp[j][i + j].mstrMin =  dp[j][k].mstrMin + "/" + dp[k + 1][i + j].mstrMax;
                        }
                        else
                        {
                            dp[j][i + j].mstrMin =  dp[j][k].mstrMin + "/(" + dp[k + 1][i + j].mstrMax + ")";
                        }
                    }
                }
            }
        }
        return dp[0][n - 1].mstrMax;
    }
};
复制代码

 

运行结果

 

posted @   过客匆匆,沉沉浮浮  阅读(37)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示