leetcode刷题笔记 2021-01-26

题号13.罗马数字转整数

  • import java.util.*;
    class Solution {
        public int romanToInt(String s) {
            int sum=0;
            int finalnum=0;
            for(int i=0;i<s.length()-1;i++){
                int prenum=getValue(s.charAt(i));
                int num=getValue(s.charAt(i+1));
                if(prenum<num){
                    sum=sum-prenum;
                }else{
                    sum=sum+prenum;
                }
                finalnum=num;
            }
            sum=sum+finalnum;
            return sum;
        }
                private int getValue(char ch){
                switch(ch){
                    case 'I':return 1;
                    case 'V':return 5;
                    case 'X':return 10;
                    case 'L':return 50;
                    case 'C':return 100;
                    case 'D':return 500;
                    case 'M':return 1000;
                    default: return 0;
                }
    
            }
    }
    
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-koWCmyYY-1611670523520)(C:\Users\HASEE\AppData\Roaming\Typora\typora-user-images\1611461674333.png)]

  • 错误例子如上图。

  • 原因在于我的循环用的怪怪的。等于是假设了字符串至少有两位,遇到只有一位的情况出错了。

  • 正确解法如下:

  • import java.util.*;
    class Solution {
        public int romanToInt(String s) {
            int sum=0;
            int prenum=getValue(s.charAt(0));
            for(int i=1;i<s.length();i++){
             
                int num=getValue(s.charAt(i));
                if(prenum<num){
                    sum=sum-prenum;
                }else{
                    sum=sum+prenum;
                }
                prenum=num;
            }
            sum=sum+prenum;
            return sum;
        }
                private int getValue(char ch){
                switch(ch){
                    case 'I':return 1;
                    case 'V':return 5;
                    case 'X':return 10;
                    case 'L':return 50;
                    case 'C':return 100;
                    case 'D':return 500;
                    case 'M':return 1000;
                    default: return 0;
                }
    
            }
    }
    

题号14.最长公共前缀

  • import java.util.*;
    class Solution {
        public String longestCommonPrefix(String[] strs){
        if(strs == null||strs.length==0){
            return "";
        }
        int count=strs.length;
        int length=strs[0].length();
        for(int i=0;i<length;i++){
            char c=strs[0].charAt(i);
            for(int j=1;j<count;j++){
                if(i==strs[j].length()||strs[j].charAt(i) != c){//重点复习
                return strs[0].substring(0,i);
                }
            }
        }
       return strs[0];
        }
    }
    
  • 错误:

    import java.util.*;
    class Solution {
        public String longestCommonPrefix(String[] strs){
        if(strs == null||strs.length==0){
            return "";
        }
        int count=strs.length;
        int length=strs[0].length();
        for(int i=0;i<length;i++){
            char c=strs[0].charAt(i);
            for(int j=1;j<count;j++){
                if(strs[j].charAt(i) != c||i==strs[j].length()){//重点复习
                return strs[0].substring(0,i);
                }
            }
        }
       return strs[0];
        }
    }
    
    • 错误描述[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YUWVBqN1-1611670523522)(C:\Users\HASEE\AppData\Roaming\Typora\typora-user-images\1611463976005.png)]
    • strs[j].charAt(i) != c||i==strs[j].length()与两个逻辑语句的顺序有关,是先判断达到某个字符串最大长度还是判断字符不相等的顺序与代码顺序有关,最开始我的代码是先判断字符不相等了,结果出了上图的错,一个字符先达到了最大长度,strs[1].charAt(2)语句直接报错,没有进行之后的长度判断。
    • 本道题的细节在于应先判断字符串的长度是否达到最大

