LeetCode·每日一题·1096. 花括号展开 II·DFS+HASH

news2025/7/21 4:54:24

作者:Guang

链接:https://leetcode.cn/problems/brace-expansion-ii/solutions/997719/xss1096-hua-gua-hao-zhan-kai-iiby-zgh-by-vumf/

来源:力扣(LeetCode)

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

题目

示例

思路

从题目来看,有几个要注意:

  • 题目提出“返回它所表示的所有字符串组成的有序列表”,因此结果要按字母排序后返回。

  • 示例中提到:不应出现重复的组合结果。表明需要去重,则最好使用hash。

代码中使用了递归DFS,每次处理首先遇到的最内层的括号(即括号内不含子括号),split按逗号拆分,按每个拆分元素与剩余部分组合成新字符串DFS。 直到一条处理路径中新字符串不含子括号为止,用逗号切分,添加到hash表。 全部路径处理完后,排序hash表。返回结果。

举个例子: 输入:{a,b},x{c,{d,e}y}

  • 从左到右处理第一个括号内不含子括号的内容 括号内容:a,b 按逗号切分为a和b 分别取a和b与其余部分组合。以a为例,a,x{c,{d,e}y}作为新字符串。继续处理。

  • 输入a,x{c,{d,e}y}从左到右取括号内不含子括号的部分 括号内容:d,e 按逗号切分为d和e 继续与其余部分组合,以d为例:a,x{c,dy}

  • 输入: a,x{c,dy} 括号内容:c,dy 按逗号切分:c和dy 与其余部分组合:以c为例为a,xc 以dy为例为a,xdy

  • 输入:a,xc和a,xdy 无括号,则拆分后插入哈希表。此轮插入了a,xc,xdy

  • 回到上面第2步的结果,取e继续:a,x{c,ey} 继续拆分下来,第一部分a,xc第二部分a,xey.插入哈希表a,xc,xey

  • 回到上面第一步的结果,取b的组合结果处理b,x{c,{d,e}y} 拆分一次,分为b,x{c,dy}和b,x{c,ey},继续拆分,插入哈希表:b,xc,xdy,b,xc,xey

  • 哈希表中保存的a,xc,xdy,xey,b 使用HASH_SORT排序,结果a,b,xc,xdy,xey。遍历哈希表,结果输出到二维数组。

代码

#define SIZE 62

typedef struct {//哈希结构
    char str[62];
    UT_hash_handle hh;
} HashNode;

HashNode *g_hashMap = NULL;

void hashAdd(HashNode **map, char *name)//加入哈希表
{
    HashNode *node = NULL;
    HASH_FIND_STR(*map, name, node);//查询是否在哈希表中存在
    if (node == NULL) {
        node = (HashNode *)malloc(sizeof(HashNode));//不存在加入哈希表
        strcpy(node->str, name);
        HASH_ADD_STR(*map, str, node);
        return;
    }
    strcpy(node->str, name);
}

HashNode *hashFind(HashNode *map, char *name)//查询是否在哈希表中
{
    HashNode *node = NULL;
    HASH_FIND_STR(map, name, node);
    return node;
}

static inline int IsExistLeftBacket(char* expression)//查找{
{
    while (*expression) {
        if (*expression == '{') {
            return true;
        }
        ++expression;
    }
    return false;
}

static inline int Split(char* str, char* splitStr, char (*ret)[SIZE])//字符串切割
{
    char *q = strtok(str, splitStr);
    int count = 0;
    while(q) {
        strcpy(ret[count], q);
        ++count;
        q = strtok(NULL, ","); 
    }
    return count;//返回切割点
}

void Dfs(char* expression)
{
    if (expression == NULL) {
        return ;
    }
    if (!IsExistLeftBacket(expression)) {//如果没有 { 号,说明不需要再递归
        char split[SIZE][SIZE] = {0};//结束入口
        int strCnt = Split(expression, ",", split);
        for (int i = 0; i < strCnt; i++) {
            hashAdd(&g_hashMap, split[i]);//有效数据加入哈希表
        }
        return;
    }

    char leftCash[SIZE] = {0};
    char rightCash[SIZE] = {0};
    char middleCash[SIZE] = {0};//临时存储区

    int left, right, i;
    int len = strlen(expression);

    for (i = 0; i < len && expression[i] != '}'; ++i) {//寻找第一个{ ,为后序递归准备
        if (expression[i] == '{') {
            left = i;
        }
    }
    right = i;
    strncpy(leftCash, expression, left);
    leftCash[left] = '\0';
    strcpy(rightCash, expression + right + 1);
    strncpy(middleCash, expression + left + 1, right - left - 1);
    middleCash[right - left - 1] = '\0';//临时区处理

    char split[SIZE][SIZE];
    int splitCount = Split(middleCash, ",", split);
    for (i = 0; i < splitCount; ++i) {//遍历并递归到下一层
        char cache[SIZE];
        memset(cache, 0, sizeof(cache));
        strcpy(cache, leftCash);
        strcat(cache, split[i]);
        strcat(cache, rightCash);
        Dfs(cache);
    }

}

