前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【DFS】汉诺塔问题 / 反转链表 / 求根节点到叶节点数字之和 / 验证二叉搜索树

【DFS】汉诺塔问题 / 反转链表 / 求根节点到叶节点数字之和 / 验证二叉搜索树

作者头像
_小羊_
发布于 2025-04-09 00:40:52
发布于 2025-04-09 00:40:52
11300
代码可运行
举报
文章被收录于专栏:C++C++
运行总次数:0
代码可运行

面试题 08.06. 汉诺塔问题

要将a柱上n个的盘子借助b柱放到c柱上,应该先将a柱上的n-1个盘子借助c放到b上,然后再将b柱上的n-1个盘子借助a柱放到c柱上,以此往复。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
public:
    void hanota(vector<int>& A, vector<int>& B, vector<int>& C) {
        dfs(A, B, C, A.size());
    }
    void dfs(vector<int>& a, vector<int>& b, vector<int>& c, int n)
    {
        if (n == 1)
        {
            c.push_back(a.back());
            a.pop_back();
            return;
        }
        dfs(a, c, b, n - 1); // a柱上的n-1个盘子借助c柱放到b柱上
        c.push_back(a.back());
        a.pop_back();
        dfs(b, a, c, n - 1);
    }
};

合并两个有序链表

重复子问题:合并两个有序列表。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        if (list1 == nullptr) return list2;
        if (list2 == nullptr) return list1;
        if (list1->val <= list2->val)
        {
            list1->next = mergeTwoLists(list1->next, list2);
            return list1;
        } 
        else
        {
            list2->next = mergeTwoLists(list1, list2->next);
            return list2;
        } 
    }
};

反转链表

单链表可以看作一棵树。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if (head == nullptr || head->next == nullptr) return head;
        ListNode* newhead = reverseList(head->next);
        head->next->next = head;
        head->next = nullptr;
        return newhead;
    }
};

两两交换链表中的节点

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if (head == nullptr || head->next == nullptr) return head;
        ListNode* newhead = swapPairs(head->next->next);
        ListNode* ret = head->next;
        head->next->next = head;
        head->next = newhead;
        return ret;
    }
};

Pow(x, n)

当n过大时,我们可以先算x的n/2次方,依此递归,然后相乘。

另外对负数取正可能会超出int范围,所以要强转成long类型。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
public:
    double myPow(double x, int n) {
        return n < 0 ? 1.0 / pow(x, -(long)n) : pow(x, n);
    }

    double pow(double x, long n)
    {
        if (n == 0) return 1;
        double num = pow(x, n / 2);
        return n % 2 == 0 ? num * num : num * num * x;
    }
};

计算布尔二叉树的值

很明显是对二叉树的后序遍历。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
public:
    bool evaluateTree(TreeNode* root) {
        if (root->val == 1) return 1;
        if (root->val == 0) return 0;
        bool left = evaluateTree(root->left);
        bool right = evaluateTree(root->right);
        return root->val == 2 ? left | right : left & right;
    }
};

求根节点到叶节点数字之和

dfs前序遍历:前序遍历按照根节点、左子树、右子树的顺序遍历二叉树的所有节点,通常用于子节点的状态依赖于父节点状态的题。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
public:
    int sumNumbers(TreeNode* root) {
        return dfs(root, 0);
    }
    int dfs(TreeNode* root, int prevsum)
    {
        prevsum = prevsum * 10 + root->val; 
        if (root->left == nullptr && root->right == nullptr) return prevsum;
        int ret = 0;
        if (root->left) ret += dfs(root->left, prevsum);
        if (root->right) ret += dfs(root->right, prevsum);
        return ret;
    }
};

二叉树剪枝

dfs后序遍历:后序遍历按照左子树、右子树、根节点的顺序遍历二叉树的所有节点,通常用于父节点的状态依赖于子节点状态的题目。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
public:
    TreeNode* pruneTree(TreeNode* root) {
        if (root == nullptr) return nullptr;
        root->left = pruneTree(root->left);
        root->right = pruneTree(root->right);
        if (root->left == nullptr && root->right == nullptr && root->val == 0)
        {
            return nullptr;
        }
        return root;
    }
};

验证二叉搜索树

二叉搜索树的中序遍历的结果一定是一个严格递增的序列。 可以初始化一个无穷小的全区变量用来记录中序遍历过程中的前驱结点,那么就可以在中序遍历的过程中,先判断是否和前驱结点构成递增序列,然后修改前驱结点为当前结点,传入下一层的递归中。

  • 在递归问题中有时可以使用全局变量,从而减少参数的传递;
  • 根据条件增加剪枝操作,降低时间复杂度。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
    long prev = LONG_MIN;