题号20.有效的括号

  • import java.util.HashMap;
    class Solution {
        public boolean isValid(String s) {
            Map<Character,Character> pair=new HashMap<Character,Character>(){{
            put(')','(');
            put(']','[');
            put('}','{'); 
            }};
    
            Deque<Character> stack=new LinkedList<Character>(); 
            for(int i=0;i<s.length();i++){
                char ch=s.charAt(i);
                if(pair.containsKey(ch)){
                    if(stack.isEmpty()||stack.peek()!=pair.get(ch)){
                        return false;
                    }
                    stack.pop();
                }else{
                    stack.push(ch);
                }
            }
            return stack.isEmpty();
    
        }
    }
    
  • HashMap的初始化值得注意。声明时初始化速度较快。

  • 栈也是一种表。pop()弹出栈顶值,peek()访问栈顶值。

  • 解法很妙。

  • import java.util.HashMap;
    class Solution {
        public boolean isValid(String s) {
            Map<Character,Character> pair=new HashMap<Character,Character>();
            pair.put(')','(');
            pair.put(']','[');
            pair.put('}','{'); 
            
    //这种初始化方法较上面声明时初始化速度慢。
            Deque<Character> stack=new LinkedList<Character>(); 
            for(int i=0;i<s.length();i++){
                char ch=s.charAt(i);
                if(pair.containsKey(ch)){
                    if(stack.isEmpty()||stack.peek()!=pair.get(ch)){
                        return false;
                    }
                    stack.pop();
                }else{
                    stack.push(ch);
                }
            }
            return stack.isEmpty();
    
        }
    }
    

题号21.合并两个有序链表

  • 当一个函数用它自己来定义时就称为是递归。

  • 不断剔除两个链表中的最小值

  • 解法一:递归

    • /**
       * Definition for singly-linked list.
       * public class ListNode {
       *     int val;
       *     ListNode next;
       *     ListNode() {}
       *     ListNode(int val) { this.val = val; }
       *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
       * }
       */
      class Solution {
          public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
              if(l1 ==null){
                  return l2;
              }
              if(l2 ==null){
                  return l1;
              }
              if(l1.val<l2.val){
                  l1.next=mergeTwoLists(l1.next,l2);
                  return l1;
              }else{
                  l2.next=mergeTwoLists(l1,l2.next);
                  return l2;
              }
          }
      }
      
    • 方法巧妙,但也难想。

    • 思路就是函数功能是返回两个链表的最小值。递归一次返回一个最小值然后将剩下的节点再输入函数作递归,一步步直到出现空链表,递归结束。

  • 解法二:迭代

    • /**
       * Definition for singly-linked list.
       * public class ListNode {
       *     int val;
       *     ListNode next;
       *     ListNode() {}
       *     ListNode(int val) { this.val = val; }
       *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
       * }
       */
      class Solution {
          ListNode prehead=new ListNode(-1);//prehead是头节点
          ListNode prev=prehead;//prev是移动节点
          
          public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
              /*if(l1 ==null){
                  return l2;
              }
              if(l2 ==null){
                  return l1;
              }
              if(l1.val<l2.val){
                  l1.next=mergeTwoLists(l1.next,l2);
                  return l1;
              }else{
                  l2.next=mergeTwoLists(l1,l2.next);
                  return l2;
              }*/
      
              while(l1!= null&&l2!=null){
                  if(l1.val<l2.val){
                      prev.next=l1;
                      l1=l1.next;
                  }else{
                      prev.next=l2;
                      l2=l2.next;
                  }
                  prev=prev.next;
              }
              prev.next=l1==null?l2:l1;
              return prehead.next;//从第二个节点开始返回
      
          }
      }
      

题号.26 删除排序数组中的重复项

  •  class Solution {
        public int removeDuplicates(int[] nums) {
            if(nums.length==0) return 0;
            int i=0;
            for(int j=1;j<nums.length;j++){
                if(nums[j]!=nums[i]){
                    i++;
                    nums[i]=nums[j];
                }
            }
            return i+1;
        }
    }
    
  • 这个解法双指针用的巧妙,自愧不如。人这双指针真是优雅。

  • i是慢指针,j是快指针,只有找到不同值时i+1,把nums[j]的值赋给nums[i+1],nums[j]=nums[i]时就让快指针加。

  • package com.leetcode;
    
    import com.BeforeShiErZhang.QuadrangleUseInterface;
    
    public class question {
            public int removeDuplicates(int[] nums) {
                int length = 0;
                for (int i = 0; i < nums.length; i++) {
                    int j=i;
                    while(j<nums.length&&nums[j]==nums[i]){
                        j++;
                    }
                    length = i ;
                }
                return length;
            }
        public static void main(String[] args) {
                question q1=new question();
    
                System.out.println(q1.removeDuplicates(new int[]{0, 0, 1, 1, 1, 2, 2, 3, 3, 4}));
        }
    }
    
  • 这是我的解法,在内层循环中找到不一样的值之后不知道怎么停下来,只能一直找到最大的。

