(Java版)剑指offer (四)

31.栈的压入和弹出
栈辅助法,两个汉诺塔

class Solution {
    public boolean validateStackSequences(int[] pushed, int[] popped) {
		//辅助栈方法
        Stack<Integer> stack = new Stack<>();
        int i = 0;
        for(int num : pushed) {
            stack.push(num); // num 入栈
            while(!stack.isEmpty() && stack.peek() == popped[i]) { // 循环判断与出栈
                stack.pop();
                i++;
            }
        }
        return stack.isEmpty();
    }
}

32-I 从上到下打印二叉树
可以使用层序遍历,但要求的是int[]数据类型输出,所以,考虑结果用什么容器存放比较重要

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int[] levelOrder(TreeNode root) {
        //层序遍历
        if(root == null) return new int[0];
        Queue<TreeNode> queue = new LinkedList<>(){{ add(root); }};//定义并初始化
        ArrayList<Integer> ans = new ArrayList<>();
        while(!queue.isEmpty()) {
            TreeNode node = queue.poll();
            ans.add(node.val);
            if(node.left != null) queue.add(node.left);
            if(node.right != null) queue.add(node.right);
        }
        int[] res = new int[ans.size()];
        for(int i = 0; i < ans.size(); i++)
            res[i] = ans.get(i);
        return res;
    }
}

直接使用双链表输出,需要把双链表转化为int[]

class Solution {
    public int[] levelOrder(TreeNode root) {
        //层序遍历,但是要求是输出int[]
        
        Queue<TreeNode> queue = new LinkedList<>();
        List<List<Integer>> ans = new ArrayList<>();
        if(root !=null) queue.add(root);
        while(!queue.isEmpty()) {
            int size = queue.size();
            List<Integer> tmp = new ArrayList<>();
            for(int i =0;i<size;i++){
                TreeNode node = queue.poll();//返回之后再删除
                tmp.add(node.val);
                if(node.left != null) queue.add(node.left);
                if(node.right != null) queue.add(node.right);                
            }
            ans.add(tmp);
        }
        ArrayList<Integer> collect2 = ans.stream().collect(ArrayList::new, ArrayList::addAll, ArrayList::addAll);
        return collect2.stream().mapToInt(k->k).toArray();//二维链表转换成一维链表在转成一维数组输出,耗时较长,不如前一次提交的方法
    }
}

32-II从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
层序遍历,输出类型为 List<List>

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        //二叉树的层序遍历
        Queue<TreeNode> queue = new LinkedList<>();
        List<List<Integer>> ans = new ArrayList<>();
        if(root !=null) queue.add(root);
        while(!queue.isEmpty()) {
            int size = queue.size();
            List<Integer> tmp = new ArrayList<>();
            for(int i =0;i<size;i++){
                TreeNode node = queue.poll();//返回之后再删除
                tmp.add(node.val);
                if(node.left != null) queue.add(node.left);
                if(node.right != null) queue.add(node.right);                
            }
            ans.add(tmp);
        }
        return ans;
    }
}

32-III 按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        Deque<TreeNode> deque = new LinkedList<>();
        List<List<Integer>> res = new ArrayList<>();
        if(root != null) deque.add(root);
        while(!deque.isEmpty()) {
            // 打印奇数层
            List<Integer> tmp = new ArrayList<>();
            for(int i = deque.size(); i > 0; i--) {
                // 从左向右打印
                TreeNode node = deque.removeFirst();//第一次进入就删除节点,ode不是空节点了吗?
                tmp.add(node.val);
                // 先左后右加入下层节点
                if(node.left != null) deque.addLast(node.left);
                if(node.right != null) deque.addLast(node.right);
            }
            res.add(tmp);
            if(deque.isEmpty()) break; // 若为空则提前跳出
            // 打印偶数层
            tmp = new ArrayList<>();//重新构造临时数组
            for(int i = deque.size(); i > 0; i--) {
                // 从右向左打印
                TreeNode node = deque.removeLast();
                tmp.add(node.val);
                // 先右后左加入下层节点
                if(node.right != null) deque.addFirst(node.right);
                if(node.left != null) deque.addFirst(node.left);
            }
            res.add(tmp);
        }
        return res;
    }
}

33.二叉搜索树的后序遍历序列
搜索树:中序遍历是一个升序排列的数

class Solution {
    public boolean verifyPostorder(int[] postorder) {
        return recur(postorder, 0, postorder.length - 1);
    }
    boolean recur(int[] postorder, int i, int j) {
        if(i >= j) return true;
        int p = i;
        while(postorder[p] < postorder[j]) p++; //postorder[j]是根结点
        int m = p;//划分左右子树
        while(postorder[p] > postorder[j]) p++; //判断右子树是否都大于根结点
        return p == j && recur(postorder, i, m - 1) && recur(postorder, m, j - 1);
    }
}

34.二叉树汇总和为某一值的路径(有难度)

class Solution {
    LinkedList<List<Integer>> res = new LinkedList<>();
    LinkedList<Integer> path = new LinkedList<>(); 
    public List<List<Integer>> pathSum(TreeNode root, int sum) {
        recur(root, sum);
        return res;
    }
    void recur(TreeNode root, int tar) {
        if(root == null) return;
        path.add(root.val);
        tar -= root.val;
        if(tar == 0 && root.left == null && root.right == null)
            res.add(new LinkedList(path));//复制一个path,之后改变path,res中的path不会改变。
            //为什么要new新开辟一个list
        recur(root.left, tar);//前序遍历
        recur(root.right, tar);
        path.removeLast();
    }
}

35.复杂链表的复制
map中的key表示next指针,map中的value表示random指针

class Solution {
    public Node copyRandomList(Node head) {
        if(head == null) return null;
        Node cur = head;
        Map<Node, Node> map = new HashMap<>();
        // 3. 复制各节点,并建立 “原节点 -> 新节点” 的 Map 映射
        while(cur != null) {
            map.put(cur, new Node(cur.val)); //为什么不能直接用cur.val,因为map的value是Node类型
            cur = cur.next;
        }
        cur = head;
        // 4. 构建新链表的 next 和 random 指向
        while(cur != null) {
            map.get(cur).next = map.get(cur.next);//构建next指向
            map.get(cur).random = map.get(cur.random);//构建random指向
            cur = cur.next;
        }
        // 5. 返回新链表的头节点
        return map.get(head);
    }
}

36,二叉搜索树与双向链表

class Solution {
    Node pre, head;
    public Node treeToDoublyList(Node root) {
        if(root == null) return null;
        dfs(root);
		
        head.left = pre; //头结点指向尾结点
        pre.right = head; //尾结点指向头节点
        return head;
    }
    void dfs(Node cur) {
		//中序遍历
        if(cur == null) return;
        dfs(cur.left);
        if(pre == null)  head = cur; //cur左侧没有节点,即此时cur为双向链表中的头节点
        else { //cur左侧有结点
		pre.right = cur;//1->2
		}
        cur.left = pre;//1<-2
        pre = cur;//保存cur
        dfs(cur.right);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值