《Cracking the Coding Interview》——第2章:链表——题目6
2014-03-18 02:41
题目:给定一个带有环的单链表,找出环的入口节点。
解法1:用hash来检测重复节点肯定是容易想而且效率也高的好办法。
代码:
// 2.6 You have a circular Linked List: a->b->c->d->e->c. Find where the cycle starts.
#include <cstdio>
#include <unordered_set>
using namespace std; struct ListNode {
int val;
ListNode *next;
ListNode(int x): val(x), next(nullptr) {};
}; class Solution {
public:
ListNode* firstFirstNodeInCycle(ListNode *head) {
if (head == nullptr) {
return head;
} // hash the pointers.
unordered_set<ListNode *> us;
ListNode *ptr; ptr = head;
while (ptr != nullptr) {
if (us.find(ptr) != us.end()) {
// the first node of the cycle is found.
return ptr;
} else {
us.insert(ptr);
ptr = ptr->next;
}
} // the list has no cycle.
return nullptr;
}
}; int main()
{
int i;
int n, k;
int val;
struct ListNode *head, *tail, *ptr;
Solution sol; while (scanf("%d", &n) == && n > ) {
// create a linked list
ptr = head = tail = nullptr;
for (i = ; i < n; ++i) {
scanf("%d", &val);
if (head == nullptr) {
head = ptr = new ListNode(val);
} else {
ptr->next = new ListNode(val);
ptr = ptr->next;
}
}
tail = ptr; // create a cycle in the list
scanf("%d", &k);
if (k >= && k <= n) {
ptr = head;
for (i = ; i < k; ++i) {
ptr = ptr->next;
}
tail->next = ptr;
} // find the first node in the cycle.
ListNode *first_node = sol.firstFirstNodeInCycle(head);
if (first_node != nullptr) {
printf("%d\n", first_node->val);
} else {
printf("no cycle\n");
} /*
// print the list
ptr = head;
for (i = 0; i < n; ++i) {
printf("%d->", ptr->val);
ptr = ptr->next;
}
printf("\n");
*/ // delete the list
for (i = ; i < n; ++i) {
ptr = head->next;
delete head;
head = ptr;
}
} return ;
}
解法2:如果你非不让我用hash,就只有观察一下几个特殊节点了。既然这个环有“第一个”点,那肯定也有“最后一个”点。我特地打了引号,是因为最后一个点恰好指向第一个。如果你从链表的头开始向后遍历,必然是先到达“第一个”,然后才能到达“最后一个的”。只有对于“最后一个”点,才会出现先到达ptr->next,后到达ptr的情况,所以如果存在符合这个情况的节点ptr,ptr->next就是我们要找的环的入口。这种方法效率不高而且不容易想,除了面试之外基本没有别的用处了。但为了面试淘汰一些人,这点用处也很重要了。
代码:
// 2.6 You have a circular Linked List: a->b->c->d->e->c. Find where the cycle starts.
#include <cstdio>
#include <unordered_set>
using namespace std; struct ListNode {
int val;
ListNode *next;
ListNode(int x): val(x), next(nullptr) {};
}; class Solution {
public:
ListNode* firstFirstNodeInCycle(ListNode *head) {
if (head == nullptr) {
return head;
} ListNode *p1, *p2; p1 = head;
while (p1 != nullptr) {
p2 = head;
while (p2 != p1->next && p2 != nullptr) {
if (p2 == p1) {
break;
} else {
p2 = p2->next;
}
}
if (p2 == p1->next) {
return p2;
} else {
p1 = p1->next;
}
} return nullptr;
}
}; int main()
{
int i;
int n, k;
int val;
struct ListNode *head, *tail, *ptr;
Solution sol; while (scanf("%d", &n) == && n > ) {
// create a linked list
ptr = head = tail = nullptr;
for (i = ; i < n; ++i) {
scanf("%d", &val);
if (head == nullptr) {
head = ptr = new ListNode(val);
} else {
ptr->next = new ListNode(val);
ptr = ptr->next;
}
}
tail = ptr; // create a cycle in the list
scanf("%d", &k);
if (k >= && k <= n) {
ptr = head;
for (i = ; i < k; ++i) {
ptr = ptr->next;
}
tail->next = ptr;
} // find the first node in the cycle.
ListNode *first_node = sol.firstFirstNodeInCycle(head);
if (first_node != nullptr) {
printf("%d\n", first_node->val);
} else {
printf("no cycle\n");
} /*
// print the list
ptr = head;
for (i = 0; i < n; ++i) {
printf("%d->", ptr->val);
ptr = ptr->next;
}
printf("\n");
*/ // delete the list
for (i = ; i < n; ++i) {
ptr = head->next;
delete head;
head = ptr;
}
} return ;
}
《Cracking the Coding Interview》——第2章:链表——题目6的更多相关文章
- Cracking the Coding Interview:: 寻找有环链表的环路起始节点
给定一个有环链表,实现一个算法返回环路的开头节点. 这个问题是由经典面试题-检测链表是否存在环路演变而来.这个问题也是编程之美的判断两个链表是否相交的扩展问题. 首先回顾一下编程之美的问题. 由于如果 ...
- Cracking The Coding Interview 2.0 单链表
#include <iostream> #include <string> using namespace std; class linklist { private: cla ...
- Cracking the coding interview 第一章问题及解答
Cracking the coding interview 第一章问题及解答 不管是不是要挪地方,面试题具有很好的联系代码总用,参加新工作的半年里,做的大多是探索性的工作,反而代码写得少了,不高兴,最 ...
- 《Cracking the Coding Interview》读书笔记
<Cracking the Coding Interview>是适合硅谷技术面试的一本面试指南,因为题目分类清晰,风格比较靠谱,所以广受推崇. 以下是我的读书笔记,基本都是每章的课后习题解 ...
- Cracking the coding interview
写在开头 最近忙于论文的开题等工作,还有阿里的实习笔试,被虐的还行,说还行是因为自己的水平或者说是自己准备的还没有达到他们所需要人才的水平,所以就想找一本面试的书<Cracking the co ...
- Cracking the Coding Interview(Trees and Graphs)
Cracking the Coding Interview(Trees and Graphs) 树和图的训练平时相对很少,还是要加强训练一些树和图的基础算法.自己对树节点的设计应该不是很合理,多多少少 ...
- Cracking the Coding Interview(Stacks and Queues)
Cracking the Coding Interview(Stacks and Queues) 1.Describe how you could use a single array to impl ...
- Cracking the coding interview目录及资料收集
前言 <Cracking the coding interview>是一本被许多人极力推荐的程序员面试书籍, 详情可见:http://www.careercup.com/book. 第六版 ...
- 《Cracking the Coding Interview》——第2章:链表——题目7
2014-03-18 02:57 题目:检查链表是否是回文的,即是否中心对称. 解法:我的做法是将链表从中间对半拆成两条,然后把后半条反转,再与前半条对比.对比完了再将后半条反转了拼回去.这样不涉及额 ...
随机推荐
- node实现爬虫
node实现获取到豆瓣电影排行榜页面. 准备工作: 1.新建一个文件夹node 在当前文件夹中打开cmd 下载 npm install 初始化 npm init(注意一下:如果你的npm init没有 ...
- 设定网页最小最大宽度和高度(兼容IE6)
http://www.cnblogs.com/double-bin/archive/2011/12/19/2293093.html /* 最小寬度 */ .min_width{min-width:30 ...
- 制作URL以GET方式提交的简单加密程序
首先我们用到的是 DESCryptoServiceProvider 类 对此微软给出的解释是 定义访问数据加密标准 (DES) 算法的加密服务提供程序 (CSP) 版本的包装对象.无法继承此类. 接下 ...
- 【CCPC-Wannafly Winter Camp Day3 (Div1) I】石头剪刀布(按秩合并并查集)
点此看题面 大致题意: 有\(n\)个人,第\(i\)个人坐在编号为\(i\)的座位上,每个人等概率有石头.剪刀.布中的一张卡片.有两种操作:第一种是第\(y\)个人挑战第\(x\)个人,如果胜利则\ ...
- 【UOJ139】【UER #4】被删除的黑白树(贪心)
点此看题面 大致题意: 请你给一棵树黑白染色,使每一个叶结点到根节点的路径上黑节点个数相同. 贪心 显然,按照贪心的思想,我们要让叶结点到根节点的路径上黑节点的个数尽量大. 我们可以用\(Min_i\ ...
- VPS一键测试脚本 / 自带结果导出
脚本命令 一下脚本可能卡住,运行时间长,建议在screen中运行. 1.秋水逸冰大佬的Bench.sh脚本 特点:用时较短,对系统测试全面,英文:但缺少国内节点测速 有趣的是,bench.sh既是脚本 ...
- 问题 B: 投简历
题目描述 小华历经12寒窗苦读,又经历4年大学磨砺,终于毕业了,随着毕业季的到来,找工作也日益紧张起来.由于要面试不同的公司,因此小华需要准备不同的简历.当然最基本的信息是必不可少的,基本信息:姓名. ...
- wcf 的小介绍
http://www.cnblogs.com/scottckt/archive/2010/10/15/1852136.html
- Yarn下分片和分块源代码分析
public class FileSplit extends InputSplit implements Writable { private Path file; private long star ...
- 【Oracle-DBA】Oracle连接非常慢APPARENT DEADLOCK
我是一名软件包工头,哪里有问题就干哪里. 这次是 Oracle 出毛病了,我就临时兼了DBA的职,没办法,谁叫我是工头呢.打开百度就开干. 这次关键词是:APPARENT DEADLOCK!!! 丫的 ...