自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(105)
  • 收藏
  • 关注

原创 【LeetCode】 713.乘积小于 K 的子数组

使用双指针left,和right,left从原始数组最左侧位置开始,right指针默认与left指针位置相同,且他们的乘积为子数组第一个元素的值,接着比较乘积与目标值k的大小,如果乘积小于目标值k,则有指针right右移一位,乘积也变大,直到他们的乘积大于等于目标值k,则本次left循环结束。1、审题:输入一个整数数组nums,和整数值k,要求从数组中找出所有的子数组,要求子数组中所有元素的乘积小于整数k,返回所有的子数组的个数。下一轮循环从left+1位置继续求子数组的乘积值。2、解题:双指针解法。

2026-11-04 10:07:41 231

原创 【LeetCode】 209.长度最小的子数组

2、解题:使用双指针解法l-r,刚开始左右指针都指向数组最左侧元素,然后判断双指针指向的子数组的和大小sum,如果和大于等于target的值,1、审题:输入一个正整数数组和一个整数值target,要求从数组中找出一个最短子数组,子数组的和大于等于target的值,并返回子数组的长度。如果小于target的值,则右指针往右移,扩大sum和的大小,直到数组的最右侧。子数组长度,要比对的是最小长度,所以默认值应该要是更大的值。求他们子数组的长度,并且让左指针left左移一位继续比较。

2026-10-29 09:27:36 128

原创 【LeetCode】 15.三数之和

先从i开始,i元素固定,然后在后面的[i+1,n-1]范围内找出两个元素的和等于-nums[i]的大小,并且该范围的数组已经是递增的了,这个操作和之前的求两数之和的操作一样的了。输入一个整数数组,要求从数组中找出三个元素,最终三个元素的和为0,这样的三个元素存在多个,返回他们组成的数组。该题是之前两数之和的升级版,先对数组进行排序,从数组中找出下标分别为i,j,k,并且他们的顺序是递增的。用三层for循环,让每一个都能与其他两个元素进行相加,并求最后三个元素的和是否等于0。可以采用双指针解法来实现。

2026-10-26 09:20:49 220

原创 261014-【LeetCode】 167.两数之和 II - 输入有序数组

如果相同,则返回两个指针下标值组成的数组,如果他们的和大于目标值target,则将右侧指针right往左移right--,使他们的和减少。输入一个递增序列的整数数组和一个target目标值,要求从数组中找出两个元素,并使他们的和等于目标值,最终返回符合要求的两个元素的下标组成的数组。题目给出的数组是元素递增,采用递增数组特性,使用双指针,刚开始left指向元素小标0,right指向数组最右侧下标size-1。让两个指针指向的元素值进行相加,判断他们的和是否与目标target相同。

2026-10-14 09:48:04 147

原创 【LeetCode】 318. 最大单词长度乘积

现在换成二进制位来标记字母出现的位置,采用的是int类型中的位内容,因为一个int类型的范围大小是4*8=32位,可以容纳所有字母的情况,为字符串中每个字母的出现设置其位的值为1.最后判断两个字符串是否存在相同字母时,只需要使用位运算&判断结果值是否等于0即可。接着判断需要比较的两个字符串是否存在相同的字母,采用同样的思路,继续使用两层for循环,遍历两个字符串中的每个字母,判断是否存在相同字母,不存在相同字母,则求两个字符串长度的乘积大小。如果没有同时存在,且求出他们的最后长度乘积的值。

2026-10-10 09:22:25 210

原创 ​【LeetCode】137. 只出现一次的数字 II​

题目要求在数组中找出仅出现一次的元素(其余元素均出现三次),需线性时间与常数空间。解法二采用位运算累加思想:统计每一位上1的总数,对3取余后重构目标数字。时间复杂度O(N),空间复杂度O(1)。

2026-09-24 09:32:48 196

原创 【LeetCode】338、比特位计数

比特位计数。

2026-09-20 19:58:05 196

原创 【LeetCode】67、二进制求和

二进制数据表示和位运算核心思路:通过while循环,不断从低位向高位获取字符串中的二进制数值,进行计算当前位置结果值和进位值扩展:使用链表方式表示的数字也可以采用这种思路。

