剑指Offer15

剑指Offer第十五天

回溯算法(中等)

在这里插入图片描述

题1:二叉树中和为某一值的路径

输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。

在这里插入图片描述

class Solution {
    //回溯算法,可以把要返回的属性放在公共可调用的位置,往往回溯的dfs方法需要去更改他的值
    List<List<Integer>> res = new ArrayList<>();
    
    public List<List<Integer>> pathSum(TreeNode root, int target) {
        //记住设成LinkedList,它能在首尾两端进行插入,而且有对应的API使用,非常方便,在很多情况下,特别是这种回溯递归的算法下,经常会有值的更替,LinkedList十分方便..
        LinkedList<Integer> list = new LinkedList<>();
        helper(root, list, target);
        return res;
    }
    private void helper(TreeNode root, LinkedList<Integer> list, int target) {
        //递归回溯算法的时候,不要想太多,只要对其中某一个节点进行分析就好了,想多了人就晕了
        //比如这里,我们对满足条件的最后叶子节点进行分析。
        //首先,如果这个节点为null,肯定就直接返回了
        if(root == null){
            return ;
        }
        //如果这个节点不为null,说明有值,那么我们往双向链表(队列)中的尾部插入当前值。(尾不尾部其实无所谓,只要是这个插入是有顺序的就可以,因为有顺序的插入可以让我们更方便的进行控制
        list.offerLast(root.val);
        
        target -= root.val;
        //题目条件满足的情况就是,二叉树到底了,且这条路径的和==target
        if(root.left == null && root.right == null && target == 0){
            res.add(new LinkedList<Integer>(list));
        }
        //如果没有满足,就对左右节点进行递归遍历..
        helper(root.left, list, target);
        helper(root.right, list, target);
        //回溯的时候,把痕迹清掉
        list.pollLast();
    }
}

在这里插入图片描述

题2:二叉搜索树与双向链表

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。

在这里插入图片描述

看题解写出来的。。感觉和链表有关的都要用双指针来做。。

class Solution {
    //新增pre指针,保存当前节点的前一个节点
    Node pre;
    //新增head指针,保存当前节点
    Node head;
    public Node treeToDoublyList(Node root) {
        if (root == null) {
            return null;
        }
        dfs(root);
        //等全部递归完,pre节点就移动到最后一个节点了,即链表尾部
        //对pre和head构建关系
        head.left = pre;
        pre.right = head;
        return head;
    }

    private void dfs(Node cur) {
        //入参的当前节点
        if (cur == null) {
            return;
        }
        dfs(cur.left);
        //如果前节点为空,说明是链表头了
        if (pre == null) {
            head = cur;
        } else{
            //如果前节点有值,就需要构建前向的关系
            pre.right = cur;
        }
        cur.left = pre;
        pre = cur;
        dfs(cur.right);
    }
}

在这里插入图片描述

题3:二叉搜索树的第k大节点

给定一棵二叉搜索树,请找出其中第k大的节点。

在这里插入图片描述

class Solution {
    int result;	//要返回的值,放在公共区域。。
    int k;	//懒得传参就写在外面,也可以传参做,都一样
    public int kthLargest(TreeNode root, int k) {
        this.k = k;
        dfs(root);
        return result;
    }

    private void dfs(TreeNode root) {
        if (root == null) {
            return;
        }
        //后序遍历,因为二叉搜索树,大的在right,然后取k大,就从右往左开减。。
        dfs(root.right);
        if (--k ==  0) {
            result = root.val;
            return;
        }
        dfs(root.left);
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值