第二章的内容主要是关于链表的一些问题。

基础代码:

class  LinkNode
{
public:
int linknum;
LinkNode *next;
int isvisit;
protected:
private:
}; extern void printlinkedlist(LinkNode* head);
extern LinkNode* createlinkedlist();
extern LinkNode* addfirst(LinkNode* ln,LinkNode* head);
extern LinkNode* addlast (LinkNode* ln,LinkNode* head);
extern LinkNode* remove (LinkNode* ln,LinkNode* head);
extern LinkNode* addloop (LinkNode* ln,LinkNode* head); extern LinkNode* removeduplicate1(LinkNode* head);
extern LinkNode* removeduplicate2(LinkNode* head); extern LinkNode* findlastnthnode(LinkNode* head,int n);
extern LinkNode* add(LinkNode* h1,LinkNode* h2); extern LinkNode* deletemiddle(LinkNode* head,int linknum); extern LinkNode* backbeginloop(LinkNode* head);
LinkNode* createlinkedlist()
{
LinkNode *head;
head = new LinkNode();
head->next = NULL;
return head;
}
LinkNode* addfirst(LinkNode* ln,LinkNode* head)
{
ln->next = head->next;
head->next = ln;
return head;
}
LinkNode* addlast (LinkNode* ln,LinkNode* head)
{
LinkNode* iterator;
iterator = head;
while (iterator->next != NULL)
{
iterator = iterator->next;
}
ln->next = iterator->next;
iterator->next = ln;
return head;
}
LinkNode* remove (LinkNode* ln,LinkNode* head)
{
LinkNode* iterator = head;
while (iterator->next != NULL)
{
if (iterator->next->linknum == ln->linknum)
iterator->next = iterator->next->next;
iterator = iterator->next;
}
return head;
}
LinkNode* addloop (LinkNode* ln,LinkNode* head)
{
LinkNode* iterator = head;
while (iterator->next != ln)
{
iterator = iterator->next;
}
LinkNode* newiterator = iterator->next;
while (iterator->next != NULL)
{
iterator = iterator->next;
}
iterator->next = newiterator;
return head;
}

1.Wirte code to remove duplicates from an unsorted linked list。How would you solve this problem if a temporary buffer is not allowed?

我的思路:移除链表中重复的元素,按照第一张数组中的思路。一种利用hashtable标记元素是否已经存在,若存在则删除。另外一种思路不利用额外的存储空间的方法利用双重循环,一个指针检查一个节点时候,另外一个指针检查其他所有的元素,相同则删除。

(1)

LinkNode* removeduplicate1(LinkNode* head)
{
int array[26] = {0};
LinkNode* iterator = head;
while (iterator->next != NULL)
{
array[iterator->next->linknum-1]++;
if (array[iterator->next->linknum-1] > 1)
iterator->next = iterator->next->next;
else
iterator = iterator->next;
}
return head;
}

(2)

LinkNode* removeduplicate2(LinkNode* head)
{
LinkNode* tmphead;
tmphead = head->next;
while (tmphead != NULL)
{
remove(tmphead,tmphead);
tmphead = tmphead->next;
}
return head;
}

书中的一些解决方案:

其实很类似,只是在第二种方法的时候,它的方案是外层循环1~tail,然后内层循环head~外层循环位置。

2.Implement an algorithm to find the nth to last element of a single linked list.

由于这个题目之前某次实习面试的时候被问到了,我当时不知道如何得到这个问题,当时给出的思路是遍历至链表的尾部,然后从尾部向前计数。当然这种思路比较蠢...

回来之后求助于网络,了解到利用两个指针一次便利即可完成此操作。

LinkNode* findlastnthnode(LinkNode* head,int n)
{
int count = 0;
LinkNode* iterator = head->next;
LinkNode* niterator = head->next;
while(iterator != NULL)
{
iterator = iterator->next;
if (count >= n)
{
niterator = niterator -> next;
}
count++;
}
return niterator;
}

书中的一些解决方案:

3.Implement an algorithm to delete a node in the middle of a single linked list given only access to that node.For example:

Input:the node 'c' from the linked list a->b->c->d->e

Result:nothing is returned,but the new linked list looks like a->b->d->e

这个题目我其实没有怎么理解,只有那个节点的访问权又是何意。in the middle of我理解成了中间的一个,所以我的代码是判断是否是这个字符,如果是则检查是否是中间的一个,如果是,则删除。

LinkNode* deletemiddle(LinkNode* head,int linknum)
{
LinkNode* iterator = head;
int prevcount = 0;
int nextcount = 0;
while (iterator->next->linknum != NULL)
{
prevcount++;
if (iterator->next->linknum == linknum)
{
nextcount = 0;
LinkNode* newiterator = iterator;
while (newiterator->next != NULL)
{
nextcount++;
newiterator = newiterator->next;
}
if (prevcount == nextcount)
{
iterator->next = iterator->next->next;
break;
}
}
iterator = iterator->next;
}
return head;
}