2026-09-07 18:30:00 395

原创 【LeetCode】29、两数相除

整数包括始终数据类型,他有正负号与数值表示范围整数遵循四则运算法则,超过数值范围会导致数值溢出暴力解法采用被除数不断减去除数的次数,直到被除数小于除数折半解法采用两层while循环,每次减少被除数的一半,采用位移方式减出除数的2的倍数。

2026-09-02 19:30:00 404

原创 【C++】026、C++内存分布:全局变量、局部变量、static变量、const常量

1、全局静态看程序生命周期(全局/静态区),局部临时变量看栈空间(Stack),动态申请看堆空间(Heap),字面常量只读区(常量区),函数指令代码区(.text)未初始化的全局变量和静态变量的默认值为0;因为.bss段数据在程序加载时由操作系统强制清零(memset),只有栈上的局部未初始化变量才是随机值。2、特殊情况:全局const在常量区,局部cosnt在栈区。

2026-08-19 20:10:07 237

原创 【C++】025、内存对齐

假设一个int(4字节)存放在地址0x1001未对齐的地址上,CPU需要先读取0x1000~0x1003这4个字节,再读取0x1004~0x1007这4个字节,然后再通过移位和拼接操作拼出正确的int值。当new int时,返回的地址一定是4的倍数,所以即使我们写char *p = new char[1]时,内存的起始地址也是16字节对齐的。所以对结构体内存优化操作:可以先把占用空间大的成员放在前面,小的放在后面,这样填充和总的结构体大小会变短。内存对齐要求数据的起始地址必须是其自身大小的整数倍。

2026-08-10 20:14:33 235

原创 【C++】024、new[]与delete[]配对使用

错误写法: string *p = new string[10];delete p;

2026-08-07 21:45:00 208

原创 【C++】023、移动语义&深拷贝

深拷贝会复制整个底层数据,让源对象和目标对象都拥有自己独立的堆内存空间移动语义是转换底层资源的所有权,将源对象的指针指向目标对象,而不赋值底层数据,时间复杂都为1移动语义将源对象的资源指针移动到目标对象,并将源对象指针设置为nullptr,这样源对象的析构操作就不会释放已经释放的资源了。移动构造函数,与移动赋值操作符函数实现 外部调用代码三、移动语义操作中置空源对象的原因?1、防止双重释放: 如果源对象的析构函数被调用时,m_data还指向原来的地址,他就会delete[]这

2026-08-05 19:59:31 174

原创 【C++】022、深拷贝&浅拷贝

移动是把源对象的指针直接置空(nullptr),并把指针值偷给目标对象,移动后的源对象处于有效但未指定的状态,他的析构函数不会再释放资源。如果一个类需要自定义析构函数释放资源,那么一定需要自定义拷贝构造函数和拷贝赋值运算符,以及C11后的移动构造和移动赋值。浅拷贝:仅仅逐字节复制对象本身的内存布局,两个对象中的指针成员指向同一块动态内存。反之,如果不需要析构函数,就不要自定义拷贝操作,直接让编译器生成默认的浅拷贝。C++中的移动语义既不是深拷贝,也不是浅拷贝,只是一种资源窃取。深拷贝会复制一份数据(昂贵)

2026-08-03 19:49:30 234

原创 【C++】021、RAII

RAII(Resource Acquisition Is Initialization)资源获取即初始化,是C++中唯一且核心的资源管理范式。RAII的设计思路是将资源的生命周期与栈上的对象的生命周期作用域进行强绑定,利用C++编译器保证确定性析构,让资源管理自动化就是让栈对象配合资源释放,无论是正常返回,还是中途抛出异常,栈对象一定会销毁,对应资源也一定会释放。

2026-07-30 20:29:41 234

原创 【C++】020、野指针&悬空指针

未初始化或已被赋值的指针,指向垃圾地址指针曾指向内存,但该内存已被释放或销毁。

2026-07-28 19:30:00 244

原创 【C++】019、内存泄漏

指程序在动态分配内存后,失去了对该内存块的所有指针引用,导致在程序内存生命周期结束前无法被释放或回收的现象。

2026-07-21 20:12:43 224

