【代码随想录】【算法训练营】【第28天】 [93]复原IP地址 [78]子集 [90]子集II

前言

思路及算法思维,指路 代码随想录。
题目来自 LeetCode。

day 28,工作的周二~

题目详情

[93] 复原 IP 地址

题目描述

93 复原 IP 地址
93 复原 IP 地址

解题思路

前提:分割问题
思路:回溯算法,确定每次递归回溯的分割位置。
重点:主要考虑清除分割位置的选取,即树状结构的划分。

代码实现

C语言
回溯

保存.的位置 + 字符串尾\0 + returnSize初始化为0

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */

bool isValidIp(char *s, int startIdx, int endIdx)
{
    if ((s == NULL) || (strlen(s) == 0) || (startIdx > endIdx))
    {
        return false;
    }
    // 起始为0情况
    if ((s[startIdx] == '0') && (startIdx != endIdx))
    {
        return false;
    }
    // 无效字符情况
    int num = 0;
    for (int idx = startIdx; idx <= endIdx; idx++)
    {
        if ((s[idx] < '0') || (s[idx] > '9'))
        {
            return false;
        }
        num = num * 10 + (s[idx] - '0');
    }
    // 超过255情况
    if (num > 255)
    {
        return false;
    }
    return true;
}

void backtracking(char *s, int strLen, int startIdx, int protNum, int *portLoc, char ***ans, int *returnSize)
{
    // 退出条件
    if (protNum == 3) {
        // 判断最后一段是否符合IP有效段
        if (((strLen - startIdx) < 4) && (isValidIp(s, startIdx, strLen - 1))) {
            // 保存输出结果
            *ans = (char **)realloc(*ans, sizeof(char *) * (*returnSize + 1));
            (*ans)[*returnSize] = (char *)malloc(sizeof(char) * 17);
            int count = 0;
            int tmp = 0;
            for (int i = 0; i < strLen; i++)
            {
                if ((count < 3) && (portLoc[count] == i))
                {
                    (*ans)[*returnSize][tmp++] = '.';
                    count++;
                }
                (*ans)[*returnSize][tmp++] = s[i];
            }
            (*ans)[*returnSize][tmp] = '\0';
            (*returnSize)++;
        }
        return ;
    }
    //递归
    for (int idx = startIdx; (idx < strLen) && (idx < startIdx + 4); idx++)
    {
        // 判断是否为IP有效段
        if (isValidIp(s, startIdx, idx)) {
            // 有效,保存该.位置
            portLoc[protNum] = idx + 1;
        }
        else {
            continue;
        }
        backtracking(s, strLen, idx + 1, protNum + 1, portLoc, ans, returnSize);
        // 回溯
    }
}

char** restoreIpAddresses(char* s, int* returnSize) {
    *returnSize = 0;
    char **ans = NULL;
    if ((s == NULL) || (strlen(s) == 0))
    {
        return NULL;
    }
    // 输出变量初始化
    int strLen = strlen(s);
    int portLoc[3] = {0};
    backtracking(s, strLen, 0, 0, portLoc, &ans, returnSize);
    return ans;
}

[78] 子集

题目描述

78 子集
78 子集

解题思路

前提:组合子集问题, 无重复元素
思路:回溯,输出树上所有节点的路径
重点:先输出路径,再判断退出条件,以免遗漏子集。

代码实现

C语言
回溯

树的所有结点路径 + 全局变量初始化

/**
 * Return an array of arrays of size *returnSize.
 * The sizes of the arrays are returned as *returnColumnSizes array.
 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 */

int **ans;
int ansSize = 0;
int *colSizes;
int *tmpNums;
int tmpNumsSize = 0;

void collect()
{
    ans[ansSize] = (int *)malloc(sizeof(int) * tmpNumsSize);
    for (int i = 0; i < tmpNumsSize; i++) {
        ans[ansSize][i] = tmpNums[i];
    }
    colSizes[ansSize] = tmpNumsSize;
    ansSize++;
    return ;
}