书中的一些解决方案:

我不太确定书中的描述:

The Solution to this is to simply copy the data from the next node into this node and then delete the next node.

NOTE:This problem can not be solved if the node to be deleted is the last node in the linked list.???这里的描述不是很明白。

4.You have two numbers represented by a linked list,where each node contains a single digit.The digits are stored in reverse order,such that the 1's digit is at the head of the list.Write a function that adds the two numbers and returns the sum as a linked list.For example:

input:3->1->5+5->9->2

output:8->0->8

简单的加法运算。首先可以每位进行相加,如果超过了10,则进位。若是最后一个元素超过10,则需要开辟新的节点。

LinkNode* add(LinkNode* h1,LinkNode* h2)
{
LinkNode* it1 = h1->next;
LinkNode* it2 = h2->next;
int back = 0;
LinkNode* newhead = new LinkNode();
while(it1 != NULL || it2 != NULL)
{
int num = back;
back = 0;
if (it1 != NULL)
{
num += it1->linknum;
it1 = it1->next;
}
if (it2 != NULL)
{
num += it2->linknum;
it2 = it2->next;
}
if (num >= 10)
{
num -= 10;
back ++;
}
LinkNode* ln = new LinkNode();
ln->linknum = num;
addlast(ln,newhead);
}
if (back != 0)
{
LinkNode* last = new LinkNode();
last->linknum = back;
addlast(last,newhead);
}
return newhead;
}

书中的一些解决方案:

整体思路类似,只是书中的参考利用递归计算。

  5.Given a circular linked list,implement an algorithm which returns node at the beginning of the loop.

  Definition:

  Circular linked list:A linked list in which a node's next pointer points to an eariler node,so as to make a loop in the linked list.

  For example:

  input:a->b->c->d->e->c

  output:c

这个题目看起来十分容易,但是我写起来的时候却想不起来解决方案。因为遍历这个链表根本不会有结束的条件,死循环。我执行程序的时候发现的这个问题。

后来只有改变链表内部节点的结构,添加一个标志位,如果访问过则标记,这样就容易找到开始循环的地方。

//broken the linkedlist node,maybe I can use an array or vector?
LinkNode* backbeginloop(LinkNode* head)
{
LinkNode* iterator = head->next;
while (iterator->isvisit == 0)
{
iterator->isvisit = 1;
iterator = iterator->next;
}
return iterator;
}

书中的解决方案:

这个题目的思考方式我觉得挺新颖的。可以这么理解,比如一个操场上两个人从共同的起点一起跑步,一个人的速度刚好是另外一个人速度的两倍,所以他们第二次必定相遇在起点的地方。这样就存在了一个结束条件。

但是这里链表的开始不能保证是起点,也就是说慢速的那个人到达链表循环的起点时候,速度快的那个人已经超过了速度慢的人k距离这么远(k为链表起点至循环起点的距离)。所以考虑不同起点的速度不同的两个人的相遇的情况...这其实是一个数据问题了,像我这种数学不是很给力的怎么也得列一个方程。 (2*speed*t + k )%n = speed*t %n

这里每次前进1,所以速度为1,则(2*t+k)%n = t%n,可以得到这个第一个t的值为n-k,所以第一次相遇在n-k的地方。

所以相遇的地方再前进k步就到达了循环的起点。然后链表的起点至循环的起点距离刚刚也是k,所以这里又是一个结束的条件。

LinkedListNode FindBeginning(LinkedListNode head) {
LinkedListNode n1 = head;
LinkedListNode n2 = head;
//step1 meeting before k at beginning loop
while(n2.next != null) {
n1 = n1.next;
n2 = n2.next.next;
if ( n1 == n2)
break;
}
if(n2.next == null) {
return null;
}
n1 = head;
//step 2,meeting at the beginning loop
while(n1 != n2) {
n1 = n1.next;
n2 = n2.next;
}
return n2;
}

