2.1 LeetCode总结(基本算法)_DFS

news2024/12/24 0:09:17

1.4 练习

104. 二叉树的最大深度

int maxDepth(struct TreeNode *root, int len) 
{
	if (root == NULL) {
		return len;
	}

	return fmax(maxDepth(root->left, len+1), maxDepth(root->right, len+1));
}

二叉树最大深度就是基本的递归思路的求解, 手法主要是递归下去之后len改如何赋值有点搞不清,这里给出了demo的用例,只要能递归就加+1,最后递归到叶子节点返回len。
手法:利用 “递”

111. 二叉树的最小深度

在这里插入图片描述
手法:利用 “归” ,这里不同于二叉树的深度求解,深度是利用递的性质,本题是先递下去,再归时做了处理。(具体见下面代码注释部分)

int minDepth(struct TreeNode *root) {
	if (root == NULL) {
		return 0;
	}

	if (root->left == NULL && root->right == NULL) {
		return 1;
	}

	int min_depth = INT_MAX; // 手法2:归上来时,要保证每次函数返回值与min_depth的fmin操作时
							//  函数返回值都能保留下来,所以min_depth要设置最大值.
	if (root->left != NULL) {
		min_depth = fmin(minDepth(root->left), min_depth);
	}
	if (root->right != NULL) {
		min_depth = fmin(minDepth(root->right), min_depth);
	}

	return min_depth + 1; // 手法1:利用归的特性,先递下去求解到叶子节点的数值,进入到循环终止条件
	                      // 然后每层,逐层归上来时+1.
}

049. 求从根节点到叶节点的路径数字之和

在这里插入图片描述

int dfs(struct TreeNode *root, int prevSum) {
    if (root == NULL) {
        return 0;
    }
    int sum = prevSum * 10 + root->val;
    if (root->left == NULL && root->right == NULL) {
        return sum; // 递归终止条件
    } else {
        return dfs(root->left, sum) + dfs(root->right, sum);
        // 先递归下去左叶子节点,计算出来,然后递归右叶子节点
    }
}

int sumNumbers(struct TreeNode *root) {
    return dfs(root, 0);
}

93. 复原 IP 地址

在这里插入图片描述

#define MAX 166     // 排列组合简单算的,实际没有这么多,很多情况不合法
void dfs(char *s, char **res, int *returnSize, int step, int index, int len, char *temp) 
{
	if (step == 4) {    // 结束条件:已取完四个数,将结果添加至结果数组
		res[*returnSize] = (char*)malloc(sizeof(char)*(len + 4));
		temp[index + step - 1] = '\0';      //将最后一个'.'去掉
		strcpy(res[*returnSize], temp);
		(*returnSize)++;
		return;
	}
	// 取一位数;
	// 剪枝:剩余长度不合法的情况
	// 剩余长度属于 [(3 - step), (3 - step) * 3]
	if ((len - index - 1 <= (3 - step) * 3) && (len - index - 1 >= (3 - step))) {
		temp[index + step]     = s[index];
		temp[index + step + 1] = '.';
		dfs(s, res, returnSize, step + 1, index + 1, len, temp);
	}
	// 取两位合法数(首位不为0); s[index] != '0'
	// 剪枝:剩余长度不合法的情况
	if ((len - index - 2 <= (3 - step) * 3) && ((len - index - 2 >= (3 - step)) && (s[index] != '0'))) {
		temp[index + step]     = s[index];
		temp[index + step + 1] = s[index + 1];
		temp[index + step + 2] = '.';
		dfs(s, res, returnSize, step + 1, index + 2, len, temp);
	}
	// 取三位合法数(首位不为0,且<=255);
	// 剪枝:剩余长度不合法的情况
	if ((len - index - 3 <= (3 - step) * 3) && (len - index - 3 >= (3 - step)) && ((s[index] != '0') && ((s[index] - '0') * 100 + (s[index + 1] - '0') * 10 + s[index + 2] - '0' <= 255))) {
		temp[index + step]     = s[index];
		temp[index + step + 1] = s[index + 1];
		temp[index + step + 2] = s[index + 2];
		temp[index + step + 3] = '.';
		dfs(s, res, returnSize, step + 1, index + 3, len, temp);
	}
}

