- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
预备知识 - 可以跳过:这个问题与 Longest Path for Directed Cyclic Graph 有关.现在,那里有一点争议,关于仅隔离有向图中的循环、迭代或递归等是多么微不足道或不微不足道,所以我决定将其作为一个问题打开——我想会有是其他非 CS 毕业生(像我一样),他们将来可能会从清晰且解释清楚的答案中受益。
现在的问题可以说是“学术性的”——目的是获得尽可能多的答案:
Given a totally connected graph obeying the "exactly one child node for every node" rule (therefore exactly one cycle must exist) remove all nodes not part of the cycle in O(N).
The algo should minimally answer to the question of "what is the length of the cycle", the identity/indexes of the node a bonus. Considerations about complexity (why is O(N)) will be welcomed.
A bonus if the algo can deal with non-totally connected graphs and identify all the cycles (not only the nodes belonging to any cycle, but also separating/tagging them with a cycle identifier).
这就是为什么我悬赏(以 SO gold 形式)并放宽语言要求的原因。
下图中的一个例子
节点沿线从低到高连接。
如果我没记错的话,邻接向量(索引指定节点
,值指定node.next
)将显示为
[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 80,
11, 12, 13, 14, 15, 16, 17, 18, 19, 81,
21, 22, 23, 24, 25, 26, 27, 28, 29, 82,
31, 32, 33, 34, 35, 36, 37, 38, 39, 83,
41, 42, 43, 44, 45, 46, 47, 48, 49, 84,
51, 52, 53, 54, 55, 56, 57, 58, 59, 85,
61, 62, 63, 64, 65, 66, 67, 68, 69, 86,
71, 72, 73, 74, 75, 76, 77, 78, 79, 87,
81, 82, 83, 84, 85, 86, 87, 80 ]
其他测试数据:
[0]
单个节点“ curl ”到自身(就像“弦论”中的额外维度?)[1,2,2,2]
- 索引为 2 的奇点,左右都落在其中[1,0,1,2,3]
- 从循环开始,尾部朝向它最佳答案
我的回答在原始问题中被接受,所以这里是我的 原始问题的解决方案 作为 JS 片段。运行时间 O(n),空间 O(n)。
var data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 80,
11, 12, 13, 14, 15, 16, 17, 18, 19, 81,
21, 22, 23, 24, 25, 26, 27, 28, 29, 82,
31, 32, 33, 34, 35, 36, 37, 38, 39, 83,
41, 42, 43, 44, 45, 46, 47, 48, 49, 84,
51, 52, 53, 54, 55, 56, 57, 58, 57, 85,
61, 62, 63, 64, 65, 66, 67, 68, 69, 86,
71, 72, 73, 74, 75, 76, 77, 78, 79, 87,
81, 82, 83, 84, 85, 86, 87, 80
];
var visited = new Array(data.length);
var chains = [];
for (var i = 0; i < data.length; i++) {
if (!visited[i]) {
var current = {
chain: chains.length
}
var j = i;
var len = 0;
do {
len++;
visited[j] = current;
j = data[j];
} while (!visited[j]);
if (visited[j].chain === current.chain) {
chains.push(len);
} else {
current.chain = visited[j].chain;
chains[current.chain] += len;
}
}
}
//the visited array now contains information about which chain each node belongs to
document.write("<table><tr>");
for (var i = 0; i < visited.length; i++) {
document.write("<td>"+i + "=>" + visited[i].chain + "</td>");
if (i % 10 == 9) {
document.write("<tr/><tr>");
}
}
document.write("</table></tr>");
document.write("<p>Chain lengths: " + chains+"</p>");
请注意,发布的数据集在 Octopus 中确实存在“错误”; 57 => 58 => 57 使它成为一个与“ Octopus ”分开的“套索”。
这里是问题的解决方案:
运行时 O(n),空间 O(n),导致数组“访问”了循环的 true 部分,false 不是循环的一部分。
var data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 80,
11, 12, 13, 14, 15, 16, 17, 18, 19, 81,
21, 22, 23, 24, 25, 26, 27, 28, 29, 82,
31, 32, 33, 34, 35, 36, 37, 38, 39, 83,
41, 42, 43, 44, 45, 46, 47, 48, 49, 84,
51, 52, 53, 54, 55, 56, 57, 58, 59, 85,
61, 62, 63, 64, 65, 66, 67, 68, 69, 86,
71, 72, 73, 74, 75, 76, 77, 78, 79, 87,
81, 82, 83, 84, 85, 86, 87, 80
];
var visited = new Array(data.length);
// Pass 1: mark
for (var i = 0; i < data.length; i++) {
if (visited[i] == null) {
var k;
var j = i;
do {
visited[j] = false;
k = j;
j = data[j];
} while (visited[j] == null);
visited[k] = i == 0;
}
}
// Pass 2: propagate
var cnt = 0;
for (var i = 0; i < visited.length; i++) {
if (visited[i]) {
var j = i;
do {
cnt ++;
visited[j] = true;
j = data[j];
} while (j != i);
break;
}
}
//the visited array now contains information about nodes belonging to loop
document.write("Count: "+cnt);
document.write("<table><tr>");
for (var i = 0; i < visited.length; i++) {
document.write("<td>" + i + "=>" + visited[i] + "</td>");
if (i % 10 == 9) {
document.write("<tr/><tr>");
}
}
编辑:如果数据结构中始终只有一个循环,则可以进一步简化过程:
var data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 80,
11, 12, 13, 14, 15, 16, 17, 18, 19, 81,
21, 22, 23, 24, 25, 26, 27, 28, 29, 82,
31, 32, 33, 34, 35, 36, 37, 38, 39, 83,
41, 42, 43, 44, 45, 46, 47, 48, 49, 84,
51, 52, 53, 54, 55, 56, 57, 58, 59, 85,
61, 62, 63, 64, 65, 66, 67, 68, 69, 86,
71, 72, 73, 74, 75, 76, 77, 78, 79, 87,
81, 82, 83, 84, 85, 86, 87, 80
];
var visited = new Array(data.length);
// Pass 1: find one item which must be in cycle, max runtime O(n)
var j = 0;
do {
visited[j] = false;
j = data[j];
} while (visited[j] == null);
// Pass 2: follow cycle, max runtime O(n)
var cnt = 1;
for (var i = data[j]; i != j; i = data[i]) {
cnt ++;
// you could store the cycle nodes here to identify the non-cycle ones
}
//the visited array now contains information about nodes belonging to loop
document.write("Count: "+cnt);
再次编辑:实现了对多周期的支持;将输出所有循环长度和最长循环的节点。复杂度仍然为 O(n)。 :)
var data=[5,4,4,1,3,0];
var visited = new Array(data.length);
var chains = [];
// Pass 1: find all chains - complexity O(n)
for (var i = 0; i < data.length; i++) {
if (!visited[i]) {
var current = {
chain: chains.length
}
var j = i;
var len = 0;
do {
len++;
visited[j] = current;
j = data[j];
} while (!visited[j]);
if (visited[j].chain === current.chain) {
chains.push(j); // this index is part of a cycle
} else {
current.chain = visited[j].chain;
}
}
}
// Pass 2: count elements, max complexity O(n) because no node is visited twice and only nodes which are part of a cycle will be visited
var lengths = new Array(chains.length);
var best = [];
for (var i = 0; i < chains.length; i++) {
var curr = [];
var j = chains[i];
do {
curr.push(j);
j = data[j];
} while (j != chains[i]);
lengths[i] = curr.length;
if (curr.length > best.length) {
best = curr;
}
}
// Output result:
document.write("<p>Identified cycle lengths: "+lengths.join(", ")+"</p>");
document.write("<p>IDs of longest cycle: "+best.join(", ")+"</p>");
关于algorithm - 修剪 Octopus - 删除不属于 O(N) 中循环的有向图的所有分支,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41120347/
我使用 Git 有一段时间了,但尽管在博客和教程上花了很多时间,但我仍然无法理解某些功能...:) 我正在与其他人合作一个项目,我的老板为此在 bitBucket 上创建了一个存储库。 我在本地克隆了
有时我会遇到以下问题: 在功能分支中添加一些提交。 从上游更新 master。 想要查看功能分支和 master 之间的差异,但是 git diff master 显示了在 master 中添加/删除
我使用的是 Gerrit 2.4.2 版。我有一个分支 master,我创建了一个名为 newbranch 的新分支。然后我将一些更改推送到远程(Gerrit 的)newbranch。在 Gerrit
假设我们有一个远程存储库并在本地克隆它。 我们 checkout master 分支,所以现在我们有本地 master 和一个 Remote remotes/origin/master . 然后我必须
我有一个项目,其中开发分支使用 CocoaPods,但其中一位开发人员决定删除它并改用 Carthage。 feature 分支使用的是 CocoaPods,因为它是在 develop 分支转换之前一
我有一个有问题的 master 分支需要调试。为此,我想插入一堆调试程序(例如,打印变量),查明错误并应用修复程序。稍后,我想将修复 merge 到 master 分支中,但我不想跳过调试更改。 #
我有一个 master 分支,我正在其中 push 我的最新开发。 现在在某个时候,我确实从 master 分支发布并创建了名为 release1 的新分支。 现在我在master分支上做新的开发 与
我正在尝试使我的一些标准工作流程自动化,我发现自己经常做的一件事是将对远程 master 分支的更改 merge 到我自己的本地分支并推送结果。 所以步骤如下: 转为大师 从远程 pull 更改 切换
使用 Gerrit 很容易意外地将开发分支中的不稳定代码 merge 到稳定分支中: $ git checkout develop $ commit $ git push origin HEAD:re
我有一个正在进行的项目,我正在雇用承包商来帮助我处理代码的某些部分。问题是我不想让任何一个承包商看到所有这些。 我可以在 GitHub 上为他们分配私有(private)存储库下的分支吗?这需要命令行
SVN 分支 Branch 选项会给开发者创建出另外一条线路。当有人希望开发进程分开成两条不同的线路时,这个选项会非常有用。我们先假设你已经发布了一个产品的 1.0 版本,你可能想创建一个新的分支,
关闭。这个问题是opinion-based .它目前不接受答案。 想改进这个问题?更新问题,以便 editing this post 提供事实和引用来回答它. 2年前关闭。 Improve this
有没有办法从特定的修订版中创建(svn)分支, 因为我想跳过提交历史中的一些修订(在新分支中)。 例如,我有从 1 到 1590 的修订,我想创建一个新分支并跳过提交(从 1504 到 1574 )和
到目前为止我看到的所有 svn 分支的例子都是这样的 svn cp -m 'Making test branch' svn://svnrepo/hellosite svn://svnrepo/hell
当我尝试使用 Sonar 扫描仪分析我的项目时,扫描失败并显示以下错误消息: Caused by: Branch does not exist on server: develop 显然,这只发生在它
在我的 Mercurial 存储库中,不知何故,有人输入了空白分支名称: 如果我hg id -r 2004,我确实得到空白文本。现在的问题是,这会导致我们的Redmine安装出现问题,因为它无法同步存
我有以下代码片段: srcaddr >= inet_ntoa . fromJust dstaddr >= inet_ntoa . fromJust -- I want to perform actio
在我的项目中,我有用于工作的本地分支和网络驱动器上的分支我在本地一号和网络一号之间做了“绑定(bind)分支”我的想法是使用绑定(bind)选项自动备份每个本地提交。 我在本地分支提交文件后,我在网络
我想创建一个脚本,根据变量的状态使用不同的表和命令执行不同的操作。在 T-SQL 中,我会这样做: DECLARE @whatToDo INT = 1; IF @whatToDo = 1 BEGIN
Write a program that reads input up to # and reports the number of times that the sequence ei occurs
我是一名优秀的程序员,十分优秀!