当前位置: 首页 > news >正文

8.28 模拟|双指针

 

 

lc 三数之和

 

 

 

lc 四数之和

剪枝法优化,提前终止无效循环

class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
sort(nums.begin(), nums.end());
vector<vector<int>> res;
int n = nums.size(); // 单独用个 int 变量表示 nums.size()
for (int i = 0; i < n - 3; i++) {
long long x = nums[i];
if (i && x == nums[i - 1])
continue;
for (int j = i + 1; j < n - 2; j++) {
long long y = nums[j];
if (j > i+1 && y == nums[j - 1])
continue;
int l = j + 1, r = n - 1;
while (l < r) {
long long sum = x + y + nums[l] + nums[r];
if (sum ==target) {
res.push_back({(int)x, (int)y, nums[l], nums[r]});
for (l++; l < r && nums[l] == nums[l - 1]; l++)
;
for (r--; l < r && nums[r] == nums[r + 1]; r--)
;
} else if (sum > target) {
r--;
} else {
l++;
}
}
}
}
return res;
}
};

 

 

lc2328

// 累加子路径数量
ret = (ret + dfs(x, y)) % mod; 

class Solution {

    typedef long long ll;
const int mod = 1e9 + 7;
public:
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
int m, n;
vector<vector<ll>> memo; // (i,j) 出发的严格递增路径数量

vector<vector<int>> matrix;

int countPaths(vector<vector<int>>& grid) {
matrix = grid;
m = matrix.size();
n = matrix[0].size();
memo.resize(m, vector<ll>(n, 0));

ll cnt = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
// 累加所有格子出发的路径数
cnt = (cnt + dfs(i, j)) % mod; 
}
}
return (int)cnt;
}

    ll dfs(int i, int j) {
if (memo[i][j]) return memo[i][j];

ll ret = 1; 
for (int k = 0; k < 4; k++) {
int x = i + dx[k], y = j + dy[k];
if (x >= 0 && x < m && y >= 0 && y < n 
&& matrix[x][y] > matrix[i][j]) {
// 累加子路径数量
ret = (ret + dfs(x, y)) % mod; 

}
}
return memo[i][j] = ret;

};

lc3459

解决与对角线(这里是类似“之字形”或带转向的对角线相关)遍历、长度计算的问题,核心逻辑围绕深度优先搜索(DFS)结合记忆化( memo  数组)优化,同时用 lambda 实现递归并巧妙处理了  this  捕获与类成员访问,以下从几个关键维度拆解讨论:

 

1. Lambda 里  this auto&& dfs  的语法作用

 

- 语法本质:这是 C++14 及以上支持的递归 lambda 写法, this auto&& dfs  是 C++ 对 lambda 递归调用的一种“就地捕获自身”技巧。

-  auto&&  让编译器自动推导  dfs  的类型(lambda 类型是编译器匿名生成的,无法手动写), this  确保在类成员函数语境下,能正确关联当前类的作用域(比如访问  memo 、 grid  这些类作用域内的变量)。

- 解决的问题:普通 lambda 无法直接递归(因为定义时“自身名字还不存在”),这种写法让 lambda 内部能通过  dfs  调用自己,实现递归逻辑(比如这里的深度优先遍历)。

 

2. 结合评论区讨论的延伸点

 

- 关于  std::function :评论提到“力扣里  std::function  慢,不如 lambda 方便”,原因是  std::function  是类型擦除的封装(内部有虚函数、动态分配等开销),而 lambda 是编译器直接生成的函数对象,调用更高效。

- 代码里用递归 lambda 替代  std::function  包装递归函数,就是在利用 lambda 的轻量优势,尤其刷题场景对时间敏感时,这种写法更优。

- “拐弯后”的逻辑:代码里  can_turn  标记、 k = (k + 1) % 4 (切换方向),对应评论说的“拐弯计算”——遍历到某位置后,尝试切换对角线方向(比如从“右下”拐到“右上”等),继续搜索更长的符合条件的路径,用  maxs  数组做理论长度剪枝(避免无效递归),提升效率。

 

