LeetCode刷题|数据结构归类|栈各算法题合辑(持续补充)

1、#1047删除字符串中所有相邻重复项

(1)、题目

难度:简单

给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。

在 S 上反复执行重复项删除操作,直到无法继续删除。

在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

示例:

输入:“abbaca”
输出:“ca”
解释:
例如,在 “abbaca” 中,我们可以删除 “bb” 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 “aaca”,其中又只有 “aa” 可以执行重复项删除操作,所以最后的字符串为 “ca”。

(2)、解题

栈的方法

我们可以用栈来维护没有重复项的字母序列:

  • 若当前的字母和栈顶的字母相同,则弹出栈顶的字母;
  • 若当前的字母和栈顶的字母不同,则放入当前的字母。
class Solution {
    public String removeDuplicates(String S) {
       int n=S.length();
       if(n==1) return S;
       String ans=""+S.charAt(0);
       char temp=S.charAt(0);//记录栈顶
       for(int i=1;i<n;i++){
           if(ans.length()!=0&&S.charAt(i)==ans.charAt(ans.length()-1)) {//如果与栈顶字符一致,则弹出栈顶,并更新栈顶
           ans=ans.substring(0,ans.length()-1);//去掉字符串的最后一个字符,即弹出栈顶
           }
           else{//如果与栈顶字符不一致,则入栈,并更新栈顶
               ans+=S.charAt(i);
           }
       }
       return ans;
    }
}

执行用时:228 ms, 在所有 Java 提交中击败了8.55%的用户

内存消耗:40.5 MB, 在所有 Java 提交中击败了36.77%的用户

官解:

class Solution {
    public String removeDuplicates(String S) {
        StringBuilder sb = new StringBuilder();
        int sbLength = 0;
        for (char character : S.toCharArray()) {
            if (sbLength != 0 && character == sb.charAt(sbLength - 1))//如果与栈顶的字符一致
                sb.deleteCharAt(sbLength-- - 1);//弹出该栈顶
            else {//如果与栈顶字符不一致
                sb.append(character);//入栈
                sbLength++;
            }
        }
        return sb.toString();
    }
}

执行用时:10 ms, 在所有 Java 提交中击败了93.19%的用户

内存消耗:40 MB, 在所有 Java 提交中击败了98.06%的用户

复杂度分析

  • 时间复杂度:O(N),其中 NN 是字符串的长度。
  • 空间复杂度:O(N)。

2、#682棒球比赛(类似计算器)

(1)、题目

难度:简单

你现在是棒球比赛记录员。
给定一个字符串列表,每个字符串可以是以下四种类型之一:
1.整数(一轮的得分):直接表示您在本轮中获得的积分数。

  1. “+”(一轮的得分):表示本轮获得的得分是前两轮有效 回合得分的总和。
  2. “D”(一轮的得分):表示本轮获得的得分是前一轮有效 回合得分的两倍。
  3. “C”(一个操作,这不是一个回合的分数):表示您获得的最后一个有效 回合的分数是无效的,应该被移除。

每一轮的操作都是永久性的,可能会对前一轮和后一轮产生影响。
你需要返回你在所有回合中得分的总和。

示例 1:

输入: [“5”,“2”,“C”,“D”,"+"]
输出: 30
解释:
第1轮:你可以得到5分。总和是:5。
第2轮:你可以得到2分。总和是:7。
操作1:第2轮的数据无效。总和是:5。
第3轮:你可以得到10分(第2轮的数据已被删除)。总数是:15。
第4轮:你可以得到5 + 10 = 15分。总数是:30。

示例 2:

输入: [“5”,"-2",“4”,“C”,“D”,“9”,"+","+"]
输出: 27
解释:
第1轮:你可以得到5分。总和是:5。
第2轮:你可以得到-2分。总数是:3。
第3轮:你可以得到4分。总和是:7。
操作1:第3轮的数据无效。总数是:3。
第4轮:你可以得到-4分(第三轮的数据已被删除)。总和是:-1。
第5轮:你可以得到9分。总数是:8。
第6轮:你可以得到-4 + 9 = 5分。总数是13。
第7轮:你可以得到9 + 5 = 14分。总数是27。

注意:

输入列表的大小将介于1和1000之间。
列表中的每个整数都将介于-30000和30000之间。

(2)、解题

让我们在处理数据时保持栈上每个有效回合的值。栈是理想的,因为我们只处理涉及最后或倒数第二轮的操作。

class Solution {
    public int calPoints(String[] ops) {
        Stack<Integer> stack=new Stack();
        int sum=0;
        for(String op:ops){
            if(op.equals("+")){
                int top1=stack.pop();//弹出栈顶值,并返回该值,不弹出该值,取不到栈顶下面的值
                int top2=stack.peek();//只是返回栈顶的值,并不弹出
                int top=top1+top2;//新栈顶
                stack.push(top1);//把被弹出的top1压回去
                stack.push(top);//新栈顶入栈
                sum+=top;
            }
            else if(op.equals("D")){
                int top=stack.peek();//返回栈顶值,并不弹出
                stack.push(top*2);//压入栈
                sum+=top*2;
            }
            else if(op.equals("C")){
                int top=stack.pop();//将栈顶弹出
                sum-=top;
            }else{//将数字都压入栈。因为示例中除了三种符号和数字,并无其他,就不考虑其他了
                stack.push(Integer.valueOf(op));
                sum+=Integer.valueOf(op);
            }
        }
        return sum;
    }
}

执行用时:3 ms, 在所有 Java 提交中击败了85.60%的用户

内存消耗:39.2 MB, 在所有 Java 提交中击败了32.00%的用户

复杂度分析

复杂度分析:O(N),其中 NN是 ops 的长度。我们解析给定数组中的每个元素,然后每个元素执行O(1) 的工作。

空间复杂度:O(N),用于存储 stack 的空间。

猜你喜欢

转载自blog.csdn.net/weixin_45759791/article/details/107797937
今日推荐