【区间、栈】算法例题

news2024/11/25 2:53:18

目录

 六、区间

48. 汇总区间 ①

49. 合并区间 ②

50. 插入区间 ②

51. 用最少数量的箭引爆气球 ② ×

七、栈

52. 有效的括号 ①

53. 简化路径 ② ×

54. 最小栈 ② ×

55. 逆波兰表达式求值 ② √-

56. 基本计算器 ③


 六、区间

48. 汇总区间 ①

 给定一个  无重复元素 的 有序 整数数组 nums 。

返回 恰好覆盖数组中所有数字 的 最小有序 区间范围列表 。也就是说,nums 的每个元素都恰好被某个区间范围所覆盖,并且不存在属于某个范围但不属于 nums 的数字 x 。

列表中的每个区间范围 [a,b] 应该按如下格式输出:

  • "a->b" ,如果 a != b
  • "a" ,如果 a == b

示例 1:

输入:nums = [0,1,2,4,5,7]
输出:["0->2","4->5","7"]
解释:区间范围是:
[0,2] --> "0->2"
[4,5] --> "4->5"
[7,7] --> "7"

示例 2:

输入:nums = [0,2,3,4,6,8,9]
输出:["0","2->4","6","8->9"]
解释:区间范围是:
[0,0] --> "0"
[2,4] --> "2->4"
[6,6] --> "6"
[8,9] --> "8->9"

提示:

  • 0 <= nums.length <= 20
  • -231 <= nums[i] <= 231 - 1
  • nums 中的所有值都 互不相同
  • nums 按升序排列

方法1:

    public List<String> summaryRanges(int[] nums) {
        ArrayList<String> list = new ArrayList<>();
        if (nums.length == 0){
            return null;
        }
        int left = 0;
        int right = left + 1;
        while (right < nums.length){
            if (nums[right] - nums[right - 1] == 1){
                right++;
            }else {
                if (right == left + 1){
                    list.add(nums[left] + "");
                }else {
                    list.add(nums[left] + "->" + nums[right - 1]);
                }
                left = right;
                right++;
            }
        }
        if (right == left + 1){
            list.add(nums[left] + "");
        }else {
            list.add(nums[left] + "->" + nums[right - 1]);
        }
        return list;
    }

方法2:(0ms)

    public List<String> summaryRanges(int[] nums) {
        List<String> ret = new ArrayList<String>();
        int i = 0;
        int n = nums.length;
        while (i < n) {
            int low = i;
            i++;
            while (i < n && nums[i] == nums[i - 1] + 1) {
                i++;
            }
            int high = i - 1;
            StringBuffer temp = new StringBuffer(Integer.toString(nums[low]));
            if (low < high) {
                temp.append("->");
                temp.append(Integer.toString(nums[high]));
            }
            ret.add(temp.toString());
        }
        return ret;
    }

49. 合并区间 ②

 以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。

示例 1:

输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].

示例 2:

输入:intervals = [[1,4],[4,5]]
输出:[[1,5]]
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。

提示:

  • 1 <= intervals.length <= 104
  • intervals[i].length == 2
  • 0 <= starti <= endi <= 104

二维数组排序:

// 先升序排序
Arrays.sort(intervals, (i1,i2) -> i1[0]-i2[0]);

方法1:(227ms)

    public static int[][] merge(int[][] intervals) {
        sort(intervals);
        int[][] result = new int[intervals.length][2];
        int index = 0;
        ArrayDeque<Integer> queue = new ArrayDeque<>();
        for (int[] interval : intervals) {
            if (queue.size() == 0){
                queue.addLast(interval[0]);
                queue.addLast(interval[1]);
            } else {
                if (interval[0] <= queue.getLast()){
                    if (interval[1] > queue.getLast()){
                        queue.removeLast();
                        queue.addLast(interval[1]);
                    }
                }else {
                    result[index][0] = queue.removeFirst();
                    result[index][1] = queue.removeLast();
                    index++;
                    queue.addLast(interval[0]);
                    queue.addLast(interval[1]);
                }
            }
        }
        result[index][0] = queue.getFirst();
        result[index][1] = queue.getLast();
        result = Arrays.copyOf(result, index + 1);
        return result;
    }
    public static int[][] sort(int[][] srcArrays){
        for (int i = 0; i < srcArrays.length - 1; i++) {
            for (int j = i + 1; j < srcArrays.length; j++) {
                if (srcArrays[i][0] > srcArrays[j][0]){
                    int temp[] = srcArrays[i];
                    srcArrays[i] = srcArrays[j];
                    srcArrays[j] = temp;
                }
            }
        }
        return srcArrays;
    }