题号27.移除元素

  • class Solution {
        public int removeElement(int[] nums, int val) {
            int i=0;
            for(int j=0;j<nums.length;j++){
            
                if(nums[j]!=val){
                    nums[i]=nums[j];
                    i++;
                }
            }
            return i;
        }
    }
    

题目28.实现strStr()

  • class Solution {
        public int strStr(String haystack, String needle) {
            //解法一:滑动窗口
           /* int n=haystack.length();
            int L=needle.length();
            for(int start=0;start<n-L+1;start++){
                if(haystack.substring(start,start+L).equals(needle)){
                    return start;
                }
            }
            return -1;*/
    
            //解法二:双指针
            int n=haystack.length();
            int L=needle.length();
            if(L==0) return 0;
            int pn=0;
            while(pn<n-L+1){
                while(pn<n-L+1&&haystack.charAt(pn)!=needle.charAt(0)) ++pn;
                int pl=0;
                int err=0;
                while(pl<L&&pn<n&&haystack.charAt(pn)==needle.charAt(pl)){
                    ++pn;
                    ++pl;
                    ++err;
                }
            if(err==L) return pn-L;
            pn=pn-err+1;//当字符串并不完全匹配时,返回到起始位置加1的位置重新匹配。
           
            }
          return -1;
    }
    }
    

题目38.外观数列

  • class Solution {
        public String countAndSay(int n) {
            if(n==1) return "1";//递归的第一件事就是要确定递归结束条件。
            String str=countAndSay(n-1);//上一轮的输出是这一轮的输入,这就是递归。
            StringBuffer ans=new StringBuffer();
            int start=0;
            
            //提供此解法的大神说“递归代码最神的地方就是一个循环可以展现出n个嵌套for()循环。
            //这里的算法在初级算法Lc中经常用到,当与前一个元素不一样时出发函数
            //从1开始是为了方便对比,长度也+1方便对比”
            
            
            for(int i=1;i<str.length()+1;i++){//必须得是str.length()+1,因为遍历到最后一位时,不管最后两位相等与否,都需要i+1,来描述最后一位或最后两位数字的个数。
                if(i==str.length()){
                    ans.append(i-start).append(str.charAt(start));
    
                }else if(str.charAt(i)!=str.charAt(start)){
                    ans.append(i-start).append(str.charAt(start));//StringBuffer类可以直接对StringBuffer对象本身操作,而不是生成新的对象。 像本例的append()方法,直接添加字符进入字符串,最后直接toString()转换为字符串,功能强大。
                    start=i;//双指针遍历
                }
            }
            return ans.toString();
    
                
            }
        }
    
    

栈:

题目155.最小栈

  • class MinStack {
        Deque<Integer> xstack;
        Deque<Integer> minStack;
        /** initialize your data structure here. */
        public MinStack() {
            xstack=new LinkedList<Integer>();
            minStack=new LinkedList<Integer>();
            minStack.push(Integer.MAX_VALUE);//缺少这行代码会报空指针错。
            //原因是:pop()、top()、getMin()操作总是在非空栈上调用,栈不能空,所以在初始化的时候提前加了一个最大值。
        }
        
        public void push(int x) {
            xstack.push(x);
            minStack.push(Math.min(minStack.peek(),x));
        }
        
        public void pop() {
            xstack.pop();
            minStack.pop();
        }
        
        public int top() {
            return xstack.peek();
        }
        
        public int getMin() {
            return minStack.peek();
        }
    }
    
    /**
     * Your MinStack object will be instantiated and called as such:
     * MinStack obj = new MinStack();
     * obj.push(x);
     * obj.pop();
     * int param_3 = obj.top();
     * int param_4 = obj.getMin();
     */
    

