牛客刷题2

122 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天。

牛客网刷题第二天

JZ6 从尾到头打印链表

描述

输入一个链表的头节点,按链表从尾到头的顺序返回每个节点的值(用数组返回)。

如输入{1,2,3}的链表如下图:

img

返回一个数组为[3,2,1]

0 <= 链表长度 <= 10000

输入:
{1,2,3}
返回值:
[3,2,1]

思路

  • ListNode是链表,只能从头到尾,要求从尾到头输出,标准的先进后出,可以用栈
  • ArrayList有个add(index,value)方法,可以在指定位置添加value值
/**
*    public class ListNode {
*        int val;
*        ListNode next = null;
*
*        ListNode(int val) {
*            this.val = val;
*        }
*    }
*
*/
import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        ArrayList<Integer> list = new ArrayList<Integer>();
        ListNode linklist = listNode;
        while(linklist != null){
            list.add(0,linklist.val);
            linklist = linklist.next;
            
        }
        return list;
        
    }
}

JZ7 重建二叉树

描述

给定节点数为 n 的二叉树的前序遍历和中序遍历结果,请重建出该二叉树并返回它的头结点。

例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建出如下图所示。

img

提示:

1.vin.length == pre.length

2.pre 和 vin 均无重复元素

3.vin出现的元素均出现在 pre里

4.只需要返回根结点,系统会自动输出整颗树做答案对比

数据范围:n \le 2000n≤2000,节点的值 −10000≤val≤10000

要求:空间复杂度 O(n)O(n),时间复杂度 O(n)O(n)

思路

  • 先序遍历,是根左右,中序遍历是左根右
  • 先序遍历第一个元素是根节点1,找到根节点去中序遍历找左右分支{4,7,2},{5,3,8,6}
  • 拿到左分支,根据先序遍历,找到左分支的根节点2,再去中序遍历中划分左右子分支{4,7},此时无右分支
  • 依次查找
import java.util.*;
/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] vin) {
        if(pre.length == 0 || vin.length == 0){
            return null;
        }
        TreeNode root = new TreeNode(pre[0]); //根节点是先序遍历的第一个元素
        for(int i=0;i<vin.length;i++){
            if(vin[i] == pre[0]){
                root.left = reConstructBinaryTree(Arrays.copyOfRange(pre,1,i+1),Arrays.copyOfRange(vin,0,i));
                //Arrays.copyOfRange(T[ ] original,int from,int to)
                //将一个原始的数组original,从下标from开始复制,复制到上标to,生成一个新的数组。
                //注意这里包括下标from,不包括上标to。
                root.right = reConstructBinaryTree(Arrays.copyOfRange(pre, i + 1, pre.length), Arrays.copyOfRange(vin, i + 1, vin.length));
                break;
            }
        }
        return root;
    
        
    }
}

JZ8 二叉树的下一个结点

描述

给定一个二叉树其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的next指针。下图为一棵有9个节点的二叉树。树中从父节点指向子节点的指针用实线表示,从子节点指向父节点的用虚线表示

1650551617196

示例:

输入:{8,6,10,5,7,9,11},8

返回:9

解析:这个组装传入的子树根节点,其实就是整颗树,中序遍历{5,6,7,8,9,10,11},根节点8的下一个节点就是9,应该返回{9,10,11},后台只打印子树的下一个节点,所以只会打印9,如下图,其实都有指向左右孩子的指针,还有指向父节点的指针,下图没有画出来

img

数据范围:节点数满足 1 \le n \le 50 \1≤n≤50 ,节点上的值满足 1 \le val \le 100 \1≤val≤100

要求:空间复杂度 O(1) *O *(1) ,时间复杂度 O(n)O(n)

输入描述:

输入分为2段,第一段是整体的二叉树,第二段是给定二叉树节点的值,后台会将这2个参数组装为一个二叉树局部的子树传入到函数GetNext里面,用户得到的输入只有一个子树根节点

返回值描述:

返回传入的子树根节点的下一个节点,后台会打印输出这个节点

输入:
{8,6,10,5,7,9,11},8
返回值:
9

思路

import java.util.*;
public class Solution {
    List<TreeLinkNode> list = new ArrayList<>();
    public TreeLinkNode GetNext(TreeLinkNode pNode) {
        // 根据传入的节点的 next 指针一直往上找,直到找到根节点 root
        TreeLinkNode root = pNode;
        while (root.next != null) root = root.next;
​
        // 对树进行一遍「中序遍历」,保存结果到 list 中
        dfs(root);
​
        // 从 list 中找传入节点 pNode 的位置 idx
        int n = list.size(), idx = -1;
        for (int i = 0; i < n; i++) {
            if (list.get(i).equals(pNode)) {
                idx = i;
                break;
            }
        }
​
        // 如果 idx 不为「中序遍历」的最后一个元素,那么说明存在下一个节点,从 list 查找并返回
        // 这里的 idx == -1 的判断属于防御性编程
        return idx == -1 || idx == n - 1 ? null : list.get(idx + 1);
    }
    void dfs(TreeLinkNode root) {
        if (root == null) return;
        dfs(root.left);
        list.add(root);
        dfs(root.right);
    }
}

\