树-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

posted @ 2018-03-31 00:47  pathjh  阅读(305)  评论(0编辑  收藏  举报