题目225.用队列实现栈

  • class MyStack {
        //两个队列实现
        /*Queue<Integer> queue1;
        Queue<Integer> queue2;
        /** Initialize your data structure here. */
        /*public MyStack() {
            queue1=new LinkedList<Integer>();
            queue2=new LinkedList<Integer>();
        }
        
        /** Push element x onto stack. */
        /*public void push(int x) {
            queue2.offer(x);
            //if(queue1.isEmpty()){//queue1里面元素不止一个,应用循环。
            while(!queue1.isEmpty()){
                queue2.offer(queue1.poll());
            }
    
            Queue<Integer> temp=queue2;
            queue2=queue1;
            queue1=temp;
        }
        
        /** Removes the element on top of the stack and returns that element. */
        /*public int pop() {
            int b=queue1.peek();
            queue1.poll();
            return b;
        }
        
        /** Get the top element. */
       /* public int top() {
            
            return queue1.peek();
        }
        
        /** Returns whether the stack is empty. */
       /* public boolean empty() {
            return queue1.isEmpty();
        }*/
    
        //一个队列实现
            /** Initialize your data structure here. */
        Queue<Integer> queue;
        public MyStack() {
            queue=new LinkedList<Integer>();
           
        }
        
        /** Push element x onto stack. */
        public void push(int x) {
            int n=queue.size();
            queue.offer(x);
            for(int i=0;i<n;i++){
                queue.offer(queue.poll());
            }
        }
        
        /** Removes the element on top of the stack and returns that element. */
        public int pop() {
    
            return queue.poll();
        }
        
        /** Get the top element. */
        public int top() {
            return queue.peek();
        }
        
        /** Returns whether the stack is empty. */
        public boolean empty() {
            return queue.isEmpty();
        }
    
    }
    
    /**
     * Your MyStack object will be instantiated and called as such:
     * MyStack obj = new MyStack();
     * obj.push(x);
     * int param_2 = obj.pop();
     * int param_3 = obj.top();
     * boolean param_4 = obj.empty();
     */
    

题目232.用栈实现队列

  • class MyQueue {
        Deque<Integer> stack1;
        Deque<Integer> stack2;
        int front;
        /** Initialize your data structure here. */
        public MyQueue() {
            stack1=new LinkedList<Integer>();
            stack2=new LinkedList<Integer>();
    
        }
    
    
        
        /* Push element x to the back of queue. */
        public void push(int x) {
            //解法一
           /* while(!stack1.isEmpty()){
                stack2.push(stack1.pop());
            }
            stack1.push(x);
            while(!stack2.isEmpty()){
                stack1.push(stack2.pop());
            }*/
    
            //解法二
            if(stack1.isEmpty()){
                front=x;
            }
            stack1.push(x);
    
    
        }
        
        /** Removes the element from in front of queue and returns that element. */
        public int pop() {
            //解法一
            //return stack1.pop();
    
            //解法二
            if(stack2.isEmpty()){
                while(!stack1.isEmpty()){
                    stack2.push(stack1.pop());
                }
            }
            return stack2.pop();
        } 
        
        /** Get the front element. */
        public int peek() {
            //解法一:return stack1.peek();
            //解法二:
            if(stack2.isEmpty()){
                return front;
            }else{
                return stack2.peek();
            }
        }
        
        /** Returns whether the queue is empty. */
        public boolean empty() {
            //解法一:return stack1.isEmpty();
            //解法二:
            return stack2.isEmpty()&&stack1.isEmpty();
        }
    }
    
    /**
     * Your MyQueue object will be instantiated and called as such:
     * MyQueue obj = new MyQueue();
     * obj.push(x);
     * int param_2 = obj.pop();
     * int param_3 = obj.peek();
     * boolean param_4 = obj.empty();
     */
    