方法2:(0ms)

    static int[][] merge(int[][] intervals) {
        int min = Integer.MAX_VALUE;
        int max = Integer.MIN_VALUE;

        for (int[] x : intervals) {
            min = Math.min(min, x[0]);
            max = Math.max(max, x[0]);
        }
        int[] range = new int[max - min + 1];

        for (int i = 0; i < intervals.length; i++) {
            // 记录了从某个start出发,最大结束区间是在哪里。即: range[start] = max(range[end])
            range[intervals[i][0] - min] = Math.max(intervals[i][1] - min, range[intervals[i][0] - min]);
        }
        int start = 0;
        int end = 0;
        List<int[]> res = new ArrayList<>();
        for (int i = 0; i < range.length; i++) {
            if (range[i] == 0) {
                // 没有从这个start出发的。
                continue;
            }
            // 如果有,就计算这个点能到多远
            if (i <= end) {
                // 这个start在end以内,说明可以连接起来
                end = Math.max(range[i], end);
            } else {
                // 这个satrt超出了end的范围,说明找到了一个区间。
                res.add(new int[] { start + min, end + min });
                start = i;
                end = range[i];
            }
        }
        res.add(new int[] { start + min, end + min });
        return res.toArray(new int[res.size()][]);
    }

方法3:(2ms)

    public int[][] merge(int[][] intervals) {
        quickSort(intervals,0,intervals.length-1);
        List<int[]> ans = new ArrayList();
        ans.add(intervals[0]);
        for(int[] interval :  intervals){
            int[] ansInterval = ans.get(ans.size()-1);
            if(ansInterval[1] < interval[0]){
                ans.add(interval);
            }else{
                ansInterval[1] = Math.max(ansInterval[1],interval[1]);
            }
        }
        return ans.toArray(new int[ans.size()][]);
    }

方法4:(8ms)

public int[][] merge(int[][] intervals) {
        // 先按照区间起始位置排序
        Arrays.sort(intervals, (v1, v2) -> v1[0] - v2[0]);
        // 遍历区间
        int[][] res = new int[intervals.length][2];
        int idx = -1;
        for (int[] interval: intervals) {
            // 如果结果数组是空的,或者当前区间的起始位置 > 结果数组中最后区间的终止位置,
            // 则不合并,直接将当前区间加入结果数组。
            if (idx == -1 || interval[0] > res[idx][1]) {
                res[++idx] = interval;
            } else {
                // 反之将当前区间合并至结果数组的最后区间
                res[idx][1] = Math.max(res[idx][1], interval[1]);
            }
        }
        return Arrays.copyOf(res, idx + 1);
    }

作者:Sweetiee 🍬
链接:https://leetcode.cn/problems/merge-intervals/solutions/204805/chi-jing-ran-yi-yan-miao-dong-by-sweetiee/

方法5(9ms)

    public int[][] merge(int[][] intervals) {
        Arrays.sort(intervals, (a, b) -> a[0] - b[0]);
        List<int[]> ans = new ArrayList<>();
        for (int i = 0; i < intervals.length; ++i) {
            if (ans.size() == 0 || intervals[i][0] > ans.get(ans.size() - 1)[1]) ans.add(intervals[i]);
            else ans.get(ans.size() - 1)[1] = Math.max(intervals[i][1], ans.get(ans.size() - 1)[1]);
        }
        return ans.toArray(new int[ans.size()][2]);
    }

50. 插入区间 ②

 给你一个 无重叠的 ,按照区间起始端点排序的区间列表。

在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。

示例 1:

输入:intervals = [[1,3],[6,9]], newInterval = [2,5]
输出:[[1,5],[6,9]]

示例 2:

输入:intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8]
输出:[[1,2],[3,10],[12,16]]
解释:这是因为新的区间 [4,8] 与 [3,5],[6,7],[8,10] 重叠。

示例 3:

输入:intervals = [], newInterval = [5,7]
输出:[[5,7]]

示例 4:

输入:intervals = [[1,5]], newInterval = [2,3]
输出:[[1,5]]

示例 5:

输入:intervals = [[1,5]], newInterval = [2,7]
输出:[[1,7]]

提示:

  • 0 <= intervals.length <= 104
  • intervals[i].length == 2
  • 0 <= intervals[i][0] <= intervals[i][1] <= 105
  • intervals 根据 intervals[i][0] 按 升序 排列
  • newInterval.length == 2
  • 0 <= newInterval[0] <= newInterval[1] <= 105

方法2:(0ms)

    public int[][] insert(int[][] intervals, int[] newInterval) {
        int n = intervals.length;
        if(n == 0) {
            int[][] result = new int[1][2];
            result[0] = newInterval;
            return result;
        }
        int min = newInterval[0], max = newInterval[1];
        int start = 0;
        while (start < n && min > intervals[start][1]) {
            start++;
        }
        if(start == n) {
            int[][] result = new int[n+1][2];
            for (int i = 0; i < n; i++) {
                result[i] = intervals[i];
            }
            result[n] = newInterval;
            return result;
        }
        min = Math.min(min, intervals[start][0]);
        int end = n-1;
        while (end >= 0 && max < intervals[end][0]) {
            end--;
        }
        if(end == -1) {
            int[][] result = new int[n+1][2];
            result[0] = newInterval;
            for (int i = 0; i < n; i++) {
                result[i+1] = intervals[i];
            }
            return result;
        }
        max = Math.max(max, intervals[end][1]);
        int[][] result = new int[start + n - end][2];
        for (int i = 0; i < start; i++) {
            result[i] = intervals[i];
        }
        result[start] = new int[]{min, max};
        for (int i = 0; i < n - end - 1; i++) {
            result[start+1+i] = intervals[end+i+1];
        }
        return result;
    }

方法3:(1ms)

    public int[][] insert(int[][] intervals, int[] newInterval) {
        List<int[]> list = new LinkedList<>();
        int i = 0;
        //区间不重合
        while(i < intervals.length && newInterval[0] > intervals[i][1]) {
            list.add(new int[]{intervals[i][0],intervals[i][1]});
            i++;
        }
        //区间开始重合 本题难点
        while(i < intervals.length && newInterval[1] >= intervals[i][0]) {
            newInterval[0] = Math.min(newInterval[0], intervals[i][0]);
            newInterval[1] = Math.max(newInterval[1], intervals[i][1]);
            i++;
        }
        list.add(newInterval);

        //剩下的区间加入到集合
        while(i < intervals.length) {
            list.add(intervals[i]);
            i++;
        }
        int[][] res = new int[list.size()][];
        return list.toArray(res);
    }

51. 用最少数量的箭引爆气球 ② ×

 有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points ,其中points[i] = [xstart, xend] 表示水平直径在 xstart 和 xend之间的气球。你不知道气球的确切 y 坐标。

一支弓箭可以沿着 x 轴从不同点 完全垂直 地射出。在坐标 x 处射出一支箭,若有一个气球的直径的开始和结束坐标为 xstartxend, 且满足  xstart ≤ x ≤ xend,则该气球会被 引爆 。可以射出的弓箭的数量 没有限制 。 弓箭一旦被射出之后,可以无限地前进。

给你一个数组 points ,返回引爆所有气球所必须射出的 最小 弓箭数 

示例 1:

输入:points = [[10,16],[2,8],[1,6],[7,12]]
输出:2
解释:气球可以用2支箭来爆破:
-在x = 6处射出箭,击破气球[2,8]和[1,6]。
-在x = 11处发射箭,击破气球[10,16]和[7,12]。

示例 2:

输入:points = [[1,2],[3,4],[5,6],[7,8]]
输出:4
解释:每个气球需要射出一支箭,总共需要4支箭。

