博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[LeetCode] Alien Dictionary 另类字典
阅读量:7081 次
发布时间:2019-06-28

本文共 3911 字,大约阅读时间需要 13 分钟。

There is a new alien language which uses the latin alphabet. However, the order among letters are unknown to you. You receive a list of words from the dictionary, where words are sorted lexicographically by the rules of this new language. Derive the order of letters in this language.

For example,

Given the following words in dictionary,

[  "wrt",  "wrf",  "er",  "ett",  "rftt"]

The correct order is: "wertf".

Note:

  1. You may assume all letters are in lowercase.
  2. If the order is invalid, return an empty string.
  3. There may be multiple valid order of letters, return any one of them is fine.

 

这道题让给了我们一些按“字母顺序”排列的单词,但是这个字母顺序不是我们熟知的顺序,而是另类的顺序,让我们根据这些“有序”的单词来找出新的字母顺序,这实际上是一道有向图的问题,跟之前的那两道和的解法很类似,我们先来看BFS的解法,我们需要一个set来保存我们可以推测出来的顺序关系,比如题目中给的例子,我们可以推出的顺序关系有:

t->fw->er->te->r

那么set就用来保存这些pair,我们还需要另一个set来保存所有出现过的字母,需要一个一维数组in来保存每个字母的入度,另外还要一个queue来辅助拓扑遍历,我们先遍历单词集,把所有字母先存入ch,然后我们每两个相邻的单词比较,找出顺序pair,然后我们根据这些pair来赋度,我们把ch中入度为0的字母都排入queue中,然后开始遍历,如果字母在set中存在,则将其pair中对应的字母的入度减1,若此时入度减为0了,则将对应的字母排入queue中并且加入结果res中,直到遍历完成,我们看结果res和ch中的元素个数是否相同,若不相同则说明可能有环存在,返回空字符串,参见代码如下:

解法一:

class Solution {public:    string alienOrder(vector
& words) { set
> s; unordered_set
ch; vector
in(256, 0); queue
q; string res = ""; for (auto a : words) ch.insert(a.begin(), a.end()); for (int i = 0; i < words.size() - 1; ++i) { int mn = min(words[i].size(), words[i + 1].size()), j = 0; for (; j < min(words[i].size(), words[i + 1].size()); ++j) { if (words[i][j] != words[i + 1][j]) { s.insert(make_pair(words[i][j], words[i + 1][j])); break; } } if (j == mn && words[i].size() > words[i + 1].size()) return ""; } for (auto a : s) ++in[a.second]; for (auto a : ch) { if (in[a] == 0) { q.push(a); res += a; } } while (!q.empty()) { char c = q.front(); q.pop(); for (auto a : s) { if (a.first == c) { --in[a.second]; if (in[a.second] == 0) { q.push(a.second); res += a.second; } } } } return res.size() == ch.size() ? res : ""; }};

下面来看一种DFS的解法,思路和BFS的很类似,我们需要建立一个二维的bool数组g,然后把出现过的字母的对应的位置都赋为true,然后我们把可以推出的顺序的对应位置也赋为true,然后我们就开始递归调用,如果递归函数有返回false的,说明有冲突,则返回false,递归调用结束后结果res中存了入度不为0的字母,最后把入度为0的字母加到最后面,最后把结果res翻转一下即可,参见代码如下:

解法二:

class Solution {public:    string alienOrder(vector
& words) { vector
> g(26, vector
(26, false)); vector
path(26, false); string res = ""; for (string word : words) { for (char c : word) { g[c - 'a'][c - 'a'] = true; } } for (int i = 0; i < words.size() - 1; ++i) { int mn = min(words[i].size(), words[i + 1].size()), j = 0; for (; j < mn; ++j) { if (words[i][j] != words[i + 1][j]) { g[words[i][j] - 'a'][words[i + 1][j] - 'a'] = true; break; } } if (j == mn && words[i].size() > words[i + 1].size()) return ""; } for (int i = 0; i < 26; ++i) { if (!dfs(g, i, path, res)) return ""; } for (int i = 0; i < 26; ++i) { if (g[i][i]) res += (char)(i + 'a'); } return string(res.rbegin(), res.rend()); } bool dfs(vector
> &g, int idx, vector
&path, string &res) { if (!g[idx][idx]) return true; path[idx] = true; for (int i = 0; i < 26; ++i) { if (i == idx || !g[idx][i]) continue; if (path[i]) return false; if (!dfs(g, i, path, res)) return false; } path[idx] = false; g[idx][idx] = false; res += (char)(idx + 'a'); return true; }};

本文转自博客园Grandyang的博客,原文链接:,如需转载请自行联系原博主。

你可能感兴趣的文章
SUPERVISOR进程管理器配置指南
查看>>
解决:no device found for connection ‘ System eth0′
查看>>
jacob使用入门及问题解析
查看>>
实例讲解虚拟机3种网络模式(桥接、nat、Host-only)
查看>>
javascript相关
查看>>
51 Node 1174
查看>>
deeplink技术的两篇资料
查看>>
矩阵求和及Kadane算法
查看>>
linux文件系统目录
查看>>
二叉查找树的前驱后继
查看>>
amazeui学习笔记--css(基本样式2)--基础设置Base
查看>>
Vue el-date-picker 日期组件的使用
查看>>
Qt实现控件内捕获鼠标位置
查看>>
客户端地址和服务端地址
查看>>
Linux命令-文件
查看>>
yaml模块
查看>>
2017.7.13
查看>>
JAVA将数字字符串强制转换成整型变量----求参数之和实验代码(附流程图)
查看>>
深入理解Java虚拟机-----------虚拟机类加载机制
查看>>
编程语言介绍
查看>>