链表面试题(一):反转链表的算法实现

关于链表的考察

  链表是面试里面经常涉及到的考点,因为链表的结构相比于Hashmap、Hashtable、Concurrenthashmap或者图等数据结构简单许多,对于后者更多面试的侧重点在于其底层实现。比如Hashmap中Entry<k,v>等操作、如何扩容、容量的设定等。链表的考察更侧重于代码的书写和思路的形成。虽然说,链表的结构简单,但是涉及到指针的操作,容易引申出一些挑战性的考题,其中也牵涉到诸多小的细节的考虑,更能看出代码书写的能力和功底。

面试题:反转链表

题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。

  下面给出了链表结点的定义:

1 struct ListNode {
2     int val;
3     struct ListNode *next;
4     ListNode(int x) :
5             val(x), next(NULL) {
6     }
7 };

分析:

  链表前后元素的关联就是通过指针实现的,每个链表都有一个next指针指向下一个结点,末尾的节点的next域则置NULL;

  反转链表就是要求修改指针的指向。下面的图就是反转前和反转后的效果。

反转前:

反转后:

下面来谈谈如何对链表进行反转。

  假设我们现在正在对结点v进行反转操作,即原来结点u的next域指向v(图中已经调整完毕,现在指向前一个结点),v的next域指向w。现在要做的是将v的next域指向u。从图中我们可以看出,当把v的next指针指向u的同时,原先指向的w就已经无法被正常的访问到了,为了避免“断链”,我们必须在指针更改指向之前,保存修改结点的下一结点。同时我们也必须存储上一个结点,因为next域即将修改指向该结点。因此定义三个指针,分别指向当前遍历的结点,前一个结点和后一个结点。

算法实现如下:

 1 ListNode* ReverseList(ListNode* pHead)
 2 {
 3     ListNode* pReversedHead = NULL;
 4     ListNode* pNode = pHead;
 5     ListNode* pPrev = NULL;
 6     while(pNode != NULL)
 7     {
 8         ListNode* pNext = pNode->m_pNext;
 9
10         if(pNext == NULL)
11             pReversedHead = pNode;
12
13         pNode->m_pNext = pPrev;
14
15         pPrev = pNode;
16         pNode = pNext;
17     }
18
19     return pReversedHead;
20 }

  当然,上面的源码中用到了四个指针,看完源码就会发现和上面分析的原理并没有相悖。或者下面这样也是可以的,两者的思路一致,没有差别。只不过下面的代码必须注意一点,跳出while循环的时候,最后一个结点的next域别忘记指向前一个结点,否则就会导致“断链”。

 1     ListNode* ReverseList(ListNode* pHead) {
 2         ListNode *root=pHead;
 3         ListNode *pre=NULL;
 4         ListNode *next=NULL;
 5         if(pHead==NULL) return NULL;
 6     while(root->next){
 7         next=root->next;
 8         root->next=pre;
 9         pre=root;
10         root=next;
11     }
12         root->next=pre;
13         return root;
14     } 
时间: 2024-12-15 01:38:19

链表面试题(一):反转链表的算法实现的相关文章

【剑指Offer】面试题24. 反转链表

题目 定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点. 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 限制: 0 <= 节点个数 <= 5000 注意:本题同[LeetCode]206. 反转链表 思路一:反转链表元素 取出链表中元素放入vector中,然后将vector中元素逆向存入链表中. 遍历链表,用vector存放数组元素. 再次遍历链表,从ve

链表(4)----反转链表

1.链表结构定义 typedef struct ListElement_t_ { void *data; struct ListElement_t_ *next; } ListElement_t; typedef struct List_t_{ int size; int capacity; ListElement_t *head; ListElement_t *tail; } List_t; 2.反转链表实现 int ReverseList( List_t *list) { if( list

LeetCode 面试题24. 反转链表

题目链接:https://leetcode-cn.com/problems/fan-zhuan-lian-biao-lcof/ 定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点. 示例: 输入: 1->2->3->4->5->NULL输出: 5->4->3->2->1->NULL 限制: 0 <= 节点个数 <= 5000 1 /** 2 * Definition for singly-linked list.

数据结构与算法(c++)——反转链表

算法概述:要求实现将一条单向链表反转并考虑时间复杂度. 算法分析: 数组法(略): 将列表元素逐个保存进数组,之后再逆向重建列表 点评:实现逻辑最简单,需要额外的内存开销. 移动指针: 通过三个指针逐个从链表头开始逐一反转链表元素的指针 点评:不需要额外的内存开销,会改变原始链表. 递归: 以递归的方式首先找到链表尾部,再逐一反转指针 点评:不需要额外的内存开销,不会改变原始链表. 算法实现: 构建链表结构 /* 节点结构 */ struct NODE { int data; struct NO

【LeetCode】206. 反转链表

题目 反转一个单链表. 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 进阶: 你可以迭代或递归地反转链表.你能否用两种方法解决这道题? 注意:本题同[剑指Offer]面试题24. 反转链表 思路一:反转链表元素 取出链表中元素放入vector中,然后将vector中元素逆向存入链表中. 遍历链表,用vector存放数组元素. 再次遍历链表,从vector尾部读取元素依次放入链表中. 代码

链表——按k个结点一组来反转链表

题目:按k个结点一组来反转链表 思路: 运用反转链表的通法reverse,对链表进行循环,当计数长度k不时,指针继续前进:当计数长度到达k时,将该组首尾节点first和node作为参数传入翻转函数reverse进行翻转,然后重新拼接到原链表中.直至到达链表末尾. 代码如下: /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x)

笔试算法题(13):反转链表 &amp; 左旋转字符串

出题:反转链表(递归和非递归解法): 分析:有递归跟非递归实现,注意对原始链表头节点的处理,因为其他节点都指向下一个节点,其需要指向NULL: 解题: 1 struct Node { 2 int v; 3 Node *next; 4 }; 5 Node* NonRecursiveListReverse(Node *head) { 6 if(head == NULL) return NULL; 7 Node *previous=NULL, *current=head, *temp=NULL; 8

反转链表算法Java实现

之前遇到反转链表的算法,比较晦涩难解,但其实挺简单的. 目标:将一个顺序链表反转. 思路:用三个辅助节点,每次实现一个节点的指向反转,即他的后继变为他的前驱. 三个辅助节点: p  q  r  按顺序分别指向 节点0,1,2, 然后一次次移动,指向1,2,3 : 2,3,4...... 算法分为三部分: 第一部分:初始化部分: q是中心节点,是每次反转的节点,于是q是由函数参数传入的,前面的节点p一个是null,后面的节点r是q的后继节点q.next 第二部分:循环部分 分为两个操作: 1.反转

[算法练习] 反转链表

题目说明: 输入一个链表的头结点,反转该链表,并返回反转后链表的头结点.链表结点定义如下:struct ListNode{     int m_nKey;     ListNode* m_pNext;}; 程序代码: #include <gtest/gtest.h> #include <vector> using namespace std; struct ListNode { int m_nKey; ListNode* m_pNext; }; ListNode* ReverseL