553. 最优除法 / 150. 逆波兰表达式求值

本文介绍了两道中等难度的算法题:最优除法和逆波兰表达式求值。最优除法问题通过数学分析,得出结论:最大结果是将第一个数除以后面所有数的连乘。逆波兰表达式求值则利用栈结构,根据运算符进行相应的加减乘除操作。这两题都需要对算法和数学有较好的理解。
摘要由CSDN通过智能技术生成

553. 最优除法【中等题】【每日一题】

思路:【数学法】

  1. 设这n个数相除的最优解为Fn=x/y,显然分子尽量大,分母尽量小,得出的结果才会是最大的,而由于nums中全是大于1的正整数,越除越小,因此只有当分子取nums[0]时才是最大的,于是现在就变成了,Fn=nums[0]/Fn-1,Fn-1表示后n-1个数相除的结果。
  2. 那么此时为了使Fn最大,由上述分析知需要让Fn-1最小,Fn-1也可表示为分数x/y的形式,要使Fn-1最小,需使分子x最小的同时分母y最大,那么出于数学运算乘除的规则,在nums后n-1个数的组合中,只有当nums[1]自己当分子时分子最小的同时,后n-2个数连续相乘时分母最大,于是Fn-1的最小值表示为
    nums[1]/(后边所有数相乘)。
  3. 于是,Fn(max)=nums[0]/Fn-1(min)=nums[0]/(nums[1]/nums[2]/…/nums[len-1]),即:当数组长度len为1时直接返回nums[0],当数组长度为2时,返回nums[0]/nums[1],当数组长度大于2时,返回nums[0]/(nums[1]/nums[2]/…/nums[len-1])。

代码:

class Solution {
    public String optimalDivision(int[] nums) {
        int len = nums.length;
        if (len == 1){
            return nums[0]+"";
        }
        if (len == 2){
            return nums[0]+"/"+nums[1];
        }
        StringBuilder ans = new StringBuilder(nums[0] + "/(");
        for (int i = 1; i < len; i++) {
            ans.append(nums[i]).append("/");
        }
        ans.deleteCharAt(ans.length()-1);
        return ans+")";
    }
}

150. 逆波兰表达式求值【中等题】

思路:

  1. 这题没什么技术含量,下边的提示给的太明显了。
  2. 题目给的肯定是有效的逆波兰表达式,所以tokens的长度是1的话,这肯定是个数,返回这个数即可,tokens的长度不可能是2,如果是2的话不能构成有效的逆波兰表达式,但是tokens的范围又写了大于等于1,那么就意思一下吧,长度为2返回-1,其实也没必要,不可能都到len=2这段代码里的。
  3. 长度大于等于3时,前两个数必然是数字,将其添加进Linkedlist中,从tokens第3个位置开始遍历,遇到运算符,就将当前list的最后一个元素取出,设为n2,删掉最后一个位置元素,然后再取出当前list的最后一个元素,设为n1,并再次删掉list最后一个元素,总之这个操作的意思就是,遇到运算符,就将list的倒数第2个元素取出设为n1,最后一个元素取出设为n2,并删除最后两个元素,对n1和n2根据运算符进行运算(n1
    运算符 n2),得到的结果添加到list的最后一个位置;如果遇到的是数组,那么直接将当前这个数字存入list的最后一个位置。
    4.遍历结束,list只剩一个元素,这个元素就是最后的运算结果,将其返回即可。

代码:

class Solution {
    public int evalRPN(String[] tokens) {
        int len = tokens.length;
        if (len == 1){
            return Integer.parseInt(tokens[0]);
        }
        if (len == 2){
            return -1;
        }
        LinkedList<Integer> list = new LinkedList<>();
        list.addFirst(Integer.parseInt(tokens[0]));
        list.addLast(Integer.parseInt(tokens[1]));
        for (int i = 2; i < len; i++) {
            String cur = tokens[i];
            if ("+".equals(cur) || "-".equals(cur) || "*".equals(cur) || "/".equals(cur)){
                int n2 = list.getLast();
                list.removeLast();
                int n1 = list.getLast();
                list.removeLast();
                int n = 0;
                switch (cur){
                    case "+":n = n1+n2;break;
                    case "-":n = n1-n2;break;
                    case "*":n = n1*n2;break;
                    case "/":n = n1/n2;break;
                }
                list.addLast(n);
            }else {
                list.add(Integer.parseInt(cur));
            }
        }
        return list.getFirst();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值