原创 【C++】018、内存分区的完整布局

虚拟人地址通过MMU(内存管理单元)和页表,将虚拟机地址映射到物理内存中,当需要将虚拟内存保存到物理内存中时,会触发缺页中断,以页表的方式进行映射。权限:只读(Read),可执行(Execute),绝对不可写,试图修改代码区的操作,会导致触发段错误(Segmant Fail)我们所说的内存,和内存分区,其实是指虚拟地址空间的逻辑划分,并非物理内存,且每个进程拿到的虚拟地址空间都完全一样。存放内容:函数局部变量,函数参数,返回地址,,栈帧信息,临时对象。只读数据,如字符串,字面量,cosnt全局数据。

2026-07-20 21:12:03 212

原创 【C++】017、new/delete与malloc/free的区别

new 默认分配失败时会抛出异常 std::bad_alloc异常,使用try-catch可捕获异常,不用每次判空,也就是说使用new创建对象实例,成功了就可以直接使用,如果失败就会报错。new 先调用operate new(运算符重载)函数,来分配原始内存(底层也是调用的malloc库函数),接着调用对象的构造函数来初始化申请到的内存。new出来的内存,不能使用free进行释放,malloc也一样,因为两则new、malloc在堆管理数据结构的头部信息不同,混用会导致内存崩溃。

2026-07-15 20:34:29 195

原创 【C++】016、栈和堆的区别

现代C++建议尽量不用new/delete,改为使用智能指针unique_ptr 与 make_unique来申请内存。new、malloc操作后一直存在,直到delete,free被调用或进程结束,不确定强。字符串string存储位置,如果是端字符串会进行优化存储在栈上,长字符串使用堆保存。栈分配仅需一条cpu指令,堆分配涉及操作系统调用,和空闲链表遍历。变量在声明时创建,离开作用域{}时,立刻析构销毁,确定性强。每个线程拥有独立的栈空间,局部变量是线程私有的。大数据,多态对象,容器内部用堆。

2026-07-08 19:50:27 255

原创 【C++】015、函数参数:值传递,指针传递,引用传递的区别

指针可指向另外的对象地址,而引用不允许。实参的别名(底层也是地址)无(引用必须事先绑定对象)能(通过解引用*ptr)实参的副本(全新拷贝)实参地址(拷贝地址值)能(直接操作原对象)小(拷贝8字节地址)空值(null)风险。有(空指针需判断空)

2026-07-07 19:28:36 180

原创 【C++】014、左值与右值的区别

左值是有户口本的居民;右值是有暂住证的旅客;move是让居民办理临时注销,把资源合法转移给新用户。

2026-07-07 19:15:06 180

原创 【C++】013、空类占多少字节?

在C++中,任何完整的对象在内存中都必须具有唯一的地址// 输出:1// 输出两个不同的地址(说明确实占了1字节,地址不同)

2026-07-06 19:06:01 357

原创 【C++】012、typedef和using的区别

typedef和using的核心功能都是为类型创建别名(type alias),注意是给类型创建别名,让复杂类型变得简洁易读。suing是C++11引入的现在语法,优于typedef(C++98)using支持模板别名,typedef做不到。“声明式”将新名字放在类型后面,容易搞混。“赋值式”,新名字在左边,类型在右边。遵循C++作用域规则。遵循C++作用域规则。

2026-07-06 19:04:55 259

原创 【C++】011、mutable关键字

mutable的设计目的,是为了允许类成员变量在const成员成函数中被修改。但是这个函数希望第一次读取时计算数据并进行缓存结果,后续直接返回缓存值。将互斥锁Mutex声明为mutable,让const函数能安全地加锁。则mutable修饰的成员变量,可满足上面的要求。但mutable关键字破坏了第一个规则。不允许调用其他非const成员函数。不允许修改任何非静态成成员变量。使用const函数返回对象数据。

2026-07-06 19:03:38 255

原创 【C++】010、volatile关键字

