链表问题:反转链表、反转m和n之间的链表、K个一组翻转链表

1、反转链表

       反转一个单链表。

示例:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
struct ListNode {
	int val;
	ListNode *next;
	ListNode(int x) : val(x), next(NULL) {}
};

class Solution {
public:
    ListNode* reverseList(ListNode* head) {  
        ListNode *p1 = 0;
        ListNode *p2 = head;
        ListNode *pt;
        
        while(p2)
        {
            pt = p2->next;
            p2->next = p1;
            
            p1 = p2;
            p2 = pt;
        }
        return p1;
    }
};

/* 递归思想
 
每次取一个节点放在头部,递归该操作


class Solution {
public:
    ListNode* reverseList(ListNode* head) {  
        if(head==0) return 0;
        
        ListNode *p1 = head;
        ListNode *p2 = p1->next;
        ListNode *pt;
        
        while(p2)
        {
            pt = p2->next;
            p2->next = head;
            head = p2;
            
            p1->next = pt;
            p2 = pt;
        }
        return head;
    }
};
*/

2、反转 [m, n] 的链表

       反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。

说明:
       1 ≤ m ≤ n ≤ 链表长度。

示例:

       输入: 1->2->3->4->5->NULL, m = 2, n = 4
       输出: 1->4->3->2->5->NULL

struct ListNode {
	int val;
	ListNode *next;
	ListNode(int x) : val(x), next(NULL) {}
};

ListNode* reverseBetween(ListNode* head, int m, int n) {
	if (m == n) return head;

	//添加头节点
	struct ListNode *newhead = new struct ListNode(0);   //头节点
	newhead->next = head;

	//找到第 m-1 个节点(前段链表尾)、第 m 个节点(中间段链表尾)
	ListNode *pre = newhead;        //第 m-1 个节点
	for (int i = 1; i < m; i++)
	{
		pre = pre->next;
	}
	ListNode *pm = pre->next;       //第 m 个

	//反转链表,次数 n-m 次,最终中间段链表头为 p1, 后段链表头为 p2
	ListNode *p1 = pre->next;      //第 m 个
	ListNode *p2 = p1->next;       //第 m+1 个
	ListNode *pt;
	for (int i = m; i < n; i++)
	{
		pt = p2->next;
		p2->next = p1;

		p1 = p2;
		p2 = pt;
	}
	ListNode *pn = p1;           //第 n 个
	ListNode *after = p2;        //第 n+1 个节点

	//串起三段链表
	pre->next = pn;
	pm->next = after;

	//去掉头节点
	head = newhead->next;
	delete newhead;

	return head;
}

3、K个一组翻转链表

       给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。

       k 是一个正整数,它的值小于或等于链表的长度。

       如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

示例 :

       给定这个链表:1->2->3->4->5

       当 k = 2 时,应当返回: 2->1->4->3->5

       当 k = 3 时,应当返回: 3->2->1->4->5

struct ListNode {
	int val;
	ListNode *next;
	ListNode(int x) : val(x), next(NULL) {}
};

ListNode* reverseKGroup(ListNode* head, int k) {
	if (head == 0) return head;
	if (k <= 1) return head;

	//添加头节点
	ListNode *newhead = new ListNode(0);
	newhead->next = head;

	//统计链表长度
	int cnt = 0;
	while (head)
	{
		cnt++;
		head = head->next;
	}

	//每k个反转一次
	head = newhead;  //前一个元素
	for (int i = 0; i < cnt / k; i++)
	{
		head = reverseK(head, k);   //返回该段最后一个元素
	}

	//去掉头节点
	head = newhead->next;
	delete newhead;

	return head;
}

ListNode* reverseK(ListNode* head, int k) {

	ListNode *pend = head->next;   //保留第二段最终的段尾

	ListNode *p1 = head->next;  //第一个,最终为第二段的段头
	ListNode *p2 = p1->next;    //第二个,最终为第三段的段头
	ListNode *pt;
	for (int i = 1; i < k; i++)      //k-1次反转
	{
		pt = p2->next;
		p2->next = p1;

		p1 = p2;
		p2 = pt;
	}

	head->next->next = p2;     //第二段段尾接第三段段头
	head->next = p1;           //第一段段尾接第二段段头

	return pend;                  //返回第二段最终的段尾
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值