示例 3:

输入:points = [[1,2],[2,3],[3,4],[4,5]]
输出:2
解释:气球可以用2支箭来爆破:
- 在x = 2处发射箭,击破气球[1,2]和[2,3]。
- 在x = 4处射出箭,击破气球[3,4]和[4,5]。

提示:

  • 1 <= points.length <= 105
  • points[i].length == 2
  • -231 <= xstart < xend <= 231 - 1

方法2:(28ms)

    public int findMinArrowShots(int[][] points) {
        if(points == null || points.length == 0) return 0;
        Arrays.sort(points, new Comparator<int[]>(){
            public int compare(int[] i, int[] j){
                if(i[1] == j[1]) return i[0] - j[0];
                return i[1] - j[1];
            }
        });
        int start = points[0][0], end = points[0][1], counts = 1;
        for(int i = 0; i < points.length; i++){
            if(points[i][0] <= end){
                start = Math.max(points[i][0], start);
                end = Math.min(points[i][1], end);
            }else{
                counts++; start = points[i][0]; end = points[i][1];
            }
        }
        return counts;
    }

方法3:(51ms)

    public int findMinArrowShots(int[][] points) {
        Arrays.sort(points, (a, b) -> Integer.compare(a[1], b[1]));

        int pos = points[0][1];
        int count = 1;

        for (int i = 1; i < points.length; i++) {
            if (pos >= points[i][0]) {
                continue;
            } else {
                pos = points[i][1];
                count++;
            }
        }
        return count;
    }

方法4:(56ms)

    public int findMinArrowShots(int[][] points) {
        // 贪心
        int n = points.length;
        if(n == 0) return 0;

        Arrays.sort(points, (a, b) -> Long.compare(a[1], b[1]));
        int result = 1;
        // 第一支箭直接射出
        int arrow = points[0][1];  
        for(int i = 1; i < n; i++){
            if(points[i][0] <= arrow){
                // 该区间能被当前箭right穿过
                continue;
            }
            arrow = points[i][1]; // 继续射出箭
            result++; // 箭数加1
        }
        return result;
    }

作者:ydnacyw
链接:https://leetcode.cn/problems/minimum-number-of-arrows-to-burst-balloons/solutions/2539356/java-tan-xin-tu-jie-yi-dong-by-cao-yang-yjv4c/

七、栈

52. 有效的括号 ①

 给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。

示例 1:

输入:s = "()"
输出:true

示例 2:

输入:s = "()[]{}"
输出:true

示例 3:

输入:s = "(]"
输出:false

提示:

  • 1 <= s.length <= 104
  • s 仅由括号 '()[]{}' 组成

    public static boolean isValid(String s) {
        Stack<Character> stack = new Stack<>();
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (stack.size() == 0 || c == '(' || c == '[' || c == '{'){
                stack.push(c);
            }else {
                if (c == ')' && stack.peek() == '('){
                    stack.pop();
                }else if (c == ']' && stack.peek() == '['){
                    stack.pop();
                }else if (c == '}' && stack.peek() == '{'){
                    stack.pop();
                }else {
                    stack.push(c);
                }
            }
        }
        return stack.size() == 0? true : false;
    }

方法2:

    public boolean isValid(String s) {
          if ((s.length() & 1) != 0 || s.length() == 1) {
            return false;
        }
        int max = s.length() / 2;
        char[] chars = new char[max];
        int index = 0;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if ('(' == c || '[' == c || '{' == c) {
                if (index >= max) {
                    return false;
                }
                chars[index] = c;
                index++;
            } else if (index-- > 0) {
                char aChar = chars[index];
                if (')' == c) {
                    if (aChar != '(') {
                        return false;
                    }
                } else if (']' == c) {
                    if (aChar != '[') {
                        return false;
                    }
                } else if ('}' == c) {
                    if (aChar != '{') {
                        return false;
                    }
                }
            } else {
                return false;
            }
        }
        return index==0;
    }

