力扣(leetcode)每日一题 2306 公司命名

2306. 公司命名

给你一个字符串数组 ideas 表示在公司命名过程中使用的名字列表。公司命名流程如下:

  1. 从 ideas 中选择 2 个 不同 名字,称为 ideaA 和 ideaB 。
  2. 交换 ideaA 和 ideaB 的首字母。
  3. 如果得到的两个新名字  不在 ideas 中,那么 ideaA ideaB串联 ideaA 和 ideaB ,中间用一个空格分隔)是一个有效的公司名字。
  4. 否则,不是一个有效的名字。

返回 不同 且有效的公司名字的数目。

示例 1:

**输入:**ideas = [“coffee”,“donuts”,“time”,“toffee”]
**输出:**6
**解释:**下面列出一些有效的选择方案:

  • (“coffee”, “donuts”):对应的公司名字是 “doffee conuts” 。
  • (“donuts”, “coffee”):对应的公司名字是 “conuts doffee” 。
  • (“donuts”, “time”):对应的公司名字是 “tonuts dime” 。
  • (“donuts”, “toffee”):对应的公司名字是 “tonuts doffee” 。
  • (“time”, “donuts”):对应的公司名字是 “dime tonuts” 。
  • (“toffee”, “donuts”):对应的公司名字是 “doffee tonuts” 。
    因此,总共有 6 个不同的公司名字。

下面列出一些无效的选择方案:

  • (“coffee”, “time”):在原数组中存在交换后形成的名字 “toffee” 。
  • (“time”, “toffee”):在原数组中存在交换后形成的两个名字。
  • (“coffee”, “toffee”):在原数组中存在交换后形成的两个名字。

示例 2:

**输入:**ideas = [“lack”,“back”]
**输出:**0
**解释:**不存在有效的选择方案。因此,返回 0 。

题解

因为是hard题目,所以想着如何优化到一次遍历,显然是行不通的。然后就寄了。

实践上不能通过的写法

public static long distinctNames(String[] ideas) {  
    HashSet<String> set = new HashSet<String>();  
    for (int i = 0; i < ideas.length; i++) {  
        set.add(ideas[i]);  
    }  
    long sum = 0;  
    for (int i = 0; i < ideas.length; i++) {  
        for (int j = i + 1; j < ideas.length; j++) {  
            String idea1 = ideas[i];  
            String idea2 = ideas[j];  
            String newIdea1 = idea1.substring(0, 1) + idea2.substring(1);  
            String newIdea2 = idea2.substring(0, 1) + idea1.substring(1);  
            if (!set.contains(newIdea1) && !set.contains(newIdea2)) {  
                sum++;  
            }  
        }  
    }  
    return sum * 2;  
} 

把首字母抽取出来,减少循环的数量

public static long distinctNames(String[] ideas) {  
    HashMap<Character, Set<String>> map = new HashMap<>();  
    for (int i = 0; i < ideas.length; i++) {  
        Set<String> set = map.getOrDefault(ideas[i].charAt(0), new HashSet<>());  
        set.add(ideas[i].substring(1));  
        map.put(ideas[i].charAt(0), set);  
    }  
    long sum = 0;  
    for (Map.Entry<Character, Set<String>> entry : map.entrySet()) {  
        Character key = entry.getKey();  
        Set<String> value = entry.getValue();  
        for (Map.Entry<Character, Set<String>> entry2 : map.entrySet()) {  
            Character key2 = entry2.getKey();  
            Set<String> value2 = entry2.getValue();  
            if (key == key2) {  
                continue;  
            }  
            HashSet<String> strings = new HashSet<>(value);  
            // 3   + 5   -   6  那么就是 2            strings.addAll(value2);  
            int count = value.size() + value2.size() - strings.size();  
            sum += (long) (value2.size() - count) * (long) (value.size() - count);  
        }  
    }  
    return sum;  
}

这里可以想到用数组代替hash,但是没有什么时间上的提升


public static long distinctNames(String[] ideas) {  
    Set<String>[] sets = new Set[26];  
    HashMap<Character, Set<String>> map = new HashMap<>();  
    for (int i = 0; i < ideas.length; i++) {  
        char c = ideas[i].charAt(0);  
        if (sets[c - 'a'] == null) {  
            HashSet<String> set = new HashSet<>();  
            set.add(ideas[i].substring(1));  
            sets[c - 'a'] = set;  
        } else {  
            sets[c - 'a'].add(ideas[i].substring(1));  
        }  
    }  
    long sum = 0;  
    for (int i = 0; i < 26; i++) {  
        if (sets[i] != null) {  
            for (int j = i; j < 26; j++) {  
                if (sets[j] != null) {  
                    Set<String> set1 = sets[i];  
                    Set<String> set2 = sets[j];  
                    Set<String> set3 = new HashSet<>(set1);  
                    set3.addAll(set2);  
                    int count = set1.size() + set2.size() - set3.size();  
                    sum += (long) (set1.size() - count) * (long) (set2.size() - count);  
                }  
            }  
        }  
    }  
    return sum * 2;  
}

