【每日一题】反转链表

前言

工作之后每天都是CRUD,CRUD多了脑袋也跟着生锈,为了拯救一下自个贫瘠的脑瓜子,也为了以后的大厂梦,决定每日从牛客网上找个题目来练练手,刚开始先挑个简单的来提升一下自信心。

正文

反转链表是牛客网中上周最热且比较简单题目,就它了,开搞。

题目描述

反转链表:传入一个链表的表头,反转链表后返回新链表的表头。
链表节点结构如下:

class ListNode{
        Object value;
        ListNode next;
        public ListNode(Object value){
            this.value = value;
        }
    }
输入样例

{1,2,3}

输出样例

{3,2,1}

分析

题目很简单,用我们大脑思考就是遍历每一个节点将当前节点的next指向它的上一个节点即可。
用代码处理的话我们需要注意的是防止把当前节点的next指向它前一个后会丢失对它原next引用的问题。
此时我们就需要引入一些辅助变量帮我们记录前一个节点、当前节点、下一个节点。伪代码如下:

		// head是出入的链表头
		// 初始用头节点做上一个节点
        ListNode preNode = head;
        // 头节点的下一个节点为当前节点
        ListNode currentNode = preNode.next;
        // 当前节点的下一个节点做下一个节点
        ListNode nextNode = currentNode.next;
        // 初始时候直接将当前节点的下一个指向它的前一个节点,接下来遍历链表从next节点开始
        currentNode.next = preNode;
        // 一定要把头节点的下一个指针指向null,因为原本head.next指向currentNode,上一步又相当于把currentNode.next = head。如果不把head.next置为null会出现head和currentNode的循环指向了。
        head.next = null;

接下来我们分析遍历时我们需要做什么事情:
1、将currenNode和nextNode的链接关系反转
2、将nextNode赋值给currentNode,将nextNode.next赋值给nextNode
代码实现如下:

while (nextNode!=null){
			// 辅助变量,防止nextNode.next的引用丢失
            ListNode newNext = nextNode.next;
            // 反转currentNode和nextNode的链接关系
            nextNode.next = currentNode;
            // 重置currentNode
            currentNode = nextNode;
            // 重置nextNode
            nextNode = newNext;
        }

至此核心代码已经完成,但是还需要注意一点就是如果head的长度为0和1时需要做以下特殊处理,不然容易出现空指针异常。
完整代码如下:

    public static ListNode reverseList(ListNode head){
        // 当传入的链表为空就返回null
        if(head==null){
            return null;
        }
        ListNode preNode = head;
        ListNode currentNode = preNode.next;
        // 如果链表只有一个元素,怎么反转都还是这个元素,直接返回即可
        if(currentNode==null){
            return head;
        }
        ListNode nextNode = currentNode.next;
        // 初始时候直接将当前节点的下一个指向它的前一个节点,接下来遍历链表从next节点开始
        currentNode.next = preNode;
        // 一定要把头节点的下一个指针指向null,因为原本head.next指向currentNode,上一步又相当于把currentNode.next = head。如果不把head.next置为null会出现head和currentNode的循环指向了。
        head.next = null;
        while (nextNode!=null){
            // 辅助变量,防止nextNode.next的引用丢失
            ListNode newNext = nextNode.next;
            // 反转currentNode和nextNode的链接关系
            nextNode.next = currentNode;
            // 重置currentNode
            currentNode = nextNode;
            // 重置nextNode
            nextNode = newNext;
        }
        return currentNode;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用C++实现一个单向链表的代码: ```c++ #include <iostream> using namespace std; struct ListNode { int val; ListNode* next; ListNode(int x) : val(x), next(NULL) {} }; ListNode* reverseList(ListNode* head) { ListNode* prev = NULL; ListNode* curr = head; while (curr != NULL) { ListNode* next = curr->next; curr->next = prev; prev = curr; curr = next; } return prev; } int main() { // 创建链表 1 -> 2 -> 3 -> 4 -> 5 ListNode* head = new ListNode(1); head->next = new ListNode(2); head->next->next = new ListNode(3); head->next->next->next = new ListNode(4); head->next->next->next->next = new ListNode(5); // 链表 ListNode* newHead = reverseList(head); // 输出后的链表 while (newHead != NULL) { cout << newHead->val << " "; newHead = newHead->next; } cout << endl; return 0; } ``` 在上面的代码中,我们首先定义了一个链表节点的结构体 `ListNode`,包括一个值域 `val` 和一个指向下一个节点的指针 `next`。然后,我们定义了一个 `reverseList()` 函数来链表。函数中使用了三个指针,分别为 `prev`、`curr` 和 `next`,其中 `prev` 表示当前节点的前一个节点,`curr` 表示当前节点,`next` 表示当前节点的下一个节点。 在 `while` 循环中,我们首先将 `curr` 的下一个节点保存到 `next` 中,然后将 `curr` 的 `next` 指针指向 `prev`,最后将 `prev` 指向 `curr`,`curr` 指向 `next`。这样,我们就完成了一次节点的。循环直到 `curr` 为 `NULL`,即链表处理完毕,返回 `prev`,即为后的头节点。 在 `main()` 函数中,我们创建了一个链表 `1 -> 2 -> 3 -> 4 -> 5`,然后调用 `reverseList()` 函数来链表。最后,我们输出后的链表。输出结果为 `5 4 3 2 1`。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值