int Cmp(const HashNode *a, const HashNode *b)//字典序排序
{
    return strcmp(a->str, b->str);
}

char ** braceExpansionII(char * expression, int* returnSize)
{
    if (expression == NULL) {
        *returnSize = 0;
        return NULL;
    }
    g_hashMap = NULL;

    Dfs(expression);//头递归

    *returnSize = HASH_COUNT(g_hashMap);//获取哈希表中数据个数
    HASH_SORT(g_hashMap, Cmp);//排序

    char** ret = (char**)malloc(sizeof(char*) * (*returnSize));
    HashNode *tmp = NULL;
    int index = 0;
    for (tmp = g_hashMap; tmp != NULL; tmp = tmp->hh.next) {//枚举哈希表所有数据并保存
        ret[index] = (char*)malloc(sizeof(char) * SIZE);
        strcpy(ret[index], tmp->str);
        index++;
    }
    
    return ret;
}

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

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

相关文章

项目管理软件中什么是依赖管理,具体有什么作用?

项目管理软件中的依赖管理有什么作用&#xff1f;没有项目任务是孤立存在的。除了第一个项目任务之外&#xff0c;每个任务或活动都以某种方式依赖于其他活动。无论是等待另一个任务的输出还是要释放资源&#xff0c;您都需要在任何项目中管理许多依赖项。依赖管理是管理所有这…

VUE3入门第二篇:安装pnpm

VUE介绍 VUE是一个使用JavaScript编写的框架&#xff0c;所以在开发的时候&#xff0c;我们可以使用Js的包管理工具进行安装/管理Js框架 pnpm介绍 一般情况下&#xff0c;对于我们都会使用npm进行管理&#xff0c;但是使用 npm 时&#xff0c;依赖每次被不同的项目使用&…

C++面向对象编程之一:封装

C面向对象编程三大特性为&#xff1a;封装&#xff0c;继承&#xff0c;多态。C认为万事万物皆为对象&#xff0c;对象有属性和行为。比如&#xff1a;游戏里的地图场景可以看作是长方形对象&#xff0c;属性场景id&#xff0c;有长&#xff0c;有宽&#xff0c;可能有NPC&…

【LeetCode】旋转图像 [M](数组)

48. 旋转图像 - 力扣&#xff08;LeetCode&#xff09; 一、题目 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例 1&…

服务搭建篇(七) Elasticsearch单节点部署以及多节点集群部署

1.Elasticsearch Elasticsearch(简称ES) 是一个分布式 , RESTful风格的搜索和数据分析引擎 , 使用java开发并且是当前最流行的开源的企业级搜索引擎&#xff0c;能够达到近实时搜索&#xff0c;稳定&#xff0c;可靠&#xff0c;快速&#xff0c;安装使用方便。 客户端支持Ja…

教你如何搭建店铺—客户管理系统,demo可分享

1、简介1.1、案例简介本文将介绍&#xff0c;如何搭建店铺-客户管理。1.2、应用场景以店铺客户管理为核心&#xff0c;维度数据分析&#xff0c;智能指导门店经营&#xff0c;店铺经营更高效备。2、设置方法2.1、表单搭建1&#xff09;新建表单【客户信息】&#xff0c;字段设置…

Redis6学习笔记

文章目录一、简介1.1 Redis键(key)1.2 字符串(String)1.2.1 简介1.2.2 命令1.2.3 数据结构1.3 列表(List)1.3.1 简介1.3.2 命令1.3.3 数据结构1.4 集合(Set)1.4.1 简介1.4.2 命令1.4.3 数据结构1.5 哈希(Hash)1.5.1 简介1.5.2 命令1.5.3 数据结构1.6 有序集合(Zset)1.6.1 简介1…

通过Debug探索SpringMVC执行过程

文章目录对SpringMVC的理解SpringMVC工作原理SpringMVC工作流程对SpringMVC的理解 MVC&#xff1a;MVC是一种设计模式 MVC的原理图&#xff1a; M-Model 模型&#xff08;完成业务逻辑&#xff1a;有javaBean构成&#xff0c;servicedaoentity&#xff09;V-View 视图&#…

苹果或3月8日开新品发布会是真的吗?

苹果或3月8日开新品发布会是真的吗&#xff1f;都发布什么产品&#xff1f;iPhone14即将推出至少1种新颜色 #iPhone #苹果 苹果怎么又出小屏手机&#xff1f; S1 多好用&#xff0c;单手就能操作。 诶&#xff0c;苹果这么小字都看不清楚&#xff0c;可是这是有 H5 又怎么样…