Cracking the Coding Interview(linked list)的更多相关文章

  1. Cracking the Coding Interview(Trees and Graphs)

    Cracking the Coding Interview(Trees and Graphs) 树和图的训练平时相对很少,还是要加强训练一些树和图的基础算法.自己对树节点的设计应该不是很合理,多多少少 ...

  2. 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 ...

  3. 二刷Cracking the Coding Interview(CC150第五版)

    第18章---高度难题 1,-------另类加法.实现加法. 另类加法 参与人数:327时间限制:3秒空间限制:32768K 算法知识视频讲解 题目描述 请编写一个函数,将两个数字相加.不得使用+或 ...

  4. Cracking the Coding Interview(String and array)

    1.1实现一个算法判断一个字符串是否存在重复字符.如果不能利用另外的数据结构又该如何实现? My solution: /** *利用类似一个hash table的计数 *然后检查这个hash tabl ...

  5. Cracking the coding interview

    写在开头 最近忙于论文的开题等工作,还有阿里的实习笔试,被虐的还行,说还行是因为自己的水平或者说是自己准备的还没有达到他们所需要人才的水平,所以就想找一本面试的书<Cracking the co ...

  6. Cracking the coding interview 第一章问题及解答

    Cracking the coding interview 第一章问题及解答 不管是不是要挪地方,面试题具有很好的联系代码总用,参加新工作的半年里,做的大多是探索性的工作,反而代码写得少了,不高兴,最 ...

  7. 《Cracking the Coding Interview》读书笔记

    <Cracking the Coding Interview>是适合硅谷技术面试的一本面试指南,因为题目分类清晰,风格比较靠谱,所以广受推崇. 以下是我的读书笔记,基本都是每章的课后习题解 ...

  8. 链表(Linked List)

    链表(Linked List) 一.介绍 链表是有序的列表,它在内存中存储方式(物理存储)如下: 小结: (1)链表是以节点的方式来存储,是链式存储. (2)每个节点包含 data 域:存储数据:ne ...

  9. Cracking the coding interview目录及资料收集

    前言 <Cracking the coding interview>是一本被许多人极力推荐的程序员面试书籍, 详情可见:http://www.careercup.com/book. 第六版 ...

随机推荐

  1. 简单介绍Linux下安装Tomcat的步骤

    Tomcat是一个免费的开源的Serlvet容器,它是Apache基金会的Jakarta项目中的一个核心项目,由Apache,Sun和其它一些公司及个人共同开发而成.由于有了Sun的参与和支持,最新的 ...

  2. 按键精灵如何调用Excel及按键精灵写入Excel数据的方法教程---入门自动操作表格

    首先来建立一个新的Excel文档,在桌面上点击右键,选择[新建]-[Excel工作表],命名为[新手学员]. 现在这个新Excel文档是空白的,我们接下来会通过按键精灵的脚本来打开并写入一些数据.打开 ...

  3. vue用阿里云oss上传图片使用分片上传只能上传100kb以内的解决办法

    首先,vue和阿里云oss上传图片结合参考了 这位朋友的 https://www.jianshu.com/p/645f63745abd 文章,成功的解决了我用阿里云oss上传图片前的一头雾水. 该大神 ...

  4. WebGL 浏览器函数

    1.requestAnimationFrame(func) 请求浏览器在将来某时刻回调函数func以完成重绘.requestAnimationFrame()成功的一个关键是确定你在执行其他用户diam ...

  5. 取值为[1,n-1]含n个元素的整数数组,至少存在一个重复数,即可能存在多个重复数,O(n)时间内找出其中任意一个重复数,不使用额外存储空间。

    有一种非常诡异的算法,就是采用类似于单链表是否存在环的问题.“判断单链表是否存在环”是一个非常经典的问题,同时单链表可以采用数组实现,此时每个元素值作为next指针指向下一个元素.本题可以转换化为“已 ...

  6. Cordova 问题点备忘

    1 cordova File插件问题 cordova 5.0创建本地文件夹 目录变成了 file:///data/user/0/com.xxx.xxx/xxx 4.0 是 file:///storag ...

  7. Dubbo -- 系统学习 笔记 -- 示例 -- 静态服务

    Dubbo -- 系统学习 笔记 -- 目录 示例 想完整的运行起来,请参见:快速启动,这里只列出各种场景的配置方式 静态服务 有时候希望人工管理服务提供者的上线和下线,此时需将注册中心标识为非动态管 ...

  8. [AX]AX2012 R2 出差申请和支出报告

    AX2012中有个模块叫做出差和支出,用于管理出差以及相关的费用,用户只能在员工自助服务EP站点上提交出差申请.费用报销报告,在Client程序中做审核以及后续的支付动作等,最后形成相关的财务分录. ...

  9. Bypass D盾_IIS防火墙SQL注入防御(多姿势)

    0X01 前言 D盾_IIS防火墙,目前只支持Win2003服务器,前阵子看见官方博客说D盾新版将近期推出,相信功能会更强大,这边分享一下之前的SQL注入防御的测试情况.D盾_IIS防火墙注入防御策略 ...

  10. JavaWeb学习总结(十七)EL表达式

    语法格式: ${expression} 1. 表达式支持算术运算符合逻辑运算符 <%@ page language="java" contentType="text ...