面试算法-链表-反转链表(golang、c++)

目录

1、题目

2、解题思路

[2.1 遍历、迭代](#2.1 遍历、迭代)

[2.2 递归](#2.2 递归)

3、源代码

[3.1 c++](#3.1 c++)

[3.2 golang](#3.2 golang)

4、复杂度分析

[4.1 遍历、迭代法](#4.1 遍历、迭代法)

[4.2 迭代法](#4.2 迭代法)

1、题目

链表是一种常用的数据结构,链表的特点是插入、删除节点的效率非常高,因为他不需要移动其他任何元素,只需要改变节点的指向接口,但是他的缺点也很明显,访问任意节点,都需要从链表头遍历,时间复杂度O(n)。

题目:给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例一:

复制代码
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

示例二:

复制代码
输入:head = []
输出:[]

2、解题思路

2.1 遍历、迭代

这种方法,说的直白点,就是硬拧,把链表指向掉头。

解题过程:

  1. 从头结点开始,遍历每个节点。
  2. 保存当前节点的下一个节点cur_next。
  3. 将当前节点的next指向前一个节点pre,
  4. 将pre指向当前节点,将当前节点执行cur_next。
  5. 返回新链表头结点。

2.2 递归

递归的本质在于反向工作,假设有链表:

n1->n2-> n3->......->nk->nk+1->......->nm.

nk之后的链表已经逆序完成,现在只需要将nk+1节点的next指向nk即可,为了避免nk、nk+1两个节点互指,也需要将nk的next指向null。

3、源代码

3.1 c++

  • 遍历、迭代:
cpp 复制代码
struct ListNode
{
    int data;
    ListNode *next;
};
// 反转链表-遍历、迭代
ListNode *reverseList(ListNode *head)
{
    ListNode *pre = nullptr;
    ListNode *cur = head;
    if (head == nullptr || head->next == nullptr)
    {
        return head;
    }
    while (cur)
    {
        ListNode *next = cur->next;
        cur->next = pre;
        pre = cur;
        cur = next;
    }
    return pre;
}
  • 递归法:
cpp 复制代码
// 反转链表-递归
ListNode *reverseList2(ListNode *head)
{
    ListNode *cur = nullptr;
    if (head == nullptr || head->next == nullptr)
    {
        return head;
    }
    cur = reverseList2(head->next);
    head->next->next = head;
    head->next = nullptr;
    return cur;
}

3.2 golang

  • 遍历法:
Go 复制代码
func Reverse(head *ListNode) *ListNode {
	var pre, next *ListNode
	cur := head
	for cur != nil {
		next = cur.Next
		cur.Next = pre
		pre = cur
		cur = next
	}
	return pre
}
  • 递归法:
Go 复制代码
// 反转链表--递归
func Reverse2(head *ListNode) *ListNode {
	if head == nil || head.Next == nil {
		return head
	}
	newNode := Reverse2(head.Next)
	head.Next.Next = head
	head.Next = nil // 防止循环
	return newNode
}

4、复杂度分析

4.1 遍历、迭代法

时间复杂度:遍历法,需要遍历整个链表,因此时间复杂度为:O(n),n为链表长度。

空间复杂度:程序运行整个过程中,没有申请新的内存,因此空间复杂度为:O(1)。

4.2 迭代法

时间复杂度:递归算法仍然需要遍历整个链表,因此时间复杂度为:O(n),n为链表长度。

空间复杂度:递归需要申请栈空间来保存函数调用关系,因此空间复杂度为:O(n),最多n层调用。

相关推荐
Joeysoda25 分钟前
Java数据结构 (从0构建链表(LinkedList))
java·linux·开发语言·数据结构·windows·链表·1024程序员节
天乐敲代码29 分钟前
JAVASE入门九脚-集合框架ArrayList,LinkedList,HashSet,TreeSet,迭代
java·开发语言·算法
比特在路上29 分钟前
ListOJ14:环形链表II(寻找环的入口点)
数据结构·链表
十年一梦实验室33 分钟前
【Eigen教程】矩阵、数组和向量类(二)
线性代数·算法·矩阵
Kent_J_Truman34 分钟前
【子矩阵——优先队列】
算法
快手技术2 小时前
KwaiCoder-23BA4-v1:以 1/30 的成本训练全尺寸 SOTA 代码续写大模型
算法·机器学习·开源
一只码代码的章鱼2 小时前
粒子群算法 笔记 数学建模
笔记·算法·数学建模·逻辑回归
小小小小关同学2 小时前
【JVM】垃圾收集器详解
java·jvm·算法
圆圆滚滚小企鹅。2 小时前
刷题笔记 贪心算法-1 贪心算法理论基础
笔记·算法·leetcode·贪心算法
Kacey Huang3 小时前
YOLOv1、YOLOv2、YOLOv3目标检测算法原理与实战第十三天|YOLOv3实战、安装Typora
人工智能·算法·yolo·目标检测·计算机视觉