题目493.下一个更大元素

  • 单调栈+哈希map

  • //本人解法
    class Solution {
        public int[] nextGreaterElement(int[] nums1, int[] nums2) {
            Deque<Integer> stack=new LinkedList<Integer>();
            Map<Integer,Integer> map=new HashMap<Integer,Integer>();
            int ans[]=new int[nums1.length];
            for(int i=0;i<nums2.length;i++){
            while((!stack.isEmpty())&&nums2[i]>stack.peek()){
                
                map.put(stack.pop(),nums2[i]);
            }
            stack.push(nums2[i]);
            }
            for(int i=0;i<nums1.length;i++){
                if(map.containsKey(nums1[i])){
                     ans[i]=map.get(nums1[i]);
                }else{
                    ans[i]= -1;
                }
            }
            return ans;
        }
    }
    
  • 
    class Solution {
        public int[] nextGreaterElement(int[] nums1, int[] nums2) {
            Deque<Integer> stack=new LinkedList<Integer>();
            Map<Integer,Integer> map=new HashMap<Integer,Integer>();
            int ans[]=new int[nums1.length];
            for(int i=0;i<nums2.length;i++){
            while((!stack.isEmpty())&&nums2[i]>stack.peek()){
                
                map.put(stack.pop(),nums2[i]);
            }
            stack.push(nums2[i]);
            }
            //本人用for()循环实现
            /*for(int i=0;i<nums1.length;i++){
                if(map.containsKey(nums1[i])){
                     ans[i]=map.get(nums1[i]);
                }else{
                    ans[i]= -1;
                }
            }*/
            //官方题解:
            while(!stack.isEmpty()){
                map.put(stack.pop(),-1);//栈中最后剩下的元素跟-1对应起来。
            }
            for(int i=0;i<nums1.length;i++){
                ans[i]=map.get(nums1[i]);
            }
            return ans;
        }
    }
    

题目682.棒球比赛

  • 首先想到用哈希map记录x,+,D,C分别对应得操作,但是不知如何实现对前面得分的操作。

  • 既然是栈这一节,考虑能不能用栈实现?

  • 突然想到能不能用递归?因为有些操作是对前次得分的操作,函数最后返回的是得分。但是递归结束条件不是很明显。

  • 将字符串入栈,x入栈,+把栈的元素弹出并且入栈(能够将前两次的值弹出加起来再分别入栈吗)(可以实现),c就把栈顶元素删除,D就取栈顶值2入栈。

  • class Solution {
        public int calPoints(String[] ops) {
            int ans=0;
            Deque<Integer> stack=new LinkedList<Integer>();
            for(int i=0;i<ops.length;i++){
               if(ops[i].equals("+")){
                   int a=stack.pop();
                   int b=stack.peek();
                   //int b=stack.pop();
                  // stack.push(b)
                   stack.push(a);
                   stack.push(a+b);
               }else if(ops[i].equals("D")){
                   stack.push(stack.peek()*2);
               }else if(ops[i].equals("C")){
                   stack.pop();
               }else{
                   stack.push(Integer.parseInt(ops[i]));
               }
            }
            while(!stack.isEmpty()){
                ans=stack.pop()+ans;
            }
    
            return ans;
        }
    }
    
  • 两个方法内存消耗差0.lMB,全国排名差了60%。

