zoukankan      html  css  js  c++  java
  • 树-leetcode做题笔记

    总结:对于二叉树的常见问题:

    当涉及到按层序遍历,对二叉树进行各种操作时,常常采用栈或队列来对每一层数据进行保存

    收获:对做题时常用的结构的方法进行了一下简要总结

    1.Queue

    Queue: 基本上,一个队列就是一个先入先出(FIFO)的数据结构

    Queue接口与List、Set同一级别,都是继承了Collection接口。LinkedList实现了Deque接 口。

    下表显示了jdk1.5中的阻塞队列的操作:

      add        增加一个元索                     如果队列已满,则抛出一个IIIegaISlabEepeplian异常
      remove   移除并返回队列头部的元素    如果队列为空,则抛出一个NoSuchElementException异常
      element  返回队列头部的元素             如果队列为空,则抛出一个NoSuchElementException异常
      offer       添加一个元素并返回true       如果队列已满,则返回false
      poll         移除并返问队列头部的元素    如果队列为空,则返回null
      peek       返回队列头部的元素             如果队列为空,则返回null
      put         添加一个元素                      如果队列满,则阻塞
      take        移除并返回队列头部的元素     如果队列为空,则阻塞

    remove、element、offer 、poll、peek 其实是属于Queue接口。 

    在日常做题时,能使用offer(),就不使用add()

    2.ArrayList

    ArrayList是Java集合框架中的一个重要的类,它继承于AbstractList,实现了List接口,是一个长度可变的集合,提供了增删改查的功能。集合中允许null的存在。ArrayList类还是实现了RandomAccess接口,可以对元素进行快速访问。实现了Serializable接口,说明ArrayList可以被序列化,还有Cloneable接口,可以被复制。和Vector不同的是,ArrayList不是线程安全的。

    size()              函数返回集合中元素的数量;

    isEmpty()          函数返回集合是否为空,检查size是否为0,即使容量不为0(没有元素)

    contains(Object o)  检查集合中是否包含给定的元素

    indexOf(Object o)    函数返回集合中给定元素的第一次出现的位置,如果没有就返回-1

    lastIndexOf(Object o) 函数返回给定元素最后一次出现的位置,如果没有就返回-1:

    toArray()              将集合转化为数组;

    get(int index)      返回指定位置的元素

    set(int index,E element)   设置给定位置的元素为给定的元素,然后返回原来的元素

    add(E e)    添加元素;

    add(int index,E element)    在指定位置添加元素

    remove(int index)      删除指定位置的元素,然后返回这个元素

    addAll(Collection<? extends E> c)    添加给定集合中的所有元素到集合中,从末尾开始添加

    removeRange(int fromIndex,int toIndex)    删除给定范围内的所有元素

    3.LinkedList

    ArrayList基于动态数组的实现,它长于随机访问元素,但是在中间插入和移除元素时较慢

    LinkedList基于链表实现,在List中间进行插入和删除的代价较低,提供了优化的顺序访问。LinkedList在随机访问方面相对比较慢,但是它的特性集较ArrayList更大。

    支持的基础操作
    getFirst() getLast() removeFirst() removeLast() addFirst() addLast()

     本题要用到的双端队列

    public boolean offerFirst(E e) {
        addFirst(e);
        return true;
    }
    public boolean offerLast(E e) {
        addLast(e);
        return true;
    }
    public E peekFirst() {
        if (size == 0)
            return null;
        return getFirst();
    }
    public E peekLast() {
        if (size == 0)
            return null;
        return getLast();
    }
    public E pollFirst() {
        if (size == 0)
            return null;
        return removeFirst();
    }
    public E pollLast() {
        if (size == 0)
            return null;
        return removeLast();
    }

    题目如下(按之字形层序遍历)

    Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between).

    For example:
    Given binary tree{3,9,20,#,#,15,7},

        3
       / 
      9  20
        /  
       15   7
    

    return its zigzag level order traversal as:

    [
      [3],
      [20,9],
      [15,7]
    ]
    对于这类问题,首先想到的是利用中序遍历来达到层序遍历的结果,然后依次对于间隔行进行翻转
     1 import java.util.*;
     2 public class Solution {
     3     public ArrayList<ArrayList<Integer>> zigzagLevelOrder(TreeNode root) {
     4         ArrayList<ArrayList<Integer>> res=new ArrayList<ArrayList<Integer>>();
     5         
     6        Queue<TreeNode> queue=new LinkedList<>();
     7         if(root==null) return res;
     8         queue.offer(root);
     9         ArrayList<TreeNode> tmp=new ArrayList<>();
    10         int k=0;
    11         while(!queue.isEmpty()){
    12             int size=queue.size();
    13             ArrayList<Integer> list=new ArrayList<>();
    14            
    15             for(int i=0;i<size;i++){
    16                 TreeNode node =queue.poll();
    17                 tmp.add(node);
    18                 list.add(node.val);
    19                    if(node.left!=null) queue.offer(node.left);
    20                 if(node.right!=null) queue.offer(node.right);                               
    21             }
    22             if(k%2==1){
    23                 Collections.reverse(list);
    24                 }
    25             
    26             k++;
    27             res.add(list);
    28         }
    29      
    30         return res;
    31     }
    32 }

     如果熟悉ArrayList的add(int index,E element)    函数,也可以利用将元素直接添加到list位置0处以替换上面代码中对应列表的翻转,如下:

     1 import java.util.*;
     2 public class Solution {
     3     public ArrayList<ArrayList<Integer>> zigzagLevelOrder(TreeNode root) {
     4         ArrayList<ArrayList<Integer>> res=new ArrayList<ArrayList<Integer>>();
     5         
     6        Queue<TreeNode> queue=new LinkedList<>();
     7         if(root==null) return res;
     8         queue.offer(root);
     9         ArrayList<TreeNode> tmp=new ArrayList<>();
    10         int k=0;
    11         while(!queue.isEmpty()){
    12             int size=queue.size();
    13             ArrayList<Integer> list=new ArrayList<>();
    14            
    15             for(int i=0;i<size;i++){
    16                 TreeNode node =queue.poll();
    17                 tmp.add(node);
    18                 if(k%2==0)  list.add(node.val);
    19                 if(k%2==1) list.add(0,node.val);
    20                    if(node.left!=null) queue.offer(node.left);
    21                 if(node.right!=null) queue.offer(node.right);                               
    22             }
    23           
    24             
    25             k++;
    26             res.add(list);
    27         }
    28      
    29         return res;
    30     }
    31 }

    如果,我们将整个操作仔细细想一下,发现也可以用两个栈相互配合,交替使用,依次保存本行和下一行的数据,也可以达到同样的效果,只是整个操作没有前面方法方便

     1 import java.util.*;
     2 public class Solution {
     3     public ArrayList<ArrayList<Integer>> zigzagLevelOrder(TreeNode root) {
     4 
     5           TreeNode c = root;
     6         ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
     7         if (c == null)
     8             return res;
     9         Stack<TreeNode> s1 = new Stack<TreeNode>();
    10         Stack<TreeNode> s2 = new Stack<TreeNode>();
    11         s1.push(root);
    12         while (!s1.isEmpty() || !s2.isEmpty()) {
    13             ArrayList<Integer> tmp = new ArrayList<Integer>();
    14             while (!s1.isEmpty()) {
    15                 //先用栈1保存第一行的数据,然后将下一行的节点数据保存到栈2
    16                 c = s1.pop();
    17                 tmp.add(c.val);
    18                 if (c.left != null)
    19                     s2.push(c.left);
    20                 if (c.right != null)
    21                     s2.push(c.right);
    22             }
    23             res.add(tmp);
    24             //将第一行的数据保存
    25             tmp = new ArrayList<Integer>();
    26             while (!s2.isEmpty()) {
    27                 //将栈2中的依次数据出栈,然后将其子节点推入栈1
    28                 //需要注意的是子节点入栈的顺序,因为是之字形遍历,所以对于上面的要从左到右的入栈,
    29                 //对于此处要从右到左的入栈
    30                 c = s2.pop();
    31                 tmp.add(c.val);
    32                 if (c.right != null)
    33                     s1.push(c.right);
    34                 if (c.left != null)
    35                     s1.push(c.left);
    36             }
    37             if (!tmp.isEmpty())
    38                 res.add(tmp);
    39         }
    40         return res;
    41     }
    42     }

     既然可以用两个栈来完成,那么也可以用队列再来试试,但显然用两个队列是不行的,但是我们可以使用一个双向队列来进行操作,同样AC

     1 import java.util.*;
     2 public class Solution {
     3     public ArrayList<ArrayList<Integer>> zigzagLevelOrder(TreeNode root) {
     4 
     5           TreeNode c = root;
     6         boolean flag=true;
     7         ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
     8         if (c == null)  return res;
     9         LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
    10         queue.offerFirst(c);
    11        while(!queue.isEmpty()){
    12            ArrayList<Integer> list=new ArrayList<>();
    13            int size=queue.size();
    14            if(flag){
    15                    for(int i=0;i<size;i++){
    16                    TreeNode node=queue.pollFirst();
    17                    list.add(node.val);
    18              
    19                    if(node.left!=null) queue.offerLast(node.left);
    20                    if(node.right!=null) queue.offerLast(node.right);  }
    21                res.add(list);
    22                }else{
    23                        for(int i=0;i<size;i++){
    24                    TreeNode node=queue.pollLast();
    25                    list.add(node.val);
    26                            
    27                    if(node.right!=null) queue.offerFirst(node.right); 
    28                    if(node.left!=null) queue.offerFirst(node.left);
    29                      }
    30                res.add(list);
    31                        
    32                    }
    33            flag=!flag;
    34        }
    35    return res;
    36     }
    37 }
    38           

    资料参考:

    List的API

    ArrayList详解

    LinkedList 讲解

    java中的Queue

  • 相关阅读:
    从零开始的HTML5之旅(三)
    2020年3月12日
    2020年3月14日
    错误There is no Action mapped for namespace / and action name—Struts2
    2014.05.06我在这里起航
    Test For Windows Live Writer
    点亮灯泡——JS实现
    windows phone中解决html乱码问题
    .net处理多线程
    Windows Store App之数据存储
  • 原文地址:https://www.cnblogs.com/pathjh/p/8678931.html
Copyright © 2011-2022 走看看