方法3:

    public boolean isValid(String s) {
        char[] l = {'(','[','{'};
        char[] r = {')',']','}'};
        char[] ss = s.toCharArray();
        int n = ss.length;
        char[] st = new char[10010];
        int top = -1;
        st[++top] = ss[0];
        boolean flag = true;
        for(int i = 1; i < n; i++)
        {
            char c = ss[i];
            if(c == '(' || c == '[' || c == '{')
                st[++top] = c;
            else
            {
                if(top < 0)
                {
                    flag = false;
                    break;
                }
                if(c == ')' && st[top] != '(')
                {
                    flag = false;
                    break;
                }
                if(c == ']' && st[top] != '[')
                {
                    flag = false;
                    break;
                }
                if(c == '}' && st[top] != '{')
                {
                    flag = false;
                    break;
                }
                top--;
            }
        }
        if(top >= 0)
            flag = false;
        return flag;
    }

53. 简化路径 ② ×

给你一个字符串 path ,表示指向某一文件或目录的 Unix 风格 绝对路径 (以 '/' 开头),请你将其转化为更加简洁的规范路径。

在 Unix 风格的文件系统中,一个点(.)表示当前目录本身;此外,两个点 (..) 表示将目录切换到上一级(指向父目录);两者都可以是复杂相对路径的组成部分。任意多个连续的斜杠(即,'//')都被视为单个斜杠 '/' 。 对于此问题,任何其他格式的点(例如,'...')均被视为文件/目录名称。

请注意,返回的 规范路径 必须遵循下述格式:

  • 始终以斜杠 '/' 开头。
  • 两个目录名之间必须只有一个斜杠 '/' 。
  • 最后一个目录名(如果存在)不能 以 '/' 结尾。
  • 此外,路径仅包含从根目录到目标文件或目录的路径上的目录(即,不含 '.' 或 '..')。

返回简化后得到的 规范路径 。

示例 1:

输入:path = "/home/"
输出:"/home"
解释:注意,最后一个目录名后面没有斜杠。 

示例 2:

输入:path = "/../"
输出:"/"
解释:从根目录向上一级是不可行的,因为根目录是你可以到达的最高级。

示例 3:

输入:path = "/home//foo/"
输出:"/home/foo"
解释:在规范路径中,多个连续斜杠需要用一个斜杠替换。

示例 4:

输入:path = "/a/./b/../../c/"
输出:"/c"

提示:

  • 1 <= path.length <= 3000
  • path 由英文字母,数字,'.''/' 或 '_' 组成。
  • path 是一个有效的 Unix 风格绝对路径。

方法2:(1ms)

    public String simplifyPath(String path) {
        String[] arr = new String[path.length()];
        int index = 0,i=0;
        while (index < path.length()) {
            while (index < path.length() && path.charAt(index) == '/') {
                index++;
            }
            if (index == path.length()) break;
            int start = index;
            while (index < path.length() && path.charAt(index) != '/') {
                index++;
            }
            String s = path.substring(start,index);
            if ("..".equals(s)) {
                if (i > 0) {
                    i--;
                }
            }else if (!".".equals(s)) {
                arr[i++] = s;
            }
        }
        StringBuilder sb = new StringBuilder();
        for (int j = 0; j < i; j++) {
            sb.append("/").append(arr[j]);
        }
        return sb.length() == 0 ? "/" : sb.toString();
    }

方法3:(3ms)

    public String simplifyPath(String path) {
        Deque<String> deque = new LinkedList<>();
        int n = path.length();
        int start = 0, end = 1;
        while (end < n) {
            while (end < n && path.charAt(end) != '/') {
                end++;
            }
            String subString = path.substring(start, end);
            //认为是空目录
            if (subString.equals("/")) {
                start = end;
                end++;
                continue;
            }

            //当前目录
            if (subString.equals("/.")) {
                start = end;
                end++;
                continue;
            }

            //
            if (subString.equals("/..")) {
                if(!deque.isEmpty()) {
                    deque.pollLast();
                }
                start = end;
                end++;
                continue;
            }

            deque.offerLast(subString.substring(1));
            start = end;
            end++;
        }

        StringBuffer stringBuffer = new StringBuffer();
        for (String s : deque) {
            stringBuffer.append("/");
            stringBuffer.append(s);
        }

        return stringBuffer.length() == 0 ? "/" : stringBuffer.toString();
    }