题目844.比较含退格的字符串

  • 本题需要先对字符串进行处理,之后再比较

  • 退格字符串左侧字母删掉

  • 需对字符串操作

  • 遍历字符串找到所有退格字符,将其左侧字符删掉。

  • 可考虑将字符串入栈,当遇到退格字符时,栈顶值pop。当栈为空遇到退格字符不操作。

  • 对两个栈中元素进行比较,循环出栈。

    class Solution {
        public boolean backspaceCompare(String S, String T) {
            //自己解法:
            /*Deque<Character> stack1=new LinkedList<Character>();
            Deque<Character> stack2=new LinkedList<Character>();
            for(int i=0;i<S.length();i++){
                if(S.charAt(i) == '#'&&(!stack1.isEmpty())){
                    stack1.pop();
                }else if(S.charAt(i) == '#'){
                    stack1.push(S.charAt(i));
                }else{
                    stack1.push(S.charAt(i));
                }
            }
            for(int i=0;i<T.length();i++){
                if(T.charAt(i) == '#'&&(!stack2.isEmpty())){
                    stack2.pop();
                }else if(T.charAt(i) == '#'){
                    stack2.push(T.charAt(i));
                }else{
                    stack2.push(T.charAt(i));
                }
            }
            while(!stack1.isEmpty()&&!stack2.isEmpty()){
                if(stack1.pop()!=stack2.pop()){
                    return false;
                }
            }
         return (stack1.isEmpty()||stack1.peek()=='#')&&(stack2.isEmpty()||stack2.peek()=='#');*/
         //官方解法:重构字符串
            return build(S).equals(build(T));
        }
                public String build(String str){
                StringBuffer ret=new StringBuffer();
                int length=str.length();
                for(int i=0;i<length;i++){
                    char ch=str.charAt(i);
                    if(ch!='#'){
                        ret.append(ch);
                    }else{
                        if(ret.length()>0){
                            ret.deleteCharAt(ret.length()-1);
                        }
                    }
                }
                return ret.toString();
            }
    }
    
  • /

    //双指针
    class Solution {
        public boolean backspaceCompare(String S, String T) {
            //自己解法:
            /*Deque<Character> stack1=new LinkedList<Character>();
            Deque<Character> stack2=new LinkedList<Character>();
            for(int i=0;i<S.length();i++){
                if(S.charAt(i) == '#'&&(!stack1.isEmpty())){
                    stack1.pop();
                }else if(S.charAt(i) == '#'){
                    stack1.push(S.charAt(i));
                }else{
                    stack1.push(S.charAt(i));
                }
            }
            for(int i=0;i<T.length();i++){
                if(T.charAt(i) == '#'&&(!stack2.isEmpty())){
                    stack2.pop();
                }else if(T.charAt(i) == '#'){
                    stack2.push(T.charAt(i));
                }else{
                    stack2.push(T.charAt(i));
                }
            }
            while(!stack1.isEmpty()&&!stack2.isEmpty()){
                if(stack1.pop()!=stack2.pop()){
                    return false;
                }
            }
         return (stack1.isEmpty()||stack1.peek()=='#')&&(stack2.isEmpty()||stack2.peek()=='#');*/
         //官方解法:
          /*  return build(S).equals(build(T));
        }
                public String build(String str){
                StringBuffer ret=new StringBuffer();
                int length=str.length();
                for(int i=0;i<length;i++){
                    char ch=str.charAt(i);
                    if(ch!='#'){
                        ret.append(ch);
                    }else{
                        if(ret.length()>0){
                            ret.deleteCharAt(ret.length()-1);
                        }
                    }
                }
                return ret.toString();*/
    
                //双指针:
                int i=S.length()-1,j=T.length()-1;
                int skipS=0,skipT=0;
                while(i>=0 || j>=0){//当两个字符串的指针都小于0退出循环
                    while(i>=0){//对字符串s处理,若是#则skipS加一,说明前面多一个被抵消的字符。
                        //若不是#且skipS>0说明是个需要删掉的字符。两者都不是则是需要保留的字符,跳出循环去跟另一个字串比较。
                        if(S.charAt(i)=='#'){
                            skipS++;
                            i--;
                        }else if(skipS>0){
                            skipS--;
                            i--;
                        }else{
                            break;
                        }
                    }
                    while(j>=0){
                        if(T.charAt(j)=='#'){
                            skipT++;
                            j--;
                        }else if(skipT>0){
                            skipT--;
                            j--;
                        }else{
                            break;
                        }
                    }
                    //判断条件:
                    //如果这个字符不相等,直接返回false
                    //如果这个字符只是一个字串有,另一个字串指针已经<0,则数目不匹配。
                    //这里之所以要排除return false而不是直接限定相等的情况,是因为这只是判断一个字符,即使判断出相等也无法返回true,相反判断出不相等可以直接返回false。
                    if(i>=0&&j>=0){
                        if(S.charAt(i)!=T.charAt(j)){
                            return false;
                        }
                    }else{
                        if(i>=0||j>=0){
                            return false;
                        }
                    }
                    i--;
                    j--;
                }
                return true;//当两个字符都遍历完之后,若还是不不相等,则返回true。
    
            }
    }
    
    • 双指针解法时间复杂度O(N+M),空间复杂度O(1)。