char **restoreIpAddresses(char *s, int *returnSize) 
{
	*returnSize = 0;
	int len = strlen(s);
	if (len > 12 || len < 4) {
		return NULL;     //长度不合法直接return
	}
	char **res = (char **)malloc(sizeof(char *) * MAX);
	char *temp = (char *)malloc(sizeof(char) * (len + 5));
	dfs(s, res, returnSize, 0, 0, len, temp);
	return res;
}

130. 被围绕的区域

在这里插入图片描述
注意到题目解释中提到:任何边界上的 O 都不会被填充为 X。 我们可以想到,所有的不被包围的 O 都直接或间接与边界上的 O 相连。我们可以利用这个性质判断 O 是否在边界上,具体地说:

对于每一个边界上的 O,我们以它为起点,标记所有与它直接或间接相连的字母 O;
最后我们遍历这个矩阵,对于每一个字母:
如果该字母被标记过,则该字母为没有被字母 X 包围的字母 O,我们将其还原为字母 O;
如果该字母没有被标记过,则该字母为被字母 X 包围的字母 O,我们将其修改为字母 X

void dfs(char **board, int x, int y, int row, int col)
{
	if (x < 0 || x >= row || y < 0 || y >= col || board[x][y] != 'O') {  // 从边界的'O'出发遍历与之直接或间接相邻的'O'
		return;
	}

	board[x][y] = 'Z';  // 暂时将与边界上的'O'直接或间接相邻的'O'标记为'Z'
	dfs(board, x + 1, y, row, col);  // 向下遍历
	dfs(board, x - 1, y, row, col);  // 向上遍历
	dfs(board, x, y + 1, row, col);  // 向右遍历
	dfs(board, x, y - 1, row, col);  // 向左遍历
}

void solve(char **board, int boardSize, int *boardColSize)
{
	if (board == NULL || boardSize == 0 || (*boardColSize) == 0) {
		return;
	}
	int row = boardSize;
	int col = (*boardColSize);
	int i, j;

	for (i = 0; i < col; i++) {  
		// 寻找与第一行的'O'直接或间接相邻的'O'
		if (board[0][i] == 'O') {
			dfs(board, 0, i, row, col);
		}
		// 寻找与最后一行的'O'直接或间接相邻的'O'
		if (board[row - 1][i] == 'O') {
			dfs(board, row - 1, i, row, col);
		}
	}

	for (i = 0; i < row; i++) {  
		// 寻找与第一列的'O'直接或间接相邻的'O'
		if (board[i][0] == 'O') {
			dfs(board, i, 0, row, col);
		}
		// 寻找与最后一列的'O'直接或间接相邻的'O'
		if (board[i][col - 1] == 'O') {
			dfs(board, i, col - 1, row, col);
		}
	}

	// 结果
	for (i = 0; i < row; i++) {  // 将被'X'围绕的'O'转换为'X'
		for (j = 0; j < col; j++) {
			if (board[i][j] == 'O') {
				board[i][j] = 'X';
			}
			else if (board[i][j] == 'Z') { // 之前将不被'X'围绕的'O'转换为'Z',现在恢复为'O'
				board[i][j] = 'O';
			}
		}
	}
}

22. 括号生成

在这里插入图片描述

