Leetcode-队和栈经典算法题

74 阅读5分钟

跟孙哥学java

孙哥主页

用栈实现队列

用栈实现队列 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty): 实现 MyQueue 类:

  • void push(int x) 将元素 x 推到队列的末尾
  • int pop() 从队列的开头移除并返回元素
  • int peek() 返回队列开头的元素
  • boolean empty() 如果队列为空,返回 true ;否则,返回 false

说明:

  • 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
  • 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。 :::info 解题思路: 队列的特性是 FIFOFIFOFIFO(先入先出),而栈的特性是 FILOFILOFILO(先入后出)。 知道两者特性之后,我们需要用两个栈来模拟队列的特性,一个栈为入队栈,一个栈为出对栈。 当出队栈存在内容时,出队栈的栈顶,即为第一个出队的元素。 若出队栈无元素,我们的需求又是出队的话,我们就需要将入队栈的内容反序导入出队栈,然后弹出栈顶即可。 注意:根据栈的的特性,我们仅能使用 pushpushpush 和 poppoppop 操作。 :::
class MyQueue {
    private static Stack<Integer> inStack;
    private static Stack<Integer> outStack;

    public MyQueue() {
        inStack=new Stack<Integer>();
        outStack=new Stack<Integer>();

    }
    
    public void push(int x) {
        inStack.push(x);

    }
    
    public int pop() {
        if(outStack.isEmpty()){
            in2out();
        }
        return outStack.pop();

    }

    private void in2out() {
        while (!inStack.isEmpty()){
            Integer pop = inStack.pop();
            outStack.push(pop);
        }
    }

    public int peek() {
        if(outStack.isEmpty()){
            in2out();
        }
        return outStack.peek();

    }
    
    public boolean empty() {
        if(inStack.isEmpty()&&outStack.isEmpty()){
            return true;
        }else {
            return false;
        }

    }
}

用队列实现栈

用队列实现栈 请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。 实现 MyStack 类:

  • void push(int x) 将元素 x 压入栈顶。
  • int pop() 移除并返回栈顶元素。
  • int top() 返回栈顶元素。
  • boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。

:::info 解题思路:两个队列 为了满足栈的特性,即最后入栈的元素最先出栈,在使用队列实现栈时,应满足队列前端的元素是最 后入栈的元素。可以使用两个队列实现栈的操作,其中queue1用于存储栈内的元素,queve2作为入 栈操作的辅助队列。 入栈操作时,首先将元素入队到queue2,然后将queue1的全部元素依次出队并入队到queue2,,此 时queue2的前端的元素即为新入栈的元素,再将queue1和queue2互换,则queue1的元素即为栈 内的元素,queue1的前端和后端分别对应栈顶和栈底。 由于每次入栈操作都确保guue1的前瑞元素为栈顶元素,因此出栈操作和获得栈顶元素操作都可以 简单实现。出栈操作只需要移除quue1的前端元素并返回即可,获得栈顶元素操作只需要获得 queue1的前端元素并返回即可(不移除元素)。 由于queue1用于存储栈内的元素,判断栈是否为空时,只需要判断queue1是否为空即可。 :::

class MyStack {
    private Queue<Integer> queue1;
    private Queue<Integer> queue2;


    public MyStack() {
        queue1=new LinkedList<>();
        queue2=new LinkedList<>();

    }
    
    public void push(int x) {
        queue2.offer(x);
        while (!queue1.isEmpty()){
            queue2.offer(queue1.poll());
        }
        Queue<Integer> temp=queue1;
        queue1=queue2;
        queue2=temp;

    }
    
    public int pop() {
        return queue1.poll();

    }
    
    public int top() {
        return queue1.peek();

    }
    
    public boolean empty() {
            return queue1.isEmpty();
    }
}

:::info 一个队列: 入栈操作时,首先获得入栈前的元素个数 nnn,然后将元素入队到队列,再将队列中的前 nnn 个元素(即除了新入栈的元素之外的全部元素)依次出队并入队到队列,此时队列的前端的元素即为新入栈的元素,且队列的前端和后端分别对应栈顶和栈底。 由于每次入栈操作都确保队列的前端元素为栈顶元素,因此出栈操作和获得栈顶元素操作都可以简单实现。出栈操作只需要移除队列的前端元素并返回即可,获得栈顶元素操作只需要获得队列的前端元素并返回即可(不移除元素)。 :::



class MyStack{
    private Queue<Integer> queue;



    public MyStack() {
        this.queue=new LinkedList<Integer>();


    }
    
    public void push(int x) {
        int size = queue.size();
        queue.offer(x);
        while (size>0){
            queue.offer(queue.poll());
            size--;
        }

    }
    
    public int pop() {
        return queue.poll();

    }
    
    public int top() {
        return queue.peek();

    }
    
    public boolean empty() {
            return queue.isEmpty();
    }
}

n数之和专题

两数之和

:::info 解题思路: Hashmap:每次存入 nums[i] - i 如果遍历的时候 map.contains(target-nums[i],就将 value 和i返回 :::

class Solution {
    public int[] twoSum(int[] nums, int target) {
        HashMap<Integer,Integer> map=new HashMap<>();
        int[] res=new int[2];
        for (int i = 0; i < nums.length; i++) {
            if(map.containsKey(target-nums[i])){
                res[0]=map.get(target-nums[i]);
                res[1]=i;
                break;
            }else {
                map.put(nums[i],i);
            }
        }
        return res;
    }
}

三数之和

三数之和 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请 你返回所有和为 0 且不重复的三元组。 **注意:**答案中不可以包含重复的三元组。

示例 1: 输入:nums = [-1,0,1,2,-1,-4] 输出:[[-1,-1,2],[-1,0,1]] 解释: nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。 nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。 nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。 不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。 注意,输出的顺序和三元组的顺序并不重要。 :::info 解题思路: 排序+双指针+去重 :::

class Solution {
    public static void main(String[] args) {
        int[] nums={-1,0,1,2,-1,-4};
        threeSum(nums);
    }
    public static List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        List<List<Integer>> res=new ArrayList<>();
        for (int i = 0; i < nums.length-2; i++) {
            int x=nums[i];
            int l=1+i;
            int r=nums.length-1;
            while (l<r){
                if(nums[l]+nums[r]+x==0){
                    List<Integer> list=Arrays.asList(x,nums[l],nums[r]);
                    res.add(list);
                    l++;
                    r--;
                }else if(nums[l]+nums[r]+x>0){
                    r--;
                }else {
                    l++;
                }
            }
        }

        return res.stream().distinct().collect(Collectors.toList());

    }
}