张云雷再唱《探清水河》,柠檬们热情似火,预约通道都要崩溃了

起德云社的相声演员&#xff0c;很多都是唱歌的高手&#xff0c;比如说“德云一哥”岳云鹏&#xff0c;当然更少不了小辫张云雷。张云雷的成功之处在于&#xff0c;他总能够化腐朽为神奇&#xff0c;让不可能成为可能&#xff0c;这是其他相声演员所不能比拟的。 就拿他的成名曲…

《安富莱嵌入式周报》第305期:超级震撼数码管瀑布,使用OpenAI生成单片机游戏代码的可玩性,120通道逻辑分析仪,复古电子设计,各种运动轨迹函数源码实现

往期周报汇总地址&#xff1a;嵌入式周报 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz! 说明&#xff1a; 谢谢大家的关注&#xff0c;继续为大家盘点上周精彩内容。 视频版&#xff1a; https://www.bi…

Redis锁与幂等性不得不说的故事

前言&#xff1a; 相信很多小伙伴对缓存锁都不陌生&#xff0c;但是简单的缓存锁想要用好还是需要一些功力。本文总结了笔者多年使用缓存所的一些心得&#xff0c;欢迎交流探讨~ 幂等模型&#xff1a; 幂等场景一般由查重写入两步操作组成&#xff0c;两步操作组成一个最小完…

SpringSecurity支持WebAuthn认证

WebAuthn是无密码身份验证技术&#xff0c;解决了密码泄露的风险&#xff0c;主流的浏览器都支持。有很多开源的类库实现了WebAuthn规范&#xff0c;Java下流行的类库有&#xff1a;webauthn4jjava-webauthn-serververtx-authSpring Security官方暂时未支持WebAuthn&#xff0c…

怎样编写java程序

搭建好了Java开发环境之后&#xff0c;下面就来学习一下如何开发Java程序。为了让初学者更好地完成第一个Java程序&#xff0c;接下来通过几个步骤进行逐一讲解。 1&#xff0e;编写Java源文件 在D盘根目录下新建一个test文件夹&#xff0c;并在该文件夹中新建文本文档&#…

运维自动化之Ansible

一&#xff1a;Ansible的概述ansible的简介Ansible是一款为类Unix系统开发的自由开源的配置和自动化工具。它用Python写成&#xff0c;类似于saltstack和Puppet&#xff0c;但是有一个不同和优点是我们不需要在节点中安装任何客户端。它使用SSH来和节点进行通信。Ansible基于 P…

【C++】Clang-Format:代码自动格式化(看这一篇就够了)

文章目录Clang-format格式化C代码1.引言&安装1.1引言1.2 安装2. 配置字解释2.1 language 编程语言2.2 BaseOnStyle 基础风格2.3 AccessModifierOffset 访问性修饰符偏移2.4 AlignAfterOpenBracket 开括号后的对齐2.5 AlignArrayOfStructures 对齐结构体数组2.6 AlignConsec…

中电金信Gien享汇・大数据专题|金融行业数据架构及模型演进

本期嘉宾 陈子刚 中电金信商业分析事业部华南区总经理 毕业于复旦大学&#xff0c;硕士研究生&#xff1b;拥有16年以上金融行业商业智能领域从业经验&#xff1b;曾就职于中国工商银行、Teradata、东亚银行&#xff0c;服务于平安银行、广发银行、招商银行、广东农信、招商…

IT项目经理的自我修养手册(续)

上一节从工作职责和如何提升IT项目经理的个人能力讲述了作为一个职业项目经理的自我修养&#xff0c; 入口地址&#xff1a; IT项目经理的自我修养手册 本节将会从计划、组织、领导、控制这四个方面&#xff0c;系统的介绍作为职业项目经理的工作职责和工作范围。 一、计划 …

Springboot怎么实现WebSocket通信(一)

文章示例环境配置信息jdk版本:1.8开发工具&#xff1a;Intellij iDEA 2020.1springboot:2.3.9.RELEASE什么是WebSocket?WebSocket&#xff0c;是HTML5下一种新的协议&#xff0c;支持web浏览器和服务器端之间双向全双工通信 &#xff0c;基于TCP协议实现。WebSocket主要特性1、…

console使用方法介绍

console是在写前端Javascript时经常会使用到&#xff0c;我平时使用最多的是console.log&#xff0c;相比大多数人也是如此吧&#xff01; 下面一起来看一下强大的console吧&#xff01; 01函数&#xff08;属性&#xff09; 包含如下函数 / 属性&#xff1a;memory、assert、c…