3. 代码整体逻辑串联

 

- 功能:遍历二维网格  grid ,针对每个值为  1  的起点,沿 4 种对角线方向( DIRS )做深度优先搜索,允许“拐弯”切换方向,计算最长连续符合条件(值匹配  target  切换)的对角线长度,最终返回全局最大值  ans 。

- 关键设计:

-  memo  数组做记忆化:记录  (i,j,k)  位置沿方向  k  不拐弯时的结果,避免重复计算。

-  can_turn  控制逻辑:区分“是否允许拐弯”,拐弯时切换方向继续探索,不拐弯时复用  memo  加速。

- 剪枝优化( maxs  数组):通过“理论最大可能长度”预判,跳过不可能超过当前  ans  的递归,减少计算量。

 

简单说,这段代码用 C++ 递归 lambda 的语法技巧,结合记忆化 + 剪枝,高效解决了带方向切换的对角线遍历长度问题,也呼应了评论区关于 lambda 递归、 std::function  性能的讨论,是刷题场景里“语法技巧 + 算法优化”结合的典型写法。

 

lc3446.

利用同一对角线差相等提取vec tmp,sort后再填入

class Solution {

public:

    vector<vector<int>> sortMatrix(vector<vector<int>>& grid) 

    {

        int n = grid.size();

        

        for (int i = 0; i < n; i++) 

        { //提取

            vector<int> vec;

            for (int k = 0; i + k < n; k++) vec.push_back(grid[i + k][k]);

            //排序

            sort(vec.begin(), vec.end(),greater<int>());

            //填入

            for (int k = 0; i + k < n; k++) grid[i + k][k] = vec[k];

        }

        

        // 枚举右上角

        for (int j = 1; j < n; j++) 

        {

            vector<int> vec;

            for (int k = 0; j + k < n; k++) vec.push_back(grid[k][j + k]);

            sort(vec.begin(), vec.end());

            for (int k = 0; j + k < n; k++) grid[k][j + k] = vec[k];

        }

        return grid;

    }

};

 

http://www.dtcms.com/a/354369.html

相关文章:

  • 零基础-力扣100题从易到难详解(持续更新1-10题)
  • Windows 命令行:rmdir 命令
  • Qt 6 与 Qt 5 存在的兼容性差异
  • C# 数组C# 多维数组
  • QML(2) - Qt 中如何注册一个 C++ 类到 QML
  • MySQL的类split方法实现
  • Java表格处理详解以及结合实际项目使用
  • WebStrom-如何设置前端项目快捷启动
  • 29. String, StringBuffer,StringBuilder 的区别是什么
  • 统一虚拟试穿框架OmniTry:突破服装局限,实现多品类可穿戴物品虚拟试穿无蒙版新跨越。
  • 【小白笔记】网速
  • TypeScript:完整的函数类型书写方式
  • 【开题答辩全过程】以超市管理系统为例,包含答辩的问题和答案
  • Linux 系统核心调优:CPU、磁盘 I/O、网络与内核参数实战
  • 流行蝴蝶剑高清重制版Windows10可玩!
  • 小程子找Bug之for循环的初始化表达类型
  • 【美团】放它一马
  • 今日行情明日机会——20250827
  • 即时配送运营平台系统功能分析
  • 寄存器, 堆栈, 汇编指令详解
  • 入门概念|Thymeleaf与Vue
  • 企业微信对接 代理 WXJava Ngnix映射 weixin-java-cp
  • Vue 登录页高低分辨率背景图优化实现
  • mathtype公式存在乱码
  • SqlHelper类的方法详细解读和使用示例
  • Libvio访问异常排查指南
  • sql server 取起始日期到结束日期中自然月最后一天,与日期维度行转列
  • 数据治理:AI健康血液的生命线
  • Elasticsearch数据迁移快照方案初探(一):多节点集群配置踩坑记
  • Anaconda的安装与使用