public:
    bool isValidBST(TreeNode* root) {
        if (root == nullptr) return true;
        bool left = isValidBST(root->left);
        if (!left) return false; // 剪枝
        bool cur = false;
        if (root->val > prev) cur = true;
        if (!cur) return false; // 剪枝
        prev = root->val;
        bool right = isValidBST(root->right);
        return left && cur && right;
    }
};

二叉搜索树中第 K 小的元素

中序遍历二叉搜索树,找到第k个数即可。

  • 在递归问题中使用全局变量可以减少参数的传递。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
    int ret, count;
public:
    int kthSmallest(TreeNode* root, int k) {
        count = k;
        dfs(root);
        return ret;
    }
    void dfs(TreeNode* root)
    {
        if (root == nullptr) return;
        dfs(root->left);
        if (--count == 0) ret = root->val;
        dfs(root->right);
    }
};

二叉树的所有路径

回溯问题中往往需要我们恢复现场,例如使用全局变量等。如果参数是局部变量,利用传值传参会在不同的栈帧中拷贝各自的数据,因此不会改变参数,也就不需要我们手动恢复现场了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
    vector<string> ret;
public:
    vector<string> binaryTreePaths(TreeNode* root) {
        string path;
        dfs(root, path);
        return ret;
    }
    void dfs(TreeNode* root, string path)
    {
        path += to_string(root->val);
        if (root->left == nullptr && root->right == nullptr) 
        {
            ret.push_back(path);
            return;
        }
        path += "->";
        if (root->left) dfs(root->left, path);
        if (root->right) dfs(root->right, path);
    }
};