看了大佬的提交,将取交替的计算,进行缓存。时间上大幅提升

public static long distinctNames(String[] ideas) {  
    int[] size = new int[26]; // 集合大小  
    int[][] dp = new int[26][26]; // 交集大小  
    Map<String, Integer> groups = new HashMap<>(); // 后缀 -> 首字母  
    for (String s : ideas) {  
        int key1 = s.charAt(0) - 'a';  
        size[key1]++; // 增加集合大小  
        String value1 = s.substring(1);  
  
        // key1 对应的value     value还有对应的key2,key3  这里的交际都要加上1  
        // 而这里的key只有可能是0到25,因此可以用位来存储。  比如 ....1110001 这里字母a,e,f,g 有交际  
        int mask = groups.getOrDefault(value1, 0);  
        groups.put(value1, mask | 1 << key1); // 把 key1 加到 mask 中  
        for (int key2 = 0; key2 < 26; key2++) { // key2 是和 s 有着相同后缀的字符串的首字母  
            if ((mask >> key2 & 1) > 0) { // key2 在 mask 中  
                if (key1 < key2) {  
                    dp[key1][key2]++; // 增加交集大小  
                } else {  
                    dp[key2][key1]++; // 增加交集大小  
                }  
            }  
        }  
    }  
    long ans = 0;  
    for (int i = 0; i < 26; i++) { // 枚举所有组对  
        for (int j = i + 1; j < 26; j++) {  
            int m = dp[i][j];  
            ans += (long) (size[i] - m) * (size[j] - m);  
        }  
    }  
    return ans * 2; // 乘 2 放到最后  
}

总结

还是和数学技巧有关系

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

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

相关文章

FortiGate 无线组网

无线管理与配置 FortiAP 连接 internal 接口之后自动获得 ip 地址&#xff1a;192.168.1.xxx/24在 FortiGate 中创建 SSIDFortiGate 自动发现 FortiAP&#xff0c;将 FortiAP 添加到 FortiGate将 SSID 和 FortiAP 关联创建防火墙策略 下面我们就来一起看看在 FortiGate 中该如…

MT6765/MT6762(R/D/M)/MT6761(MT8766)安卓核心板参数比较_MTK联发科4G智能模块

联发科Helio P35 MT6765安卓核心板 MediaTek Helio P35 MT6765是智能手机的主流ARM SoC&#xff0c;于2018年末推出。它在两个集群中集成了8个ARM Cortex-A53内核&#xff08;big.LITTLE&#xff09;。四个性能内核的频率高达2.3GHz。集成显卡为PowerVR GE8320&#xff0c;频率…

前端——js基础

一、JavaScript &#xff08;简称js&#xff09;——js可以给网页实现一个动态效果 1.JavaScript 组成 - 核心语法 ECMScipt 简称(es): 规范js的基本语法 1.es是js的语法规范 管理者 2.js是es的实现 操作者 - DOM > 文档对象 提供js操作 (例如…

Golang | Leetcode Golang题解之第423题从英文中重建数字

题目&#xff1a; 题解&#xff1a; func originalDigits(s string) string {c : map[rune]int{}for _, ch : range s {c[ch]}cnt : [10]int{}cnt[0] c[z]cnt[2] c[w]cnt[4] c[u]cnt[6] c[x]cnt[8] c[g]cnt[3] c[h] - cnt[8]cnt[5] c[f] - cnt[4]cnt[7] c[s] - cnt[6]…

jq实现:点击图片时弹出详情弹窗,判断拖动图片时不弹出

1.需求分析: 要实现点击图片时弹出详情弹窗,但在拖动时不弹出,可以使用 jQuery 来判断用户的操作。可以通过设置一个标志变量来判断用户是否在拖动图片。 并且在鼠标拖动某个图片时将其层级设置为最上面,可以使用 jQuery 结合 CSS 的 z-index 属性 说明 : 标志变量:使用…

传输层TCP协议

一、TCP协议格式 我们看到报头固定有20字节&#xff0c;最后选项大小不固定。 4位首部长度&#xff08;二进制0000 ~ 1111&#xff0c;十进制范围[0, 15]&#xff09;单位是4字节&#xff08;存放字节大小范围[0, 60]&#xff09;包括了20字节固定长度 选项长度。若选项大小为…

PWA(Progressive web APPs,渐进式 Web 应用): manifest.json、 Service Worker

文章目录 引言I 什么是 PWA功能特性技术上分为三个部分:II Web 应用清单将Web 应用清单文件链接到站点manifest.json字段说明III Service WorkerService worker 本质Service worker 运行在 worker 上下文注册服务辅助角色扩展知识将 PWA 作为脱机应用定义当前文档与被链接文档…

