如何用lambda表达式快速刷题


概述

好吧,我承认文章题目有点标题党了,总的来说就是用lambda表达式让你能够在一个函数之内解决战斗(本人很不喜欢刷题的时候拆开写函数),只要用到递归的地方都能够使用。

函数式编程

什么是函数式编程就不展开说了,这里主要用到Lambda演算理论中的Y Combinator,通过它我们可以实现匿名的递归调用函数。关于它的解释,一般是所谓的“懂的都懂”,感兴趣的可以去了解一下,这里只讲怎么用。具体来说,就是在c++中,如果你想在lambda表达式中递归调用自己是不行的(当然后面能够做到,不然也就没这篇文章了),编译器会提示你此时还未定义,那么怎么做呢,就是通过Y Combinator,这也不卖关子了,其实就是把函数自身当成参数传进去即可,这样就可以调用了是不是?

示例

具体怎么写递归不在这篇文章的范围,如果我们想用lambda表达式的话我们应该怎么写?实际上看下面的代码:

class Solution {
public:
    vector<vector<int>> levelOrder(Node* root) {
        vector<vector<int> > res;
        auto func=[&](auto&& func,Node* node,int depth){
            if(node==nullptr){
                return;
            }
            if(res.size()==depth){
                res.push_back({});
            }
            res[depth].push_back(node->val);
            for(auto child:node->children){
                func(func,child,depth+1);
            }
        };
        func(func,root,0);
        return res;
    }
};

lambda表达的第一个参数不一定要和定义的lambda变量重名,可以叫别的名字(通常起名为self),这样写的目的是方便直观的调用,比如下面这样:

代码如下:

class Solution {
public:
  int maxDepth(TreeNode *root) {
    int res = 0;
    auto dfs = [&](auto self, TreeNode *root) -> int {
      if (root == nullptr)
        return 0;
      int left = self(self, root->left);
      int right = self(self, root->right);
      return std::max(left, right) + 1;
    };
    return dfs(dfs, root);
  }
};

细心的可能发现了为什么第一种写法的参数需要用&&而第二个不需要,感兴趣的话可以在下面评论区留言。

结尾

其实一切的起因还是归咎于本人懒,加上代码能力一般实在不想背非递归调用的板子,还是觉得在能保证正确的情况下行数越少逻辑越清晰越好。


评论
  目录