void backtracking(int *nums, int numsSize, int startIdx)
{
    // 收集该结点路径
    collect();
    // 终止条件
    if (startIdx >= numsSize) {
        return ;
    }
    // 递归
    for (int j = startIdx; j < numsSize; j++) {
        // 保存该结点
        tmpNums[tmpNumsSize++] = nums[j];
        backtracking(nums, numsSize, j + 1);
        // 回溯
        tmpNumsSize--;
    }
    return ;
}

int** subsets(int* nums, int numsSize, int* returnSize, int** returnColumnSizes) {
    // 全局变量初始化
    ans = (int **)malloc(sizeof(int *) * 10000);
    colSizes = (int *)malloc(sizeof(int) * 10000);
    tmpNums = (int *)malloc(sizeof(int) * numsSize);
    ansSize = 0;
    tmpNumsSize = 0;
    backtracking(nums, numsSize, 0);
    *returnSize = ansSize;
    *returnColumnSizes = colSizes;
    return ans;
}

[90] 子集II

题目描述

90 子集II
90 子集II

解题思路

前提:组合子集问题,有重复元素
思路:回溯,排序后同一树层去重, 输出树上所有节点的路径。
重点:同一树层去重; 先输出路径,再判断退出条件,以免遗漏子集。

代码实现

C语言
回溯

回溯 + 同一树层元素去重 + 输出全结点路径

/**
 * Return an array of arrays of size *returnSize.
 * The sizes of the arrays are returned as *returnColumnSizes array.
 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 */

int **ans;
int ansSize;
int *length;
int *path;
int pathSize;
bool *used;

int cmp(void *p1, void *p2)
{
    return *(int *)p1 > *(int *)p2;
}

void collect()
{
    ans[ansSize] = (int *)malloc(sizeof(int) * pathSize);
    // 输出该子集
    for (int j = 0; j < pathSize; j++) {
        ans[ansSize][j] = path[j];
    }
    length[ansSize] = pathSize;
    ansSize++;
    return ;
}

void backtracking(int *nums, int numsSize, int startIndex)
{
    // 输出该子集
    collect();
    // 退出条件
    if (startIndex >= numsSize) {
        return;
    }
    // 递归
    for (int i = startIndex; i < numsSize; i++) {
        // 去重
        if ((i > 0) && (nums[i] == nums[i - 1]) && (used[i - 1] == false)) {
            continue;
        }
        // 保存该元素
        path[pathSize++] = nums[i];
        used[i] = true;
        backtracking(nums, numsSize, i + 1);
        // 回溯
        pathSize--;
        used[i] = false;
    }
    return ;
}

int** subsetsWithDup(int* nums, int numsSize, int* returnSize, int** returnColumnSizes) {
    // 全局变量初始化
    ans = (int **)malloc(sizeof(int *) * 10000);
    ansSize = 0;
    length = (int *)malloc(sizeof(int) * 10000);
    path = (int *)malloc(sizeof(int) * numsSize);
    pathSize = 0;
    used = (bool *)malloc(sizeof(bool) * numsSize);
    for (int k = 0; k < numsSize; k++) {
        used[k] = false;
    }

    // 排序
    qsort(nums, numsSize, sizeof(int), cmp);

    // 回溯
    backtracking(nums, numsSize, 0);

    // 赋值输出结果
    *returnSize = ansSize;
    *returnColumnSizes = length;

    return ans;
}

今日收获

  1. 组合分割问题:分割位置的递归回溯,叶子结点的路径输出
  2. 组合子集问题:元素是否重复,同一树层去重,所有结点的路径输出。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

navi_cat查看数据库的连接密码

Navi_Cat 建立连接&#xff0c;来访问数据库。可惜&#xff0c;忘记了数据库密码&#xff0c;没事&#xff0c;这么搞。 首先先导出链接&#xff0c;再从链接里取出被加密的密码&#xff0c;然后找个可在线运行PHP的网站&#xff08;代码在线运行 - 在线工具&#xff09;&…