题目1021.删除最外层的括号

  • 将问题分为两部分,原语化分解和去外括号

  • 将括号字符串堆栈,当入栈值与栈顶值对应则弹出,并重新入栈2,当栈弹空时即为外括号将其去掉。

  • 通过判断栈为空可以找到一个原语。

  • 如何去掉外括号呢?问题在于这种括号(()),如果按顺序出栈就会分成两个括号。

  • class Solution {
        public String removeOuterParentheses(String S) {
            StringBuilder ans=new StringBuilder();
            Stack<Character> stack=new Stack<>();
            int start=0;
            int end=0;
            boolean flag=false;
            for(int i=0;i<S.length();i++){
                char ch=S.charAt(i);
                if(ch=='('){
                    stack.push(ch);
                    if(!flag){
                        start=i;
                        flag=true;
                    }
                }
                if(ch==')'){
                    stack.pop();
                    if(stack.isEmpty()){
                        end=i;
                        ans.append(S.substring(start+1,end));
                        flag=false;
                        start=end;
                    }
                }
            }
            return ans.toString();
        }
    }
    
    • 这题我钻了牛角尖,老是想着入栈出栈后直接加到结果ans上。但实际上是两步,虽然没法还原(()),但是我能成功找到原语,后面无非就是去括号,去括号可以考虑一些其他做法的,通过坐标描述就可以去掉括号的其实。

题目1047.删除字符串中的所有相邻重复项

  • 将字符串入栈,判断栈是否为空,如果为空则入栈,不为空判断与栈顶元素是否相同,相同则弹出栈顶元素,否则继续入栈。

  • class Solution {
        public String removeDuplicates(String S) {
            Deque<Character> stack=new LinkedList<>();
            StringBuffer ans=new StringBuffer();
            for(int i=0;i<S.length();i++){
                if(stack.isEmpty()||stack.peek()!=S.charAt(i)){
                    stack.push(S.charAt(i));
                }else {
                    if(stack.peek()==S.charAt(i))
                    stack.pop();
                }
            }
            while(!stack.isEmpty()){
                ans.append(stack.pop());
            }
            return ans.reverse().toString();
        }
    }
    

题目1441.用栈操作构建数组

  • 只要读到不与数组索引差一的数字就输出push,pop,其他数字push。不能这样考虑

  • 双指针,i是列表指针,j是数组指针,for()循环循环遍历列表,计算数组值与列表值差值作为push还是push、pop判断依据。

  • 当数组值与列表值相等(i+1即是列表值)时输入Push,注意得是大写。

  • 当数组值比列表值大,差值为circle。则需循环输出circle次Push、Pop,由于存在for()循环,i每循环一次会+1,则我们输出circle次Push、Pop对应i递增circle-1次,最后一次由for()循环递增,实现将中间元素过滤的功能,找到目标元素。

  • 现在做题分3个步骤:

    1. 读题自己思考解法
    2. 若自己有思路自己先试着编写,实在编写不出来跳到3,编写出来则运行,有bug去IDEA里调试,一般bug都能找出来。
    3. 实在没思路看解析,看懂之后,自己试着编写。
  • class Solution {
        public List<String> buildArray(int[] target, int n) {
            List<String> ans=new ArrayList<>();
            int j=0;
            int circle=0;
            for(int i=0;i<n;i++){
                circle=target[j]-i-1;
                if(circle==0){
                    ans.add("Push");
                    j++;
                }else{
                    for(int d=0;d<circle;d++){
                        ans.add("Push");
                        ans.add("Pop");
                    }
                    for(int m=0;m<circle-1;m++){
                        i++;
                    }
    
                }
                if(j==target.length) break;
            }
            return ans;
    
        }
    }
    

