`

链表的一些常见笔试面试问题总结及代码

阅读更多

先什么也不说,假设链表节点的数据结构为:

 

struct node
{
int data;
struct node* next;
};

创建单链表的程序为:

struct node* create(unsigned int n)
{
//创建长度为n的单链表
assert(n > 0);
node* head;
head = new node;
head->next = NULL;
cout << "请输入head节点的值(int型):";
cin >> head->data;
if (n == 1)
{
   return head;
}
node* p = head;
for (unsigned int i = 1; i < n; i++)
{
   node* tmp = new node;
   tmp->next = 0;
   cout << "请输入第" << i+1 << "个节点的值(int):";
   cin >> tmp->data;
   p->next = tmp;
   p = tmp;
}
return head;
}

问题1:链表逆置

思想为:head指针不断后移,指针反向即可,代码为:

void reverse(node*& head)
{
if (head != NULL && head->next != NULL)
{
   node* p = head;
   node* q = head->next;
   p->next = NULL;
   while (q->next != NULL)
   {
    head = q->next;
    q->next = p;
    p = q;
    q = head;
   }
   head->next = p;
}
return;
}

问题2:删除不知头结点链表的某个节点
如果单向链表不知道头节点,一个指针指向其中的一个节点,问如何删除这个指针指向的节点?

思想为:把这个节点的下一个节点的值复制给该节点,然后删除下一个节点即可。

问题3:怎么判断链表中是否有环?

思想为:设置两个指针,一个步长为1,另一个步长为2,依次后移,如果相遇且都不为空,则有环。

与这个类似的问题包括:怎么快速检测出一个巨大的链表中的死链?或者如何找出一个单链表的中间节点?

代码为:

bool loop(node* head)
{
bool flag = true;
if (head == NULL)
{
   flag = false;
}
node* one = head;
node* two = head->next;
if (two == NULL)
{
   flag = false;
}
while (one != two)
{
   if (one != NULL)
   {
    one = one->next;
   }
   if (two != NULL)
   {
    two = two->next;
   }
   if (two == NULL)
   {
    break;
   }
   two = two->next;
   if (one == NULL || two == NULL)
   {
    break;
   }
}
if (one == NULL || two == NULL)
{
   flag = false;
}
return flag;
}

问题4:如果一个单向链表,其中有环,怎么找出这个链表循环部分的第一个节点?

思想为:假设该节点在x位置处,假设步长为1的指针和步长为2的指针相遇在x+z处,循环的长度为y,那么2(x+z)-(x+z)=k*y,
那么当一个指针再从开始出后移时,另一个指针从相遇点开始后移时,这两个指针就会在循环开始处相遇。

代码为:

node* findLoopPlace(node* head, unsigned int* place = NULL)
{
//查找循环的位置,place存储位置
if (!loop(head))
{
   return NULL;
}
node* one = head;
node* two = head->next;
unsigned int count = 1;

while (one != two)
{
   one = one->next;
   two = two->next->next;
}
one = head;
while (one != two)
{  
   if (count != 1)
   {
    one = one->next;
   }
   two = two->next;
   count++;
}
*place = count;
return one;
}

问题5:如何查找链表中倒数第k个节点?

思想为:两个指向头结点的指针,一个先向后移动k位,然后两个同时向后面移动直到一个节点到达链尾,前面一个指针的位置就是了。

node* findLastK(node* head,unsigned int k)
{
//查找单链表倒数第k个位置
node* p = head;
unsigned int count = 0;
while (p != NULL)
{
   p = p->next;
   count++;
}
if (count < k)
{
   return NULL;
}
p = head;
node* q = head;
for (unsigned int i = 0; i < k; i++)
{
   p = p->next;
}
while (p != NULL)
{
   q = q->next;
   p = p->next;
}
return q;
}

问题6:编程序判断两个链表是否相交。

这个问题的精彩解说请参见《编程之美》一书之《编程判断两个链表是否相交》,这里就不写了,该书的pdf文档在网上很好下。

文章后面给了两个扩展问题:

(1)如果链表可能有环,如何做判断?

思想为:首先应该明白,只有一个链表有环的情况下是不会相交的,只有都有环或者都没有环的情况下才可能相交,都没有环的情况下最简便的方法就是判断链尾是否相交即可;都有环的情况下,分别找到环上的任一点,一个不动,另一个步进,即可判断是否相交。

(2)如何求相交链表的第一个节点?应该为单链表情况

思想为:方法一是先把任一个链表连成环,即从表尾接到表头,按照问题4的解法;方法二是计算两个链表的长度,而两个链表是按照尾部对齐的,那么从短链表的第一个位置从长链表的第长度差+1的位置依次比较指针值,相等的位置即是。

相关程序包括:单链表中在某个位置插入环以及销毁链表等,代码如下:

void insertCircle(node* head, unsigned int n)
{
//在第n个位置形成环,记head为n=1
node* p = head;
node* q = head;
unsigned int count = 1;

while(p->next != NULL)
{
   p = p->next;
   count++;
}
if (n <= count)
{
   for (unsigned int i = 1; i < n; i++)
   {
    q = q->next;
   }
   p->next = q;
}
return;
}

void destroy(node* head)
{
//销毁链表
if (loop(head))
{
   node *q = findLoopPlace(head);
   while (head != q)
   {
    node* p = head;
    head = head->next;
    delete p;
   }
   head = head->next;
   q->next = NULL;
   destroy(head);
}
else
{
   while (head != NULL)
   {
    node* p = head;
    head = head->next;
    delete p;
   }
}
}

分享到:
评论

相关推荐

    IT常见笔试面试题

    这份名为“IT常见笔试面试题”的资料,无疑是为毕业生和求职者提供了一个宝贵的准备工具。以下是对这些常见题型的详细解读,希望能帮助你更好地理解和应对IT行业的面试挑战。 一、编程能力 在IT面试中,编程能力是...

    链表面试题目总结 全

    在计算机科学领域,链表是一种基本且非常重要的数据结构,它是面试中的常见考察点。链表通常由节点组成,每个节点包含数据部分和指向下一个节点的指针,最后一个节点指向null。链表分为单链表、双链表、循环链表等...

    历年华为笔试面试题目及面试经历汇总

    本资源“历年华为笔试面试题目及面试经历汇总”显然是一个集大成者,包含了华为招聘过程中可能遇到的各种问题和面试者的亲身经验,这对于有意加入华为的求职者来说是一份宝贵的参考资料。 首先,我们要了解华为笔试...

    C语言链表在笔试常考题.docx

    "C语言链表笔试面试常考题总结" 在C语言笔试面试中,链表是一道常考题,以下是两个常见的链表题目及其解决方案。 链表逆置 链表逆置是将链表的节点顺序逆转的过程。例如,原始链表为1-&gt;2-&gt;3-&gt;4-&gt;5,逆置后的链表...

    腾讯笔试面试题汇总

    下面,我们将深入探讨腾讯笔试面试题中可能涵盖的知识点,并提供相关领域的详细解释。 一、编程基础 腾讯的笔试题通常会包含编程基础题,这包括但不限于数据结构(如数组、链表、栈、队列、树、图)、算法(排序、...

    程序设计笔试面试题(汇总所有的程序设计试题)

    本资源"程序设计笔试面试题(汇总所有的程序设计试题)"聚焦于C/C++编程语言,提供了大量的试题和答案,旨在帮助求职者提升在找工作过程中的竞争力。 首先,我们来看“比较有利用价值的华为中兴笔试题.doc”。这份...

    百度笔试面试题目及答案1

    这份"百度笔试面试题目及答案1"资源包含了一份文档(百度题目1.doc)和一个名为merge.cpp的源代码文件,它们分别涵盖了编程技术和面试技巧方面的知识点。 首先,让我们深入探讨编程题目。merge.cpp很可能是一个实现...

    Java常见笔试面试题.doc

    Java作为一门广泛使用的编程语言,其...以上就是Java笔试面试中常出现的一些重要知识点,理解和掌握这些概念对于Java开发者来说至关重要。在面试或准备面试时,深入理解并能够熟练应用这些知识将大大提升你的竞争力。

    java 常见笔试面试题

    Java 常见笔试面试题涵盖了Java编程语言的基础和高级概念,对于求职者来说,熟悉这些知识点至关重要。以下是一些核心知识点的详细说明: 1. **面向对象的特征**: - **抽象**:允许创建类来代表真实世界中的实体,...

    JAVA程序员笔试面试题汇总及答案

    【JAVA程序员笔试面试题汇总及答案】 在Java编程领域,面试和笔试经常涉及到核心概念和技术的理解,这包括面向对象的特性、数据类型的差异、字符串处理、异常处理、Servlet的生命周期以及集合框架等关键知识点。 1...

    Java常见笔试面试题

    Java作为一门广泛使用的编程语言,其面试和笔试题目往往涵盖了...以上是Java面试和笔试中常见的知识点,它们涉及到语言基础、面向对象、异常处理、Web开发等多个领域,是成为一名合格Java开发者必须掌握的核心技能。

    常见Java笔试面试题

    【Java笔试面试题详解】 1. **面向对象的特征** - **抽象**:抽象是对象和类概念的基础,它允许我们将关注点集中在问题的关键部分,忽略不相关的细节。抽象分为过程抽象(方法)和数据抽象(类)。 - **继承**:...

    面试笔试题集锦

    7. **问题解决能力**:面试通常会通过一些实际问题来考察候选人的逻辑思维和问题解决能力,例如,如何优化一段代码,如何设计一个简单的系统等。 8. **编码规范和调试技巧**:良好的编程习惯和有效的调试方法也是...

    2017互联网笔试面试

    总结来说,2017年互联网笔试面试中的知识点广泛且深入,涵盖了技术、理论到实践的多个层面。而网易作为互联网巨头,其面试更注重综合能力的考察,包括技术实力、团队合作、学习能力和创新思维。准备这样的面试,应聘...

    125条常见的java面试笔试题汇总

    综上所述,掌握这些Java基础知识点对于通过面试笔试至关重要。它们不仅覆盖了Java的核心概念,还涉及到了Web开发中Servlet的使用,以及集合框架中不同数据结构的特性。通过不断练习和理解这些知识点,Java开发者可以...

    数据结构笔试面试汇总

    ### 数据结构笔试面试汇总知识点详解 #### 一、如何判断一个单向链表是否有环路? **题目背景:** ...以上是关于数据结构笔试面试中的一些经典题目及解题思路,希望能帮助大家更好地准备相关的笔试和面试。

    JAVA 2程序员笔试面试题汇总及答案

    【JAVA 2程序员笔试面试题汇总及答案】 在Java编程领域,面试和笔试常常涉及到一些核心概念和技术。以下是一些常见的面试题目及其解答: 1. **面向对象的特征** - **抽象**:抽象是将复杂的实体简化为关键特征的...

Global site tag (gtag.js) - Google Analytics