// 回溯法求解
#define MAX_SIZE 1430  // 卡特兰数: 1, 1, 2, 5, 14, 42, 132, 429, 1430
void generate(int left, int right, int n, char *str, int index, char **result, int *returnSize) 
{
	if (index == 2 * n) { // 当前长度已达2n
		result[(*returnSize)] = (char *)malloc((2 * n + 1) * sizeof(char));
		memset(result[(*returnSize)], 0, (2 * n + 1) * sizeof(char));
		strcpy(result[(*returnSize)++], str);
		return;
	}
	// 如果左括号数量不大于 n,可以放一个左括号
	if (left < n) {
		str[index] = '(';
		generate(left + 1, right, n, str, index + 1, result, returnSize);
	}
	// 如果右括号数量小于左括号的数量,可以放一个右括号
	if (right < left) {
		str[index] = ')';
		generate(left, right + 1, n, str, index + 1, result, returnSize);
	}
}
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
char **generateParenthesis(int n, int *returnSize)
{
	char *str = (char *)malloc((2 * n + 1) * sizeof(char));
	memset(str, 0 ,(2 * n + 1) * sizeof(char));
	char **result = (char **)malloc(sizeof(char *) * MAX_SIZE);
	*returnSize = 0;
	generate(0, 0, n, str, 0, result, returnSize);
	return result;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1591943.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

React Hooks 全解: 常用 Hooks 及使用场景详解

React Hooks 是 React 16.8 版本引入的一项重要特性,它极大地简化和优化了函数组件的开发过程。 React 中常用的 10 个 Hooks,包括 useState、useEffect、useContext、useReducer、useCallback、useMemo、useRef、useLayoutEffect、useImperativeHandle 和 useDebugValue。这些…

「JS 基础」迭代器和生成器 Iterator Generator 入门

前言 JavaScript的生成器(Generators)和迭代器(Iterators)是ES6引入的功能,使得开发者可以更方便地实现自定义的迭代逻辑。 迭代器 迭代器是一种接口,它为各种不同的数据结构(如数组或者映射)定义了一个标准的遍历方法。具体来说,一个迭代器对象必须实现一个 next…

背包问题详解

前言 本文主要讲解01背包问题&#xff0c;读者如果能完全搞懂01背包&#xff0c;那么稍作思考也能解决完全背包、多重背包问题。至于分组背包、有依赖的背包等问题博主也没有继续深入&#xff0c;但是应该都是在01背包的基础上拓展&#xff0c;读者若有兴趣可查阅其他文章。 …

电源监视继电器HRTH-J-2H2D AC220V 导轨安装 JOSEF约瑟

系列型号&#xff1a; HRTH-Y-2H2D-X-T跳位监视、合位监视、电源监控继电器&#xff1b; HRTH-Y-2Z-X-T跳位监视、合位监视、电源监控继电器&#xff1b; HRTH-Y-2H-X-T跳位监视、合位监视、电源监控继电器&#xff1b; HRTH-J-2H2D-X-T跳位监视、合位监视、电源监控继电器…

Django之rest_framework(一)

一、请求和响应对象介绍 REST framework引入了2个新的对象:Request和Response 1.1、Request rest_framework.request.Request 该对象扩展了常规的HttpRequest ,增加了对REST框架灵活的请求解析和请求认证的支持 官网:Requests - Django REST framework 主要属性: data 这…

react使用npm i @reduxjs/toolkit react-redux

npm i reduxjs/toolkit react-redux 创建一个 store文件夹&#xff0c;里面创建index.js文件和子模块文件夹 index,js文件写入以下代码 import {configureStore} from reduxjs/toolkit // 导入子模块 import counterReducer from ./modules/one import two from ./modules/tw…

计算机网络——CSMA/CD协议以及相关习题

目录 前言 引言 CSMA/CD协议 CSMA与CSMA/CD的区别 CSMA/CD流程 前言 本博客是博主用于复习计算机网络的博客&#xff0c;如果疏忽出现错误&#xff0c;还望各位指正。 引言 最早的以太网&#xff0c;许多计算机都连接在一根总线上工作——广播通信方式。 总线的特点想…

APP开发教学:开发同城O2O外卖跑腿系统源码详解

同城O2O外卖跑腿系统&#xff0c;满足了人们对于外卖送餐和生活服务的需求。今天&#xff0c;小编将为您讲解如何开发同城O2O外卖跑腿系统源码。 1.前期准备 首先&#xff0c;我们需要明确系统的功能需求和用户需求&#xff0c;包括外卖订购、配送员接单、支付功能等。其次&am…

排序1——C语言

排序 1. 复杂度2. 插入排序2.1 直接插入排序2.2 希尔排序 3. 选择排序3.1 直接选择排序3.2 堆排序 排序在生活中很常见&#xff0c;比如在网购时&#xff0c;按价格排序&#xff0c;按好评数排序&#xff0c;点餐时&#xff0c;按评分排序等等。而排序有快和慢&#xff0c;快的…

vue2响应式原理----发布订阅模式

很多人感觉vue2的响应式其实用到了观察者发布订阅。我们先来看一下简单的发布订阅的代码&#xff1a; // 调度中心 class Dep {static subscribes {}// 订阅所有需求static subscribe (key, demand) {// 对需求分类收集if (!Dep.subscribes[key]) Dep.subscribes[key] []Dep…

使用腾讯云服务器如何搭建网站?新手建站教程

使用腾讯云服务器搭建网站全流程&#xff0c;包括轻量应用服务器和云服务器CVM建站教程&#xff0c;轻量可以使用应用镜像一键建站&#xff0c;云服务器CVM可以通过安装宝塔面板的方式来搭建网站&#xff0c;腾讯云服务器网txyfwq.com整理使用腾讯云服务器建站教程&#xff0c;…

前端下载url文件(解决PDF, 图片自动在浏览器打开)

常规下载方法&#xff1a; /* 方法1 */ window.open(下载url地址, _blank)/* 方法2 */ const link document.createElement("a"); link.download true; link.href 下载url地址; link.click(); document.body.removeChild(link);pdf文件默认在浏览器中展示解决方案…

Linux:Zabbix + Grafana10.4.2(3)

1.部署zabbix 下面这篇文章写了详细的部署zabbix过程 &#xff0c;使用的centos9系统 Linux&#xff1a;部署搭建zabbix6&#xff08;1&#xff09;-CSDN博客https://blog.csdn.net/w14768855/article/details/137426966?spm1001.2014.3001.5501下面这篇文章使用的是centos7…

RTSP/Onvif安防视频EasyNVR平台 vs.多协议接入视频汇聚EasyCVR平台:设备分组的区别

EasyNVR安防视频云平台是旭帆科技TSINGSEE青犀旗下支持RTSP/Onvif协议接入的安防监控流媒体视频云平台。平台具备视频实时监控直播、云端录像、云存储、录像检索与回看、告警等视频能力&#xff0c;能对接入的视频流进行处理与多端分发&#xff0c;包括RTSP、RTMP、HTTP-FLV、W…

二叉树练习day.8

235.二叉搜索树的最近公共祖先 链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共…

30万的源码和300的源码有什么区别?

源码的质量很大程度上取决于其来源、开发者的技术水平和项目的具体需求。有些源码可能确实存在一些问题&#xff0c;比如代码结构混乱、注释不清晰、性能不佳等。 而价高优秀的源码都采用了高效的数据结构和算法&#xff0c;代码结构清晰&#xff0c;逻辑严谨&#xff0c;具有良…

ubuntu22下使用vscode调试redis7源码环境搭建

ubuntu22下使用vscode调试redis7源码环境搭建 ##vscode launch.json配置文件 {// 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。// 欲了解更多信息&#xff0c;请访问: https://go.microsoft.com/fwlink/?linkid830387"version": "0.2.0&…

【神经网络与深度学习】循环神经网络基础

tokenization tokenization&#xff1a;分词 每一个词语都是token 分词方法&#xff1a;转为单个词、转为多个词语 N-gram表示法 准备词语特征的方法 &#xff08;把连续的N个词作为特征&#xff09; 如 ”我爱你“——>[我&#xff0c;爱&#xff0c;你] 2-gram——[[我…

游戏服务器DDOS克星-抗D盾(游戏盾)

随着网络游戏市场的不断扩大和发展&#xff0c;游戏服务器遭受DDOS攻击的频率也在逐年增加。DDOS攻击的主要目的是使游戏服务器瘫痪&#xff0c;使得游戏无法正常进行&#xff0c;导致游戏运营商巨额损失。鉴于此&#xff0c;针对游戏服务器的防DDOS攻击技术德迅云安全自主研发…

Ubuntu 22上安装Anaconda3。下载、安装、验证详细教程

在Ubuntu 22上安装Anaconda3&#xff0c;你可以遵循以下步骤&#xff1a; 更新系统存储库&#xff1a; 打开终端并运行以下命令来更新系统存储库&#xff1a; sudo apt update安装curl包&#xff1a; 下载Anaconda安装脚本通常需要使用curl工具。如果系统中没有安装curl&#x…