一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天。
牛客网刷题第二天
JZ6 从尾到头打印链表
描述
输入一个链表的头节点,按链表从尾到头的顺序返回每个节点的值(用数组返回)。
如输入{1,2,3}的链表如下图:
返回一个数组为[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},则重建出如下图所示。
提示:
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个节点的二叉树。树中从父节点指向子节点的指针用实线表示,从子节点指向父节点的用虚线表示
示例:
输入:{8,6,10,5,7,9,11},8
返回:9
解析:这个组装传入的子树根节点,其实就是整颗树,中序遍历{5,6,7,8,9,10,11},根节点8的下一个节点就是9,应该返回{9,10,11},后台只打印子树的下一个节点,所以只会打印9,如下图,其实都有指向左右孩子的指针,还有指向父节点的指针,下图没有画出来
数据范围:节点数满足 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);
}
}
\