Volatilede 的设计是为了告诉编译器,这个变量在使用过程中可能会被外部不可知因素修改,要求每次使用都必须从内存中读取,不允许将数据缓存到寄存器中去。缺点:但在多线程场景下,他不足以保证线程安全,因为他只解决了编译器可见性,没解决“CPU缓存一致性”和“原子性”。在现代多核CPU中,线程A修改了volatile变量,修改后的值可能还躺在A核的缓存里,没有刷回到主内存中,这时线程B读到的依然是旧值。原因:volatile禁止编译器重排,但不禁止CPU乱序执行。不保证(仅防寄存器缓存,不防CPU缓存)

2026-07-03 19:40:34 252

原创 【C++】009、extern关键字

本质:extern 关键字修饰的声明是承诺,而不是定义,它不分配内存,只是告诉编译器,这个符号(变量/函数)在其他编译单元(.cpp文件)中有定义,请链接时去哪里找。代码实现// 定义(分配内存)void logMessage() { ... } // 定义// 声明(不分配内存),告诉编译器去外部找// 声明(通常省略,函数默认就是extern的)// 链接时去 FileA.obj 找 g_counter// 链接时去 FileA.obj 找 logMessage。

2026-07-03 19:39:28 207

原创 【C++】008、sizeof与strlen的区别

sizeof是C++操作运算符,在编译期计算内存字节数strlen是C标准库的函数,在运行期通过遍历直到遇到'\0'来计算字符串的长度。

2026-07-01 20:30:00 262

原创 【C++】007、宏与inline的区别

场景:函数体包含循环(for/while),递归,switch分支过多,或静态变量声明时,编译器通常会自动忽略inline请求,把它当做普通函数进行处理。场景:通过基类指针或引用调用virtual inline函数时,由于调用目标在运行时才能确定(查虚表),编译器无法再编译期展开内联函数。场景:当把inline函数赋值给函数指针,或者通过函数指针回调时,编译器必须生成该函数的实际地址(可执行实体),此时内联无法展开。inline对于编译器而言,只是建议,不是命令,会根据情况,有可能不会展开。

2026-06-30 20:26:18 224

原创 【C++】006、#define与const的区别

const:本质上是变量,全局const存储在.rodata段(只读数据段),局部const存储在栈(stack)上。为规避宏定义的副作用,现代C++代码实践中不建议继续使用#define,改用替代方案。#define宏定义是在预处理阶段,进行文本替换操作,属于预处理器管辖。#define使用场景,只在头文件防卫,条件编译和日志/断言中使用。他们在类型安全,作用域,内存分配和调试体验上都有着本质差异。无法调试(宏在预处理阶段已被替换,找不到相关信息)分配内容(本质是变量,存放在数据段或栈中)

2026-06-30 20:25:02 251

原创 【C++】005、struct与class的区别

/ ✅ 好:struct 表示纯粹的数据聚合// ✅ 好:class 表示有约束的实体对象private:// 必须 >= 0,有业务约束(不变量)public:void deposit(double amount) { /* 校验逻辑 */ }void withdraw(double amount) { /* 校验逻辑 */ }

2026-06-26 20:20:21 231

原创 【C++】004、C与C++的最核心的区别

struct结构体,他不是类,内部只有属性,没有方法,要给struct的对象的属性进行赋值,必须在外部的函数中,将该对象指针作为参数传递,在函数中进行对象属性值的赋值。C++支持面向对象(封装、继承、多态),泛型编程,,函数式(lambda)。C语言只能通过函数指针与void*来实现抽象,类型检查较弱,多态需要运行时传参,有一定开销且不直观。数据(struct封装)和操作(函数)是分离的,要操作数据,必须把数据指针传给函数。C++通过模板编程实现多态,在编译期生成代码,无运行时开销,也就是零开销抽象。

2026-06-26 18:45:00 235

原创 【C++】003、static关键字

场景存储位置/生命周期作用域/链接性初始化次数局部变量静态存储区(程序结束时才销毁)函数内部/作用域为函数范围1次(线程安全)全局变量/函数静态存储区本文件内部(内部链接)1次(程序启动时初始化)静态成员函数静态存储区(全局共享)类域(需外部定义)1次静态成员函数无this,属于类类域(通过类名调用)--

2026-06-24 20:07:46 179

原创 【C++】002、const关键字使用

