【程序员面试金典】面试题 17.25 . 单词矩阵

news/2025/1/31 17:48:18/

【程序员面试金典】面试题 17.25 . 单词矩阵

    • 题目描述
    • 解题思路

题目描述

描述:给定一份单词的清单,设计一个算法,创建由字母组成的面积最大的矩形,其中每一行组成一个单词(自左向右),每一列也组成一个单词(自上而下)。不要求这些单词在清单里连续出现,但要求所有行等长,所有列等高。

如果有多个面积最大的矩形,输出任意一个均可。一个单词可以重复使用。

示例 1:

输入: ["this", "real", "hard", "trh", "hea", "iar", "sld"]
输出:
["this","real","hard"
]

示例 2:

输入: ["aa"]
输出: ["aa","aa"]

说明:

words.length <= 1000
words[i].length <= 100
数据保证单词足够随机

解题思路

思路:最直观的想法是,字典树。首先利用单词清单建立字典树,并且将单词按照长度分组,再记录一下最大单词长度方便剪枝。由于所有行等长且所有列等高,所以必定是长度相同的单词才能一起构建单词矩阵,又需要求解面积最大的单词矩阵,故优先搜索长度最长的单词分组。在搜索某一分组时,首先将该单词加入,此时可以保证按照行该单词是在字典树中的,现在只需按照列判断单词是否在字典树中,并区分是作为字典树的前缀还是作为完整的单词在字典树中,再依据此来更新最大单词矩阵面积。

//字典树类
class Trie{public://标记是否结束bool isEnd;//记录下一个节点Trie* next[26];//构造函数Trie(){isEnd=false;memset(next,0,sizeof(next));}void insert(string s){Trie* cur=this;for(int i=0;i<s.size();i++){if(!cur->next[s[i]-'a'])cur->next[s[i]-'a']=new Trie();cur=cur->next[s[i]-'a'];}cur->isEnd=true;}
};
class Solution {
public://字典树根节点Trie* root=new Trie();vector<string> res;vector<string> temp;vector<string> maxRectangle(vector<string>& words) {//单词长度 单词列表map<int,vector<string>> mp;int maxlen=0,maxarea=0,area=0;for(auto word:words){//建立字典树root->insert(word);//收集结果mp[word.size()].push_back(word);//求最大长度maxlen=max(maxlen,(int)word.size());}//反向遍历 长度从大到小for(auto it=mp.rbegin();it!=mp.rend();it++){//最长单词*宽度 不够 不用寻找if(maxlen*(it->first)<maxarea)break;temp.clear();area=0;dfs(it->second,maxarea,maxlen,area);}return res;}void dfs(vector<string>& words,int& maxarea,int& maxlen,int& area){//最大极限退出if(words[0].size()*maxlen<=maxarea)return;vector<bool> ans;//按行加入for(int i=0;i<words.size();i++){temp.push_back(words[i]);ans=isgood(temp);//可以继续往下加单词if(ans[0]){area=temp.size()*temp[0].size();//均是结束单词且较大面积if(ans[1]&&area>maxarea){maxarea=area;res=temp;}//否则继续添加单词dfs(words,maxarea,maxlen,area);}//不能else 回溯temp.pop_back();}}vector<bool> isgood(vector<string>& tp){Trie *cur;bool allend=true;int n=temp[0].size();//按列检查for(int i=0;i<n;i++){cur=root;for(int j=0;j<tp.size();j++){if(!cur->next[tp[j][i]-'a'])return {false,false};cur=cur->next[tp[j][i]-'a'];}allend&=cur->isEnd;}return {true,allend}; //可以继续插入}
};

总结:按照列判断单词是否在字典树中,此时可以返回两个参数加以区分,一个参数是是否可以继续加入单词,另一个参数是是否全部单词均已经结束。在C++中,逆序遍历map是使用mp.rbegin()和mp.rend()。


http://www.ppmy.cn/news/760244.html

相关文章

用户权限.

1.Linux中的正常权限有&#xff1a;读、写、执行权限 2.用户和组&#xff1a; 2.1牵涉的相关命令&#xff1a; 2.2创建用户牵涉到的文件&#xff1a; 2.3用户和组的关系&#xff1a; 2.4用户信息&#xff1a; 2.5添加用户&#xff1a;useradd命令 2.6更改和删除用户&…

基本知识 100136

基本知识 100136 单选题 A1 1.疑为多囊卵巢综合征&#xff0c;行超声检查的最佳时间是 pcos 超声检查在月经周期或黄体酮撤退后出血的 3&#xff5e;5 日进行&#xff0c;显示卵巢体积增大&#xff0c;双侧卵巢均有 ge;12 个直径 2&#xff5e;9mm 的小卵泡&#xff0c;即卵…

C——货物管理系统

1 #include <stdio.h>2 #include <stdlib.h>3 #include <string.h>4 #include <conio.h> /*屏幕操作函数库*/5 6 /*主管权限数据格式化*/7 #define HEADER1_zg "-----------------------------货物管理系统(主管)------------------------…

【深入浅出Node.js系列七】Connect模块解析

为什么80%的码农都做不了架构师&#xff1f;>>> #0 系列目录# 深入浅出Node.js系列【深入浅出Node.js系列一】什么是Node.js【深入浅出Node.js系列二】Node.js&NPM的安装与配置【深入浅出Node.js系列三】深入Node.js的模块机制【深入浅出Node.js系列四】Node.j…

php 基础代码大全(不断完善中)

下面是基础的PHP的代码&#xff0c;不断完善中~ 1 //语法错误&#xff08;syntax error&#xff09;在语法分析阶段&#xff0c;源代码并未被执行&#xff0c;故不会有任何输出。2 3 4 /* 【命名规则】 */5 常量名 类常量建议全大写&#xff0c;单词间用下划线分隔 // MIN_W…

债券各种收益率

1.p&YTM ①计算 P∑cft/(1r)t a. 求P&#xff0c;同一个r b. 求YTM pv的值跟cf是相反的&#xff0c;付息频率&#xff0c;annui或者嫉妒的需要乘下 ②YTM假设&#xff0c;持有到期、没有违约、 <>IRR&#xff0c;以YTM再投资的 ③结论 a&#xff0c; p&ytm相…

计算机专用英语词汇1695个词汇表,这个收藏了

> →点击领取阿里云限量红包 1.单词说明&#xff1a;   command n. 命令&#xff0c;指令 [kəmɑ:nd]   单词拼写 名词 单词含义 音标&#xff08;发音&#xff09;   提示:着重记忆单词对应的意思&#xff0c;有能力最好词性也记忆。 > > 2.词性说明&#…

Mysql binlog 安全删除(转载)

简介&#xff1a; 如果你的 Mysql 搭建了主从同步 , 或者数据库开启了 log-bin 日志 , 那么随着时间的推移 , 你的数据库 data 目录下会产生大量的日志文件 shell > ll /usr/local/mysql/data/ # 如下 -rw-rw----. 1 mysql mysql 63278 9月 11 02:03 mysql-bin.000001 -rw…