没看的视频都要补起来,都是基础思路得积累,前三题视频补,昨天的视频也要补。今天任性一把,先自己试着做了,花费时间太长,得不偿失
654.最大二叉树
朴素想法
思路:
- 查最大值,利用其前序构造
- 切割出新数组,递给下一层
改进:
- 新节点是又一组数中最大值确定的,思路用数组传递这个数字集合,设计到数组的搬移,可以直接在原数组上用指针框出数字集合传递下去
- 改进用chatgpt写的,二刷或有空再自己复现
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode constructMaximumBinaryTree(int[] nums) {
return traversal(nums);
}
TreeNode traversal(int [] nums){
if(nums.length == 0){
return null;
}
int max = getMaxVal(nums);
TreeNode root = new TreeNode(max);
int[] leftNums = maxValLeftNums(nums , max);
int[] rightNums = maxValRightNums(nums , max);
root.left = traversal(leftNums);
root.right = traversal(rightNums);
return root;
}
int getMaxVal(int[] nums){
int max = 0;
for(int num : nums){
if(num > max){
max = num;
}
}
return max;
}
int[] maxValLeftNums(int[] nums , int max){
int index = 0;
for(int i = 0; i < nums.length; i++){
if(nums[i] == max){
index = i;
}
}
if(index == 0){
return new int[0];
}
int[] res = new int[index];
for(int i = 0; i < index; i++){
res[i] = nums[i];
}
return res;
}
int[] maxValRightNums(int[] nums , int max){
int index = 0;
for(int i = 0; i < nums.length; i++){
if(nums[i] == max){
index = i;
}
}
if(index == nums.length - 1){
return new int[0];
}
int[] res = new int[nums.length - 1 - index];
for(int i = index + 1 , j = 0; i < nums.length ; i++ , j++){
res[j] = nums[i];
}
return res;
}
}
ChatGPT改进代码
class Solution {
public TreeNode constructMaximumBinaryTree(int[] nums) {
return construct(nums, 0, nums.length - 1);
}
TreeNode construct(int[] nums, int left, int right) {
if (left > right) {
return null;
}
int maxIdx = findMaxIndex(nums, left, right);
TreeNode root = new TreeNode(nums[maxIdx]);
root.left = construct(nums, left, maxIdx - 1);
root.right = construct(nums, maxIdx + 1, right);
return root;
}
int findMaxIndex(int[] nums, int left, int right) {
int maxIdx = left;
for (int i = left + 1; i <= right; i++) {
if (nums[i] > nums[maxIdx]) {
maxIdx = i;
}
}
return maxIdx;
}
}
617.合并二叉树
朴素想法
思路:
- 在递归遍历旧树的同时,前序构造新节点
问题:
- 新节点的作用域没出 if 语句,导致root.left和root.right无法被识别,虽然 if 条件覆盖了所有的情况,但root出不了 if 语句。(由ChatGPT查出,以前也遇到过但没查出原因)
- 递给下一层函数传参时使用了指针取值的操作。(尤其是这种递下去的参数是两个指针,有四种情况,单个null的处理两种情况易考虑不周出错),自认为参数列表可以接受null,并设置语句在函数体内解决null,但只是解决双null终止递下去,而忽视单null会继续递下去,而单null递下去就会对单null做取值操作出现空指针,递的时候的参数是依靠上一个递进来的指针做取值操作的。
解决方案:
- 问题一:
- ChatGPT:在 if 外构造节点,在 if 内赋值
- 文心一言:既然root作用域在 if 里 ,那就把剩下的所有操作都放进 if 。
- 问题二:
- ChatGPT:在递的函数的参数列表里用三元条件表达式选择null
- 文心一言:在递的函数 外面设置 if 条件作为入口
ChatGPT帮改错
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
if (root1 == null && root2 == null) {
return null;
}
TreeNode root = null;
if (root1 != null && root2 != null) {
root = new TreeNode(root1.val + root2.val);
} else if (root1 != null) {
root = new TreeNode(root1.val);
} else if (root2 != null) {
root = new TreeNode(root2.val);
}
root.left = mergeTrees(root1 != null ? root1.left : null, root2 != null ? root2.left : null);
root.right = mergeTrees(root1 != null ? root1.right : null, root2 != null ? root2.right : null);
return root;
}
}
文心一言的改错
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
if(root1 == null && root2 == null){
return null;
}
if(root1 != null && root2 != null){
TreeNode root = new TreeNode(root1.val + root2.val);
root.left = mergeTrees(root1.left , root2.left);
root.right = mergeTrees(root1.right , root2.right);
return root;
}
if(root1 != null && root2 == null){
TreeNode root = new TreeNode(root1.val);
root.left = mergeTrees(root1.left , null);
root.right = mergeTrees(root1.right , null);
return root;
}
if(root1 == null && root2 != null){
TreeNode root = new TreeNode(root2.val);
root.left = mergeTrees(null , root2.left);
root.right = mergeTrees(null , root2.right);
return root;
}
return null;
}
}
700.二叉搜索树中的搜索
朴素想法:
思路:
- 前序写法,大致框架是先写出基本前序的操作语句和左右递的函数,前者用于递到当前节点判断是否与val匹配,后者用于从上往下遍历,属于递的过程,再写出递的终止条件,一种是没匹配到递到了null那就return null,另一种是匹配到了那就return curroot。
- 然后写归的过程,如果找到了 left 子树找到了就一层层return归给上一层,而不用进入right子树的遍历
- 先写递的过程,包括对当前的层次的操作,递的函数,递的终止条件
- 再写归的过程,一般在递到终止节点时,写在递函数的下面,包括左递函数与右递函数中间和右递函数与default return中间,以及default return。
- 本题在递和归的两个过程均有操作语句,在完全搜完子树后才能进行的操作一般放在归的过程中写,也就是在递函数的下面写
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode searchBST(TreeNode root, int val) {
if(root == null){
return null;
}
if(root.val == val){
return root;
}
TreeNode left = searchBST(root.left , val);
if(left != null){
return left;
}
TreeNode right = searchBST(root.right , val);
if(right != null){
return right;
}
return null;
}
}
98.验证二叉搜索树
朴素想法:
- 错解:没完全理解题意,题目要求左子树的全部节点比头结点小,右子树的全部节点比头结点大,我理解成相邻两行满足就行就开始前序遍历了
- 尝试:
- 归的时候分别用两个容器自下而上收集左子树和右子树,但左右子树是相对某一节点而言的,节点时刻在上溯,无法灵活切换容器收集
- 在递的时候维护一个对于左子树笼统的最大值,对于右子树笼统的最小值,相邻层
- 想在前序部分写两个变量分别维护右顶端的最小值和左顶端的最大值,但无法表述当前节点处于root的左边还是右边,无法用 if 控制变量的使用。
放弃自己做,直接看视频
思路:
- 二叉搜索树的性质就是中序遍历是递增的,维护一个当前最大值不断向后比即可
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
long max = Long.MIN_VALUE;
public boolean isValidBST(TreeNode root) {
if(root == null){
return true;
}
boolean left = isValidBST(root.left);
if(max < root.val){
max = root.val;
}else{
return false;
}
boolean right = isValidBST(root.right);
return left && right;
}
}