底层const (const int *),规定指向的值不能改变,赋值给int*后,约束破坏了,他可以修改对象的值。在成员函数声明末尾加const,表示该函数不会修改任何非静止成员(变量mutable成员除外)顶层const (int* const), 指向的指针不能改变,但是对象值可以改变,不受影响。const关键字在C++中不只是表示常量,他的核心是只读契约。特点:值不能改,但指针可以改(是顶层const)特点:指向不能改,但值可以改(是顶层const)用于替代#define。返回引用防止返回值修改。

2026-06-22 20:15:21 205

原创 【C++】001、引用与指针的区别

对指针使用sizeof得到的是指针本身的大小,表示指针变量本身所占的字节数,64位的计算机结果值为8字节。这也是引用必须在初始化时绑定对象,且不可变更绑定的原因所在。指针可以通过复制改变指向,一个指针通过赋值预算福=可以指向其他对象的地址。指针需要用*接引用才能访问对象,使用->来访问对象的属性值和方法调用。而且引用比指针使用更安全,不用担心空指针,也不必显示解引用。引用的底层通常使用指针常量来实现的。引用定义时必须绑定一个对象,不能是空引用。引用必须绑定有效对象,不允许空引用存在。

2026-06-17 19:38:50 253

原创 【算法专题训练】38、二分查找算法

本文介绍了二分查找算法及其在LeetCode题目中的应用。首先讲解了二分查找的基本原理:在有序数组中通过分治思想将查找范围不断缩小,时间复杂度为O(log n)。随后分析了四道LeetCode题目: LCR 068:在有序数组中查找目标值或应插入位置,通过比较中间值与目标值调整查找范围。 LCR 069:寻找山脉数组的峰顶索引,利用二分法判断中间元素处于上升还是下降区间。 LCR 070:在成对出现的有序数组中找出唯一元素,通过比较相邻元素确定异常位置。 LCR 071:按权重随机选择,通过前缀和数组配合二

2026-01-27 19:15:00 1498

原创 【算法专题训练】37、前缀树&二叉树

本文讨论了如何在数组中找出两个数的最大异或值。首先介绍了暴力解法,通过双重循环计算所有数对的异或值并取最大值,时间复杂度为O(n²)。然后提出更高效的前缀树解法,将每个数字的二进制位存入二叉树,从最高位开始构建。查询时优先选择相反位以最大化异或结果,时间复杂度优化为O(n)。两种方法都给出了C++实现代码,重点解释了前缀树构建和查询过程中的位运算处理技巧,以及如何通过二进制位优先匹配来保证高位异或结果最大化。

2026-01-12 18:15:00 297

原创 【算法专题训练】36、前缀树路径和

本文介绍了两个基于前缀树的算法问题。1)LCR 065单词压缩编码:通过构建逆序单词的前缀树,计算所有叶子节点路径长度之和,实现最小编码长度。2)LCR 066键值映射:设计MapSum类,使用前缀树存储键值对,insert方法更新节点值,sum方法通过深度优先遍历统计指定前缀所有键值的总和。两个问题都利用了前缀树高效处理字符串前缀的特性,分别实现了字符串压缩和前缀统计功能。

2025-12-30 18:30:00 205

原创 【算法专题训练】35、前缀树查找

前缀树构建,每个节点包含子节点个数为26,根据字符在字母表中的位置,查找对应的子节点在数组中的位置前缀树查找,也是同样的思路,根据字符位置查找对应结点位置,并不断赋值,直到最后结点的单词标记位为true。

2025-12-25 18:30:00 591

原创 【算法专题训练】34、前缀树

本文介绍了前缀树(字典树)的基本概念和实现方法。前缀树是一种多叉树结构,用于高效存储和检索字符串,每个节点代表一个字符,路径表示字符串。文章详细讲解了前缀树的特性,如节点最多26个子节点(对应英文字母)、路径可能终止于非叶节点等。随后以LeetCode题目LCR 062为例,展示了如何实现前缀树的插入、查询和前缀匹配功能,提供了完整的C++代码实现。最后总结了前缀树的核心要点,包括路径表示单词、结束标记位isWord以及创建查询的逻辑。该数据结构适用于自动补全、拼写检查等场景。

2025-12-16 18:30:00 467

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除