本篇文章的分享就到这里了,如果您觉得在本文有所收获,还请留下您的三连支持哦~

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-04-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
立等可取的 Vue + Typescript 函数式组件实战
不同于面向对象编程(OOP)中通过抽象出各种对象并注重其间的解耦问题等,函数式编程(FP) 聚焦最小的单项操作,将复杂任务变成一次次 f(x) = y 式的函数运算叠加。函数是 FP 中的一等公民(First-class object),可以被当成函数参数或被函数返回;同时,这些函数应该不依赖或影响外部状态,这意味着对于给定的输入,将产生相同的输出。
江米小枣
2020/11/04
2.4K0
立等可取的 Vue + Typescript 函数式组件实战
[译]: Vue.js 函数式组件:what, why & when?
原文:https://medium.com/js-dojo/vue-js-functional-components-what-why-and-when-439cfaa08713
江米小枣
2020/07/06
1.9K0
Vue 2x 中使用 render 和 jsx 的最佳实践 (3)
通过对上面的代码进行分析,不难发现,Vue模板中的每一个元素编译之后都会对应一个createElement。
默默的成长
2022/10/29
4.1K0
Vue JSX、自定义 v-model
最初用到 JSX,就是做这个博客的时候。iview 表格组件,不支持像 element 那样直接写 html 代码渲染,只能通过 render 函数渲染,也就是 JSX 语法
Krry
2020/07/16
4.8K1
学会使用Vue JSX,一车老干妈都是你的
连续几篇文章,每篇都有女神,被掘友给吐槽了,今天不提了女神了,反正女神都是别人的(扎心了)。这两天小编看了腾讯与老干妈的事情,晚上馒头夹老干妈吃起来都感觉很带劲。今天这篇文章将给大家小编在项目中使用JSX的一些实战经验。其实一般情况下写Vue还是比较推荐template的写法的,但是有时候我们真的需要更灵活的去做一些功能,这时候就需要用到JSX了。
前端进击者
2021/07/27
3K0
函数式组件完整例子 原
之前创建的组件是比较简单,没有管理或者监听任何传递给他的状态,也没有生命周期方法。它只是一个接收参数的函数。 在下面这个例子中,我们标记组件为 functional,这意味它是无状态 (没有响应式数据),无实例 (没有 this 上下文)。
tianyawhl
2019/04/04
1.7K0
Vue.js 的一些小技巧
比如一个 <my-button> 上暴露了一个 width 属性,我们既可以传 100px,也可以传 100 :
步履不停凡
2019/09/11
8200
Vue.js-渲染函数 & JSX 原
Vue推荐在绝大多数情况下使用template来创建你的Html,然而在一些场景中,你真的需要JavaScript的完全编程的能力,这就是、render函数,它比template更接近编译器 使用template例子
tianyawhl
2019/04/04
2.6K0
搞懂并学会运用 Vue 中的无状态组件
状态管理通常在较小的项目并不需要,但是当涉及到更大的范围时,如企业级的应用大部分需要它了。简单的说,状态是一个包含应用程序使用的最新值的对象。但是,如果咱们从结构的、更抽象的角度来看待它,就会清楚地看到,状态是复杂应该中重要一块,它使能够构建干净的体系结构,并将关注点强有力地分离开来。
前端小智@大迁世界
2019/11/21
1.5K0
搞懂并学会运用 Vue 中的无状态组件
VUE防抖与节流
解释:当持续触发某事件时,一定时间间隔内没有再触发事件时,事件处理函数才会执行一次,如果设定的时间间隔到来之前,又一次触发了事件,就重新开始延时。
码客说
2020/11/19
2.1K0
VUE防抖与节流
Vue.js 源码分析—— Slots 是如何实现的
今天主要分析 Vue.js 中常用的 Slots 功能是如何设计和实现的。本文将分为普通插槽、作用域插槽以及 Vue.js 2.6.x 版本的 v-slot 语法三部分进行讨论。
前端黑板报
2021/07/23
2.7K0
Vue.js 源码分析—— Slots 是如何实现的
Vue.js render函数那些事儿
大多时候,我会使用template, vue单文件去渲染组件。虽然知道Vue中有个render函数,但却很少在项目中去主动使用它。使用最多的地方是在使用一些UI框架的时候,比如iview table中的按钮操作,会使用到render函数。另外平时在阅读一些Vue UI框架源码的时候,也时常能遇到使用render函数的地方,这也激发了自己研究学习的欲望。如果你也感兴趣,那就继续阅读吧。
前端知否
2020/04/07
2.5K0
Vue.js render函数那些事儿
Vuejs函数式组件,你值得拥有(1)
我们可以把函数式组件想像成组件里的一个函数,入参是渲染上下文(render context),返回值是渲染好的HTML
用户2845596
2021/01/21
5700
vue 中使用 jsx 总结
vue 中使用 jsx 调用方式 标签函数组件 // 模式1: 类式函数组件 const Sub = { functional: true, name: "Sub", render(h, context){...} } // 模式2: 函数式函数组件 const Sub = (context) => ( <div> { context.props.title } </div> ) // 标签式调用 <template> <Sub title='函数式组件' />
copy_left
2019/12/12
1.4K0
vue如何二次封装一个高频可复用的组件
在我们的业务里,我们通常会二次封装一些高频业务组件,比如弹框,抽屉,表单等这些业务组件,为什么要二次封装?我们所有人心里的答案肯定是,同样类似的代码太多了,我想复用组件,或者原有组件可能达不到我想要的效果,我想基于原有组件自定义一些自己的接口,那么此时就需要二次封装了。二次封装虽好,但同时也会带来一定的心智负担,因为二次封装的组件可能会变得不那么纯粹。
Maic
2022/12/21
2.4K0
vue如何二次封装一个高频可复用的组件
Vue中vdom的创建
昨天发的牢骚里感觉Vue的三个功能是解析并渲染html模板,解析并执行js,解析并渲染css样式。然后有个核心概念vdom,那么这个虚拟dom(vdom)在代码里是怎么体现的呢。一起来看下。
terrence386
2022/07/14
3840
Vue中vdom的创建
手把手教你用jsx封装Vue中的复杂组件(网易云音乐实战项目需求)
最近在做vue高仿网易云音乐的项目,在做的过程中发现音乐表格这个组件会被非常多的地方复用,而且需求比较复杂的和灵活。
ssh_晨曦时梦见兮
2024/01/27
3590
手把手教你用jsx封装Vue中的复杂组件(网易云音乐实战项目需求)
Vue 进阶必学之高阶组件 HOC(保姆式教学,冲击20k必备)
高阶组件这个概念在 React 中一度非常流行,但是在 Vue 的社区里讨论的不多,本篇文章就真正的带你来玩一个进阶的骚操作。
ssh_晨曦时梦见兮
2020/04/11
5.6K0
你绝对不知道的 Vue 技巧 - 三
什么是指令?指令就是你女朋友指着你说,“那边搓衣板,跪下,这是命令!”。开玩笑啦,程序员哪里会有女朋友。通过上一节我们开发了一个loading组件,开发完之后,其他开发在使用的时候又提出来了两个需求
公众号---人生代码
2020/07/07
7800
vue源码分析-组件
Vue作为单页面应用遇到最棘手的问题是首屏加载时间的问题,单页面应用会把页面脚本打包成一个文件,这个文件包含着所有业务和非业务的代码,而脚本文件过大也是造成首页渲染速度缓慢的原因。因此作为首屏性能优化的课题,最常用的处理方法是对文件的拆分和代码的分离。按需加载的概念也是在这个前提下引入的。我们往往会把一些非首屏的组件设计成异步组件,部分不影响初次视觉体验的组件也可以设计为异步组件。这个思想就是按需加载。通俗点理解,按需加载的思想让应用在需要使用某个组件时才去请求加载组件代码。我们借助webpack打包后的结果会更加直观。
yyzzabc123
2022/10/17
6380
相关推荐
立等可取的 Vue + Typescript 函数式组件实战
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档