题目1544.整理字符串

  • 本题将字符串入栈,用当前字符与栈顶值比较,若为大小写则弹出栈顶值,否则入栈。

  • 关键在于是否互为大小写的判定,当两个字符不相等且都转化为小写却相等时互为大小写。

  • class Solution {
        public String makeGood(String s) {
            StringBuffer ans=new StringBuffer();
            Deque<Character> stack=new LinkedList<>();
            for(int i=0;i<s.length();i++){
            if(stack.isEmpty()){
                stack.push(s.charAt(i));
            }else if( ! ((stack.peek()!=s.charAt(i))  &&  (Character.toLowerCase( stack.peek()) ==Character.toLowerCase( s.charAt(i)))) ){
                stack.push(s.charAt(i));
            }else{
                stack.pop();
            }
        }
        while(!stack.isEmpty()){
            ans.append(stack.pop());
        }
        return ans.reverse().toString();
    }
    }
    
  • 
    
    class Solution {
        public String makeGood(String s) {
           /* StringBuffer ans=new StringBuffer();
            Deque<Character> stack=new LinkedList<>();
            for(int i=0;i<s.length();i++){
            if(stack.isEmpty()){
                stack.push(s.charAt(i));
            }else if( ! ((stack.peek()!=s.charAt(i))  &&  (Character.toLowerCase( stack.peek()) ==Character.toLowerCase( s.charAt(i)))) ){
                stack.push(s.charAt(i));
            }else{
                stack.pop();
            }
        }
        while(!stack.isEmpty()){
            ans.append(stack.pop());
        }
        return ans.reverse().toString();*/
        //官方解法
        StringBuffer ret=new StringBuffer();
        int retIndex=-1;
        int length=s.length();
        for(int i=0;i<length;i++){
            char ch=s.charAt(i);
            if(ret.length()>0 && Character.toLowerCase(ret.charAt(retIndex))==Character.toLowerCase(ch)&&ret.charAt(retIndex)!=ch){
                ret.deleteCharAt(retIndex);
                retIndex--;
            }else{
                ret.append(ch);
                retIndex++;
            }
        }
        return ret.toString();
    }
    }
    
    • 官方解法比我的解法快1ms,
      1. 最后不需出栈,节省时间,题目中直接对stringBuffer对象操作
      2. 逻辑判断在一个括号里,节省时间。

题目1598.文件夹操作日志搜集器

  • 将字符串列表入栈,遍历字符串列表,对每一项进行如下判断:

    • 如果等于…/,则移除栈顶元素。
    • 如果等于./,则不操作
    • 否则入栈。
  • 最后返回栈内元素数量

  • class Solution {
        public int minOperations(String[] logs) {
            Deque<String> Stack=new LinkedList<>();
            for(int i=0;i<logs.length;i++){
                if((!logs[i].equals("../"))&&(!logs[i].equals("./"))){
                    Stack.push(logs[i]);
                }else {
                    if(logs[i].equals("../")&&!Stack.isEmpty())  Stack.pop();
                }
            }
            int j=0;
            while(!Stack.isEmpty()){
                Stack.pop();
                j++;
            }
            return j;
        }
    }
    
    • 使用栈用时3ms太慢
  • //不使用栈,直接计数,速度1ms,内存37.8MB.
    class Solution {
        public int minOperations(String[] logs) {
     
            int count=0;
            for(String log:logs){
                if(log.equals("../")){
                    if(count==0) continue;
                    count--;
                }else if(log.equals("./")){
                    continue;
                }else{
                    count++;
                }
            }
            return count;
        }
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值