方法4:(8ms)

    public String simplifyPath(String path) {
        Deque<String> stack = new LinkedList<>();
        for (String item : path.split("/")) {
            if (item.equals("..")) {
                if (!stack.isEmpty()) stack.pop();
            } else if (!item.isEmpty() && !item.equals(".")) stack.push(item);
        }
        String res = "";
        for (String d : stack) res = "/" + d + res;
        return res.isEmpty() ? "/" : res;  
    }

54. 最小栈 ② ×

设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

实现 MinStack 类:

  • MinStack() 初始化堆栈对象。
  • void push(int val) 将元素val推入堆栈。
  • void pop() 删除堆栈顶部的元素。
  • int top() 获取堆栈顶部的元素。
  • int getMin() 获取堆栈中的最小元素。

示例 1:

输入:
["MinStack","push","push","push","getMin","pop","top","getMin"]
[[],[-2],[0],[-3],[],[],[],[]]

输出:
[null,null,null,null,-3,null,0,-2]

解释:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin();   --> 返回 -3.
minStack.pop();
minStack.top();      --> 返回 0.
minStack.getMin();   --> 返回 -2.

提示:

  • -231 <= val <= 231 - 1
  • poptop 和 getMin 操作总是在 非空栈 上调用
  • pushpoptop, and getMin最多被调用 3 * 104 次

方法2(4ms)

    // 数组栈, [当前值, 当前最小值]
    private Stack<int[]> stack = new Stack<>();

    public MinStack() {

    }

    public void push(int x) {
        if (stack.isEmpty()){
            stack.push(new int[]{x, x});
        }else {
            stack.push(new int[]{x, Math.min(x, stack.peek()[1])});
        }
    }

    public void pop() {
        stack.pop();
    }

    public int top() {
        return stack.peek()[0];
    }

    public int getMin() {
        return stack.peek()[1];
    }

方法3 :(6ms) 

    private Node head;
    
    public void push(int x) {
        if(head == null) 
            head = new Node(x, x);
        else 
            head = new Node(x, Math.min(x, head.min), head);
    }

    public void pop() {
        head = head.next;
    }

    public int top() {
        return head.val;
    }

    public int getMin() {
        return head.min;
    }
    
    private class Node {
        int val;
        int min;
        Node next;
        
        private Node(int val, int min) {
            this(val, min, null);
        }
        
        private Node(int val, int min, Node next) {
            this.val = val;
            this.min = min;
            this.next = next;
        }
    }

55. 逆波兰表达式求值 ② √-

给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。

请你计算该表达式。返回一个表示表达式值的整数。

注意:

  • 有效的算符为 '+''-''*' 和 '/' 。
  • 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
  • 两个整数之间的除法总是 向零截断 。
  • 表达式中不含除零运算。
  • 输入是一个根据逆波兰表示法表示的算术表达式。
  • 答案及所有中间计算结果可以用 32 位 整数表示。

示例 1:

输入:tokens = ["2","1","+","3","*"]
输出:9
解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9

示例 2:

输入:tokens = ["4","13","5","/","+"]
输出:6
解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6

示例 3:

输入:tokens = ["10","6","9","3","+","-11","*","/","*","17","+","5","+"]
输出:22
解释:该算式转化为常见的中缀算术表达式为:
  ((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22

方法1:(18ms)

    public static int evalRPN(String[] tokens) {
        Stack<String> stack = new Stack<>();
        for (int i = 0; i < tokens.length; i++) {
            String token = tokens[i];
            if (stack.size() == 0 ||token.matches("\\d+") || (token.charAt(0) == '-' && token.length() > 1)){
                stack.add(token);
            }else {
                int num2 = Integer.parseInt(stack.pop());
                int num1 = Integer.parseInt(stack.pop());
                int res = cal(num1, num2, token);
                stack.push(res + "");

            }
        }
        return Integer.parseInt(stack.peek());
    }
    public static int cal(int num1, int num2, String ope){
        int res = 0;
        switch (ope){
            case "+":
                res = num1 + num2;
                break;
            case "-":
                res = num1 - num2;
                break;
            case "*":
                res = num1 * num2;
                break;
            case "/":
                res = num1 / num2;
                break;
        }
        return res;
    }

}

56. 基本计算器 ③
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1531474.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

安防监控视频汇聚方案EasyCVR平台调用设备录像不返回视频流的原因排查

国标GB28181协议EasyCVR安防平台可以提供实时远程视频监控、视频录像、录像回放与存储、告警、语音对讲、云台控制、平台级联、磁盘阵列存储、视频集中存储、云存储等丰富的视频能力&#xff0c;平台支持7*24小时实时高清视频监控&#xff0c;能同时播放多路监控视频流&#xf…

使用Pygame做一个乒乓球游戏

项目介绍 使用Pygame做一个乒乓球游戏。左侧为电脑&#xff0c;右侧为玩家。 视频地址-YT 视频搬运-B站 视频教程约90分钟。 代码地址 环境&#xff1a;需要pygame库&#xff0c;可用pip安装&#xff1a;pip install pygame 1. 基础版本 首先进行一些初始化&#xff0c;初始…

MySQL 多表查询与事务的操作

一,多表联查 有些数据我们已经拆分成多个表,他们之间通过外键进行连接.当我们要查询两个表的数据,各取其中的一列或者多列. 这时候就需要使用多表联查. 数据准备: # 创建部门表 create table dept(id int primary key auto_increment,name varchar(20) ) insert into dept (n…

MySQL 多表关系(介绍) 一对多/多对多

一对多 举例介绍 例子: 部门与员工 在常理上来说: 一个部门有多个员工&#xff0c;一个员工只对应一个部门实现方式: 在多的一方建立外键&#xff0c;指向一的一方的主键 多对多 举例介绍 例子: 学生与课程 在常理上来说: 一个学生可以有多个课程,一门课程可以有多个学生实…

热插拔技术(番外)

5、总线热插拔及系统解决方案 在实际运用中&#xff0c;总线上插入板卡时&#xff0c;由于新插入板卡电容的充电以及上电过程中一些低阻抗通道的存在&#xff0c;会产生极大的浪涌电流&#xff0c;拉低总线电平&#xff0c;对总线上其他设备产生干扰&#xff0c;影响总线上其他…

【机器学习】TinyML的介绍以及在运动健康领域的应用

&#x1f9d1; 作者简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟,欢迎关注。提供嵌入式方向的学习指导…

前端基础篇-深入了解 Ajax 、Axios

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 Ajax 概述 2.0 Axios 概述 3.0 综合案例 1.0 Ajax 概述 通过 Ajax 可以给服务器发送请求&#xff0c;并获取服务器响应的数据。异步交互是指&#xff0c;可以在不…

高效编写产品规格书的秘诀与注意事项

高效编写产品规格书的秘诀&#xff1a;学会利用简单的工具&#xff0c;写出效果最佳的产品规格书。比如&#xff0c;你可以使用HelpLook、Markdown编辑器、LaTeX、notion等。 在快节奏的商业环境中&#xff0c;产品规格书是企业向市场展示产品特性和优势的重要工具。一份清晰、…

Linux——进程通信(三)命名管道

前言 我们在之前学习了匿名管道与匿名管道的应用——进程池&#xff0c;但是匿名管道的通信&#xff0c;需要有血缘关系的进程&#xff08;通过fork创建的进程们&#xff09;&#xff0c;如果我想让两个毫不相干的进程进行通信&#xff0c;可以采样命名管道的方式&#xff08;…

如何在Windows系统使用VS Code制作游戏网页并实现无公网IP远程访问

文章目录 前言1. 编写MENJA小游戏2. 安装cpolar内网穿透3. 配置MENJA小游戏公网访问地址4. 实现公网访问MENJA小游戏5. 固定MENJA小游戏公网地址 前言 本篇教程&#xff0c;我们将通过VS Code实现远程开发MENJA小游戏&#xff0c;并通过cpolar内网穿透发布到公网&#xff0c;分…

提升Java编程安全性-代码加密混淆工具的重要性和应用

在Java编程领域中&#xff0c;保护代码安全性和知识产权至关重要。本文旨在探讨代码加密混淆工具在提升代码安全性和保护知识产权方面的重要性。我们将介绍几款流行的Java代码加密混淆工具&#xff0c;如ProGuard、DexGuard、Jscrambler、DashO和ipaguard&#xff0c;并分析它们…

【RabbitMQ】【Docker】基于docker-compose构建rabbitmq容器

本文通过docker-compose构建一个单体的rabbtimq容器。 1&#xff0c;docker、docker-compose环境 首先需要有docker和docker-compose环境&#xff0c;docker安装[1]&#xff0c;docker-compose安装[2]。 通过下列命令确定docker、docker-compose是否安装成功。 [root192 ge…

单片机LED灯闪烁

延时函数计算&#xff08;相关代码生成&#xff09;&#xff1a; #include "reg52.h" #include <INTRINS.H> void Delay500ms() //11.0592MHz {unsigned char i, j, k;_nop_();_nop_();i 22;j 3;k 227;do{do{while (--k);} while (--j);} while (--i); }vo…

利用Xinstall,实现安装页面快速拉起App,推广效果倍增!

在移动互联网时代&#xff0c;App推广已成为广告主和开发者的重要任务。然而&#xff0c;面对激烈的市场竞争&#xff0c;如何提升推广效率、洞悉推广效果并衡量广告ROI&#xff0c;成为摆在他们面前的难题。今天&#xff0c;我们将聚焦一个关键环节——安装页面拉起App&#x…

Grid数据增强算法

算法原理 class Grid(object):def __init__(self, d1, d2, rotate1, ratio0.5, mode0, prob0.8):self.d1 d1self.d2 d2self.rotate rotateself.ratio ratioself.mode modeself.st_prob self.prob probdef set_prob(self, epoch, max_epoch):self.prob self.st_prob …

Debezium vs OGG vs Tapdata:如何实时同步 Oracle 数据到 Kafka 消息队列?

随着信息时代的蓬勃发展&#xff0c;企业对实时数据处理的需求逐渐成为推动业务创新和发展的重要驱动力。在这个快速变化的环境中&#xff0c;许多企业选择将 Oracle 数据库同步到 Kafka&#xff0c;以满足日益增长的实时数据处理需求。本文将深入探讨这一趋势的背后原因&#…

Java并发基石ReentrantLock:深入解读其原理与实现

码到三十五 &#xff1a; 个人主页 心中有诗画&#xff0c;指尖舞代码&#xff0c;目光览世界&#xff0c;步履越千山&#xff0c;人间尽值得 ! 在Java的并发编程库中&#xff0c;ReentrantLock是一种非常重要的同步工具&#xff0c;它提供了一种比内置synchronized关键字更加…

基于ArcGIS等多技术融合提升环境、生态、水文、土地、农业、大气等领域科研技术应用

基于ArcGIS等多技术融合提升环境、生态、水文、土地、农业、大气等领域科研技术应用 原文链接https://mp.weixin.qq.com/s?__bizMzUyNzczMTI4Mg&mid2247667012&idx5&snd2c5af65851b06ff7ee14a744c16009e&chksmfa771279cd009b6f8beff1c61c6b3b73087bf93e7d440…

顺序表的动态分配基本操作

#include <stdio.h> #include <stdlib.h>// 顺序表存储空间动态分配 #define InitSize 10 // 顺序表初始长度 typedef int ElemType; // int类型重命名为ElemType&#xff0c;方便后续调整typedef struct { // 定义结构体ElemType *data; // 用静…

“垃圾不落地,捡跑来助力”学雷锋志愿服务暨党支部党日活动

指导思想 紧紧围绕建设和谐社会主题&#xff0c;以创建文明为契机&#xff0c;学习雷锋精神&#xff0c;为人民服务为宗旨&#xff0c;大力开展志愿捡跑活动&#xff0c;激发大家积极参与志愿活动的热情&#xff0c;大力弘扬奉献、友爱、互助、进步的志愿服务精神。 活动启动 …