用Python实现运筹学——Day 4: 线性规划的几何表示

一、学习内容 线性规划的几何表示&#xff1a; 线性规划问题的解通常位于一个凸多边形&#xff08;即可行解空间&#xff09;的顶点上&#xff0c;这意味着在求解线性规划问题时&#xff0c;只需要找到可行解空间中的顶点并计算出目标函数值&#xff0c;再选择其中的最优解。 可…

C++之分割字符串的两种方式

方式一 #include <string> #include <vector> #include <sstream> #include <iostream>std::vector<std::string> split(const std::string& str, char delim) {std::stringstream ss(str);std::string item;std::vector<std::string>…

C语言贪吃蛇小游戏演示和说明

C语言贪吃蛇小游戏演示和说明 设计贪吃蛇游戏的主要目的是让大家夯实C语言基础&#xff0c;训练编程思维&#xff0c;培养解决问题的思路&#xff0c;领略多姿多彩的C语言。 游戏开始后&#xff0c;会在中间位置出现一条只有三个节点的贪吃蛇&#xff0c;并随机出现一个食物&am…

keepalived+lvs集群,实现高可用

环境准备&#xff1a;两台虚拟机&#xff0c;关闭防火墙&#xff0c;selinux,配置阿里云仓库&#xff0c;配置epel 192.168.88.21 dr1 负载均衡器 master 192.168.88.22 dr2 负载均衡器 backup 192.168.88.23 rs1 web1 192.168.88.24 rs2 web2 实验说明&…

项目启动错误

说明&#xff1a;记录一次项目启动&#xff0c;报数据库访问错误&#xff0c;如下&#xff1a; 错误信息&#xff1a;Invalid default&#xff1a;public abstract java.lang.Class tk.mybatis.spring.annotation.MapperScan.fatoryBean() 解决 没有引入mybatis依赖&#xff…

通信工程学习:什么是VIM虚拟化基础设施管理器

VIM:虚拟化基础设施管理器 VIM(Virtualized Infrastructure Manager)虚拟化基础设施管理器,是一种负责管理和控制虚拟化环境中所有虚拟资源的工具和系统。以下是关于VIM虚拟化基础设施管理器的详细解释: 一、定义与功能 VIM是网络功能虚拟化(NFV)架构中…

HarmonyOS---权限和http/Axios网络请求

网络请求(http,axios) 目录 一、应用权限管理1.1权限的等级1.2授权方式1.3声明权限的配置1.4如何向用户进行申请 二、内置http请求使用三、Axios请求使用&#xff08;建议&#xff09;3.1 使用方式一3.2 使用方式二&#xff08;建议&#xff09; 一、应用权限管理 应用权限保护…

Leetcode面试经典150题-322.零钱兑换

给你一个整数数组 coins &#xff0c;表示不同面额的硬币&#xff1b;以及一个整数 amount &#xff0c;表示总金额。 计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额&#xff0c;返回 -1 。 你可以认为每种硬币的数量是无限的。 示…

uniapp 常用高度状态栏,导航栏,tab栏,底部安全高度

实际效果 使用 //使用 let posConfig this.getPosConfig(); // 传false返回值为 px大小 console.log(posConfig.safeBottomH) // 入参 是否转换为rpxgetPosConfig(toRpx true) {const systemInfo uni.getSystemInfoSync();// #ifdef MPconst menuButtonInfo uni.getMenuBu…

基于RPA+BERT的文档辅助“悦读”系统 | OPENAIGC开发者大赛高校组AI创作力奖

在第二届拯救者杯OPENAIGC开发者大赛中&#xff0c;涌现出一批技术突出、创意卓越的作品。为了让这些优秀项目被更多人看到&#xff0c;我们特意开设了优秀作品报道专栏&#xff0c;旨在展示其独特之处和开发者的精彩故事。 无论您是技术专家还是爱好者&#xff0c;希望能带给…

Linux云计算 |【第四阶段】NOSQL-DAY2

主要内容&#xff1a; Redis集群概述、部署Redis集群&#xff08;配置manage管理集群主机、创建集群、访问集群、添加节点、移除节点&#xff09; 一、Redis集群概述 1、集群概述 所谓集群&#xff0c;就是通过添加服务器的数量&#xff0c;提供相同的服务&#xff0c;从而让…

计算机毕业设计之:微信小程序的校园闲置物品交易平台(源码+文档+讲解)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

卷积神经网络-迁移学习

文章目录 一、迁移学习1.定义与性质2.步骤 二、Batch Normalization&#xff08;批次归一化&#xff09;三、ResNet网络1.核心思想2.残差结构&#xff08;1&#xff09;残差块&#xff08;2&#xff09;残差结构类型 四、总结 一、迁移学习 迁移学习&#xff08;Transfer Lear…