Vue项目安装axios报错npm error code ERESOLVE npm error ERESOLVE could not resolve解决方法

在Vue项目中安装axios时报错 解决方法&#xff1a;在npm命令后面加--legacy-peer-deps 例如&#xff1a;npm install axios --save --legacy-peer-deps 因为别的需求我把node版本重装到了最新版&#xff08;不知道是不是这个原因&#xff09;&#xff0c;后来在项目中安装axi…

2024 年该如何利用 MidJourney 创作AI艺术(详细教程)

什么是 Midjourney Midjourney 是根据文本提示创建图像的生成式人工智能的优秀范例。与 Dall-E 和 Stable Diffusion 一样&#xff0c;它已成为最受欢迎的人工智能艺术创作工具之一。与竞争对手不同的是&#xff0c;Midjourney 是自筹资金和封闭源代码的&#xff0c;因此对它的…

BPMN开始事件-Activiti7从入门到专家(7)

开始事件类型 bpmn开始事件表示流程的开始&#xff0c;定义流程如何启动&#xff0c;在某种情况下启动&#xff0c;比如接收事件启动&#xff0c;指定事件启动等&#xff0c;开始事件有5种类型&#xff1a; 空开始事件定时器开始事件信号开始事件消息开始事件错误开始事件 继…

如何以非交互方式将参数传递给交互式脚本

文章目录 问题回答1. 使用 Here Document2. 使用 echo 管道传递3. 使用文件描述符4. 使用 expect 工具 参考 问题 我有一个 Bash 脚本&#xff0c;它使用 read 命令以交互方式读取命令参数&#xff0c;例如 yes/no 选项。是否有一种方法可以在非交互式脚本中调用这个脚本&…

探索未来制造,BFT Robotics引领潮流

“买机器人&#xff0c;上BFT” 在这个快速变化的时代&#xff0c;创新和效率是企业发展的关键。BFT Robotics&#xff0c;作为您值得信赖的合作伙伴&#xff0c;专注于为您提供一站式的机器人采购和自动化解决方案。 产品系列&#xff1a; 协作机器人&#xff1a;安全、灵活、…

水务设备数字化管理

在数字化浪潮席卷全球的今天&#xff0c;水务行业也迎来了数字化转型的重要契机。传统水务管理模式中&#xff0c;设备监控、数据收集、运行维护等环节往往存在效率低下、成本高昂、安全隐患多等问题。而HiWoo Cloud平台的出现&#xff0c;以其强大的设备接入能力、高效的数据处…

使用达梦数据库集成Python,达成快速连接

本章主要介绍在 Python 开发的时候&#xff0c;如何使用 Python 快速连接达梦数据库。 dmPython 简介 dmPython 是 DM 提供的依据 Python DB API version 2.0 中 API 使用规定而开发的数据库访问接口。 使用 Python 连接达梦数据库时需要安装 dmPython。安装完 DM 数据库软件…

Python的df.cumsum()函数

Python Pandas dataframe.cumsum() Python是一种进行数据分析的伟大语言&#xff0c;主要是因为以数据为中心的Python包的奇妙生态系统。Pandas就是这些包中的一个&#xff0c;它使导入和分析数据变得更加容易。 Pandas dataframe.cumsum()用于查找任何axis上的累积和值。每个…

基于51单片机的多功能计算器全套设计

通过本次课题设计,应用《单片机应用基础》、《数据结构》等所学相关知识及查阅资料,完成实用计算器的设计,以达到理论与实践更好的结合、进一步提高综合运用所学知识和设计的能力的目的。 通过本次设计的训练,可以使我在基本思路和基本方法上对基于MCS-51单片机的嵌入式系…

docker命令 docker ps -l (latest)命令在 Docker 中用于列出最近一次创建的容器

