链表的翻转问题

背景

链表翻转考察的其实是对多个指针的处理的细节,主要是考察代码而不是算法。

基本问题是两个一组进行两两的链表翻转

进阶问题是K 个一组翻转链表

解题思路:

此类问题直接按题意来进行分析,也就是先对链表进行切割,分为若干个长度为k的子链表,然后,在链表内部进行节点的顺序调整。需要注意的是,所谓的节点交换,交换的实际是节点的指针,而不是节点的值,如果仅仅是将节点值进行交换,考察的就不是链表了。

基本问题

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

示例 1:

输入:head = [1,2,3,4]
输出:[2,1,4,3]

 示例 2:

输入:head = []
输出:[]

示例 3

输入:head = [1]
输出:[1]

提示:

链表中节点的数目在范围 [0, 100] 内
0 <= Node.val <= 100

解题思路:

将整个链表分割为两个一组的小片段

参数说明:

curHead 当前结果链表的头节点

prevTail 前一段链表的结尾

n1 本段的第一个节点

n2 本段的第二个节点

n3 下一段的第一个节点

开始时候

 

 

 

 Java代码


/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode swapPairs(ListNode head) {
        if(head==null){
            return head;
        }
        ListNode curHead = head;
        ListNode prevTail=null;
        ListNode n1 = head;
        ListNode n2 = head.next;
        ListNode n3;
        while(n2!=null){
            n3 = n2.next;
            n2.next = n1;
            n1.next = n3;
            if(curHead==head){
                curHead = n2;
            }
            if(prevTail!=null){
                prevTail.next = n2;
            }
            prevTail = n1;
            n1 = n3;
            if(n3==null){
                break;
            }
            n2 = n3.next;
        }
        return curHead;
    }
}

Python代码

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution(object):
    def swapPairs(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if head is None:
            return head
        curHead = head
        prevTail = None
        n1 = head
        n2 = head.next
        while n2 is not None:
            n3 = n2.next
            n2.next = n1
            n1.next = n3
            if curHead == head:
                curHead = n2
            if prevTail is not None:
                prevTail.next = n2
            prevTail = n1
            n1 = n3
            if n3 is None:
                break
            n2 = n3.next
        return curHead

扩展问题

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

k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

示例 1:

输入:head = [1,2,3,4,5], k = 2
输出:[2,1,4,3,5]

 示例 2:

输入:head = [1,2,3,4,5], k = 3
输出:[3,2,1,4,5]
提示:
链表中的节点数目为 n
1 <= k <= n <= 5000
0 <= Node.val <= 1000

解题思路:

将整个链表分割成若干个长度为k的子链表来出来

参数设置:

curHead 当前正在处理的子链表的头节点

curTail 当前正常处理的子链表的尾部节点

thisHead 最终需要返回的链表的头节点

lastTail 上一个处理的链表的尾部节点

下图为各个指针的初始位置 

首先找到当前需要处理的子链表的尾节点,此节点通过重当前节点往下数k-1个节点获得。

如果在遍历过程中,走到了空节点,说明链表已经处理完,直接把当前的头节点返回即可。

下图为处理第一段子链表时候,找到子链表的尾节点过程:

到当前步骤为止,我们已经控制了子链表的头和尾,我们现在要做的事处理子链表中间的情况。

设置一些中间指针:

nextHead 下一个子链表的头节点

n1 设置为当前处理段的头部

n2 为n1的下一个位置

n3 为n2的下一个位置

 

 

如果thisHead == head 说明我们从来没更改过这个值,我们将其设置为curTail

如果lastTail有值,说明这不是第一段子链表,将上一段的尾巴连接到这一段的头

 

到此为止,一段子链表已经处理好了,我们开始循环往复处理下一段 

Java代码:


/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        if(k==1){
            return head;
        }
        ListNode curHead = head;
        ListNode curTail = head;
        ListNode thisHead = head;
        ListNode lastTail = null;
        while(curHead!=null){
            for(int i=0; i<k-1; i++){
                if(curTail!=null){
                    curTail = curTail.next;
                }else{
                    return thisHead;
                }
            }
            if(curTail==null){
                return thisHead;
            }
            ListNode nextHead = curTail.next;
            curTail.next = null;
            ListNode n1 = curHead;
            ListNode n2 = curHead.next;
            n1.next = null;
            ListNode n3;
            while(n2!=null){
                n3 = n2.next;
                n2.next = n1;
                n1 = n2;
                n2 = n3;
            }
            curHead.next = nextHead;
            if(thisHead==head){
                thisHead = curTail;
            }
            if(lastTail!=null){
                lastTail.next = curTail;
            }
            lastTail = curHead;
            curHead = nextHead;
            curTail = nextHead;
        }
        return thisHead;
    }
}

Python代码

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution(object):
    def reverseKGroup(self, head, k):
        """
        :type head: ListNode
        :type k: int
        :rtype: ListNode
        """
        if k == 1:
            return head
        curHead = head
        curTail = head
        thisHead = head
        lastTail = None
        while curHead is not None:
            for i in range(k-1):
                if curTail is not None:
                    curTail = curTail.next
                else:
                    return thisHead
            if curTail is None:
                return thisHead
            nextHead = curTail.next
            curTail.next = None
            n1 = curHead
            n2 = curHead.next
            n1.next = None
            while n2 is not None:
                n3 = n2.next
                n2.next = n1
                n1 = n2
                n2 = n3
            curHead.next = nextHead
            if thisHead == head:
                thisHead = curTail
            if lastTail is not None:
                lastTail.next = curTail
            lastTail = curHead
            curHead = nextHead
            curTail = nextHead
        return thisHead

  • 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* nextTemp = curr->next; curr->next = prev; prev = curr; curr = nextTemp; } return prev; } int main() { ListNode* head = new ListNode(1); head->next = new ListNode(2); head->next->next = new ListNode(3); head->next->next->next = new ListNode(4); cout << "Original list: "; ListNode* curr = head; while (curr != NULL) { cout << curr->val << " "; curr = curr->next; } cout << endl; head = reverseList(head); cout << "Reversed list: "; curr = head; while (curr != NULL) { cout << curr->val << " "; curr = curr->next; } cout << endl; return 0; } ``` 在上面的代码中,我们定义了一个ListNode结构体表示链表节点,包含一个整数值和一个指向下一个节点的指针。reverseList()函数实现了链表翻转操作,它使用了三个指针prev、curr和nextTemp。prev指向上一个节点,curr指向当前节点,nextTemp指向下一个节点。在while循环中,我们不断将当前节点的指针指向上一个节点,然后更新三个指针的值以便继续循环。最后返回prev作为新链表的头节点。在main函数中,我们创建了一个包含四个节点链表,并输出原始链表翻转后的链表
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值