[C++刷题之旅]反转链表

心有所向,日复一日,必有精进

专栏:C++刷题之旅

作者:早凉


目录

题目一:反转链表 

【题目链接】

【题目描述】

【解题思路】

【代码实现】 

进阶:链表中指定区间反转

【题目链接】 

【题目描述】​编辑

【解题思路】 

【代码实现】  


题目一:反转链表 

【题目链接】

题目反转链表_牛客题霸_牛客网

【题目描述】

给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头。

数据范围: 0≤n≤1000

要求:空间复杂度 O(1) ,时间复杂度 O(n) 。

如当输入链表{1,2,3}时,

经反转后,原链表变为{3,2,1},所以对应的输出为{3,2,1}。

以上转换过程如下图所示:

[C++刷题之旅]反转链表_第1张图片

【解题思路】

反转单链表,如果创建一个新的链表,遍历旧链表头插是可以解决问题,但是题目中要求了O(1)的空间复杂度,这就意味着,我们不能在开辟额外空间;我们可以利用三个指针来解决这个问题;为什么用三个指针,就是为了让当前指针既能把前面一个结点找到链接上,也能让当前指针找到之前的后继结点;

[C++刷题之旅]反转链表_第2张图片

【代码实现】 

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
		ListNode*pre,*cur,*nex;
		pre = nullptr;
		cur = nex = pHead;
		while(cur)//注意终止条件
		{
			nex = cur->next;
			cur->next = pre;
			pre = cur;
			cur = nex;
		}
		return pre;//注意头结点
    }
};

 其实这样也可以看成在新生成一个链表进行头插,这也可以是一种新思路,具体如下图:

[C++刷题之旅]反转链表_第3张图片

 当然我们还可以使用栈结构来解决问题。

 接下来是进阶:

进阶:链表中指定区间反转

【题目链接】 

 
链表内指定区间反转_牛客题霸_牛客网
 【题目链接】​​​​​​​

【题目描述】[C++刷题之旅]反转链表_第4张图片

【解题思路】 

 这道题和上一道题是一样的,我们只需要找到一个指定区间,指定区间的使用第一题的反转就好了,然后记录下区间前后指针链接起来就好啦;这道题可以增加一个虚拟头结点,这样反转首结点会方便一点,反转后返回虚拟头结点的下一个结点;

【代码实现】  

    ListNode* reverseBetween(ListNode* head, int m, int n) {
          //加个表头
        ListNode* res = new ListNode(-1);
        res->next = head;
        //前序节点
        ListNode* pre = res;
        //当前节点
        ListNode* cur = head;
        //找到m
        for(int i = 1; i < m; i++){
            pre = cur;
            cur = cur->next;
        }
        //从m反转到n
        for(int i = m; i < n; i++){
            ListNode* temp = cur->next;
            cur->next = temp->next; 
            temp->next = pre->next;
            pre->next = temp;
        }
        //返回去掉表头
        return res->next;
    }

你可能感兴趣的:(C++刷题之旅,链表,c++,数据结构)