文章目录 12345 1 docker ps -l 命令在 Docker 中用于列出最近一次创建的容器。具体来说&#xff1a; docker ps&#xff1a;这个命令用于列出当前正在运行的容器。-l 或 --latest&#xff1a;这个选项告诉 docker ps 命令只显示最近一次创建的容器&#xff0c;不论该容器当前…

【YOLOv10】使用 TensorRT C++ API 调用GPU加速部署 YOLOv10 实现 500FPS 推理速度——快到飞起!

NVIDIA TensorRT ™ 是一款用于高性能深度学习推理的 SDK&#xff0c;包含深度学习推理优化器和运行时&#xff0c;可为推理应用程序提供低延迟和高吞吐量。YOLOv10是清华大学研究人员近期提出的一种实时目标检测方法&#xff0c;通过消除NMS、优化模型架构和引入创新模块等策…

什么是 target 和 currentTarget ?

1、event.target 发生事件的元素或触发事件的元素 <div onclick"clickFunc(event)" style"text-align: center;margin:15px; border:1px solid red;border-radius:3px;"><div style"margin: 25px; border:1px solid royalblue;border-radi…

Java Web学习笔记14——BOM对象

BOM&#xff1a; 概念&#xff1a;浏览器对象模型&#xff08;Browser Object Model&#xff09;&#xff0c;允许JavaScript与浏览器对话&#xff0c;JavaScript将浏览器的各个组成部分封装为对象。 组成&#xff1a; Window&#xff1a;浏览器窗口对象 介绍&#xff1a;浏览…

解决CentOS 7无法识别ntfs的问题

解决CentOS 7无法识别ntfs的问题 方式一&#xff1a; Centos默认不支持ntfs文件格式&#xff0c;直接在Centos7上插U盘或移动硬盘无法识别&#xff0c;安装 ntfs-3g即可&#xff1a; # yum install epel-release -y # yum install ntfs-3g -y[rootbogon ~]# rpm -qa | grep nt…

世净超声波清洗机怎么样?美的、希亦、世净超声波清洗机谁更值得买?

在日常生活和专业领域中&#xff0c;清洁工作往往是既重要又烦琐的任务。特别是对于那些难以手工得尤为重要。关键是现在超声波清洗机已经不是从前的超声波清洗机了&#xff0c;不是只在工业领域上清洗一些重大零件了&#xff0c;已经逐渐开始能够清洗日常物品&#xff0c;像眼…

RFID测温技术在电力行业的革命性应用

随着科技的快速发展, RFID技术在各个领域的应用越来越广泛&#xff0c;而其中的一个重要领域就是电力行业。这一无线测温技术以其非接触、实时、高精度的特点&#xff0c;为电力设备的温度监测带来了革命性的改变。电力行业作为国家基础设施建设的重要支柱&#xff0c;设备的安…

静态IP代理服务对比:哪些提供商值得信赖?静态ip代理哪家好用?

当涉及选择静态IP代理时&#xff0c;许多人可能会感到困惑&#xff0c;因为市场上存在着各种各样的选项。本文旨在为您提供一些关键指导&#xff0c;帮助您确定哪种静态IP代理是最适合您需求的。在这个过程中&#xff0c;我们将介绍一个备受推崇的解决方案——太阳HTTP。 1.高速…

论文阅读 Explainable Image Similarity Integrating Siamese Networks and Grad-CAM

给出论文&#xff08;Explainable Image Similarity Integrating Siamese Networks and Grad-CAM&#xff09;的内容解读、代码运行说明 论文链接&#xff1a;J. Imaging | Free Full-Text | Explainable Image Similarity: Integrating Siamese Networks and Grad-CAM (mdpi.c…

大数据开发统计数据的详细口径是什么

在进行开发数据需求之前&#xff0c;我们先要明确数据统计的详细口径是什么。 需求1&#xff1a;&#xff08;不明确的示例&#xff09; 统计商品的销售数量。 存在的问题&#xff1a; 这个需求表述过于简单&#xff0c;未明确指出统计商品销售数量的时间范围、商品类型等关键…