路径总和-112

class Solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
        return f(root,targetSum);
    }
    bool f(TreeNode* root, int targetSum)
    {   
        //判断根节点是否为空
        if(root == nullptr)return false;
        /*判断是否满足题意,当前叶子节点(root->left == nullptr&&root->right == nullptr)的值
        是否等于剩余目标的和(targetSum == root->val)*/
        if(root->left == nullptr&&root->right == nullptr&&targetSum == root->val) return true;
        //递归计算左子树是否有满足条件的路径,更新目标为剩余值
        bool left = f(root->left,targetSum-root->val);
        //递归计算右子树是否有满足条件的路径,更新目标为剩余值
        bool right = f(root->right,targetSum-root->val);

        return left||right;
    }
};

每日问题

什么是C++中的常量表达式?有什么用途?

1.常量表达式的定义

在C++中,常量表达式是指在编译期间就能计算出结果的表达式。其值在程序运行过程中不会改变,并且可以在编译时确定。常量表达式可以是一个简单的常量,如字面常量(42、3.14等),也可以是由常量和运算符组成的表达式,只要这些运算符在编译阶段能够确定结果。例如,1+2、2*3+4都是常量表达式。

对于变量,只有在 C++ 11 及以后的版本中,用constexpr关键字声明的变量,并且其初始化表达式是一个常量表达式时,这个变量也属于常量表达式。例如:constexpr int num = 10;,这里的num就是一个常量表达式。

2.用途

数组大小定义

常量表达式最重要的用途之一是用于定义数组的大小。在C++中,数组的大小必须是一个常量表达式。例如:const int N = 10; int arr[N];这里N是一个常量表达式,用于确定数组arr的大小。如果不使用常量表达式来定义数组大小,编译器会报错。

在C++11之前,只能使用字面常量或者const修饰的全局变量(其初始值为常量表达式)来定义数组大小,而constexpr的出现使得可以更灵活地定义编译期确定大小的数组,只要满足constexpr的规则即可。

模板参数

常量表达式可以作为模板参数使用。模板是C++中实现泛型编程的重要工具,模板参数要求在编译时确定。例如:

template <int N> class MyArray{/*...*/};
constexpr int size = 5;
MyArray<size> myArr;

这里size作为一个常量表达式,用于确定模板类MyArray的模板参数N,使得编译器可以在编译阶段生成针对特定大小(这里是5)的数组类。

编译期计算优化

常量表达式允许编译器在编译阶段进行计算优化。由于其值在编译时就可以确定,编译器可以直接将常量表达式的结果替换到使用该表达式的地方,而不需要在运行时进行计算,这可以提高程序的运行效率,减少运行时的计算开销。例如,对于表达式constexpr int result = 2 * 3 + 4;,编译器在编译阶段就计算出result的值为10,在程序运行时,就可以直接使用这个预先计算好的值,而不是每次遇到这个表达式都重新计算。

提高代码可读性和可维护性

通过使用常量表达式,可以使代码中的常量更加清晰明了。例如,在一个复杂的数学计算程序中,如果有很多固定的数字常数,将它们定义为常量表达式可以让代码的读者更容易理解这些常数的用途和意义。同时,如果需要修改这些常数的值,只需要在定义常量表达式的地方进行修改,而不需要在代码的多个地方查找和修改相同的数值,提高了代码的可读性。

如何判断一个表达式是否是常量表达式? 

1.字面常量判断

基本数据类型字面常量:像整数常量(如42)、浮点数常量(如3.14)、字符常量(如'a')和字符串字面量(如"hello")这些基本数据类型的字面常量是常量表达式。因为它们的值在编译时就已经确定,并且不会改变。

枚举常量:在C++中,枚举类型(enum)中的枚举常量也是常量表达式。例如:

enum Color{RED,GREEN,BLUE};

这里的RED、GREEN和BLUE是枚举常量,属于常量表达式。它们在编译时就有确定的值(RED通常为0,GREEN为1,BLUE为

2,当然可以自定义初始值),并且不能被修改。

2.由常量和运算符组成的表达式判断

算数运算符:如果一个表达式是由常量通过算术运算符(+、-、*、/、%)组成,并且在编译阶段能够确定结果,那么它是常量表达式。例如,2 + 3 * 4是常量表达式,因为编译器可以在编译时计算出结果为14。但是,如果表达式中包含变量,且这个变量不是constexpr变量,那么这个表达式通常不是常量表达式。例如,int x = 5; int y = 2 * x;,这里的y表达式不是常量表达式,因为x的值不是在编译时确定的。

逻辑运算符和关系运算符:对于由常量通过逻辑运算符(&&、||、!)和关系运算符(==、!=、>、、>=、)组成的表达式,如果在编译阶段能确定结果,也是常量表达式。例如,true && false(结果为false)、5 > 3(结果为true)都是常量表达式。

位运算符:位运算符(&、|、^、~、、>>)作用于常量时,若能在编译阶段确定结果,同样是常量表达式。例如,1 (结果为8)是常量表达式。

3.const 和 constexpr修饰的变量判断

const变量(全局或静态):在C++中,具有外部链接(全局)或内部链接(静态)的const变量,并且其初始值是常量表达式时,这个const常量可以被看做常量表达式。例如:

const int global_const = 10;//全局const变量,初始值为常量表达式,是常量表达式
static const int static_const = 20;//静态const变量,初始值为常量表达式,是常量表达式

constexpr常量:用constexpr关键字修饰的变量,并且其初始化表达式是常量表达式时,这个变量时常量表达式。例如:

int func(){ return 5;}
constexpr int not_const_expr = func();//不是常量表达式,因为func()在运行时才能确定值

4.函数调用判断

constexpr函数调用:如果一个函数被声明为constexpr函数,并且其参数都是常量表达式,那么这个函数调用在编译阶段可以被计算,结果是常量表达式。例如

constexpr int square(int x){ return x * x;}
constexpr int result = square(3);//result是常量表达式,square(3)在编译时计算出结果为9

其他普通函数调用(通常不是):对于普通函数调用,如果函数内部的操作不都是在编译阶段能确定的,那么这个函数调用一般不是常量表达式。例如:

int add(int a,int b){return a + b};
int x = 2;
int y = add(x,3);

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部