《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 题目:检查链表是否是回文的,即是否中心对称. 解法:我的做法是将链表从中间对半拆成两条,然后把后半条反转,再与前半条对比.对比完了再将后半条反转了拼回去.这样不涉及额 ...
随机推荐
- 笨办法学Python(二十五)
习题 25: 更多更多的练习 我们将做一些关于函数和变量的练习,以确认你真正掌握了这些知识.这节练习对你来说可以说是一本道:写程序,逐行研究,弄懂它. 不过这节练习还是有些不同,你不需要运行它,取而代 ...
- Altium_Designer-PCB中布局元器件时的翻转问题
这个问题是我在第一次对PCB元器件布局时发现的,当时我绘制好原理图生成PCB后,出现了这样一个情况: 在我反复尝试走线后,走好线发现很困难,最后我才想到如果能把这个器件反转一下问题不就都解决了吗!自己 ...
- 将TIF格式批量转换成jpg或png格式(C#自制软件)
此项目基于.net framework 4.0 全选tif,拖进去,等待,完成. so easy... 链接:https://pan.baidu.com/s/1uCDhAT0uHRjdy4g557wK ...
- 整合ssm集成框架
第一步:配置pom.xml 该代码放在<dependencies>里面 <!--spring 所需要的jar包 web.aop.jdbc.webmvc--> <!--1. ...
- 删除已有的 HTML 元素
如需删除 HTML 元素,您必须首先获得该元素的父元素: 实例 <div id="div1"> <p id="p1">这是一个段落.&l ...
- c/c++面试指导---c语言基础算法总结1
c语言基础算法总结 1 初学者学习任何一门编程语言都必须要明确,重点是学习编程方法和编程思路,不是学习语法规则,语法规则是为编程实现提供服务和支持.所以只要认真的掌握了c语言编程方法,在学习其它的语 ...
- iconv for linux(c)
// code_convert("gb2312","utf-8",inbuf,outbuf,outlen);static int code_convert(co ...
- 神经网络系列学习笔记(四)——神经网络之RNN学习笔记
不同于传统的FNNs(Feed-forward Neural Networks,前向反馈神经网络),RNNs引入了定向循环,能够处理那些输入之间前后关联的问题. RNNs的目的是用来处理序列数据. 具 ...
- Jenkins持续化集成
Jenkins介绍 Jenkins是基于Java开发的一种持续集成工具,用于监控持续重复的工作,功能包括: 1.持续的软件版本发布/测试项目. 2.监控外部调用执行的工作. 安装环境 操作系统:lin ...
- OpenLDAP部署目录服务
文档信息 目 的:搭建一套完整的OpenLDAP系统,实现账号的统一管理. 1:OpenLDAP服务端的搭建 ...