LeetCode 25. K 个一组翻转链表

K 个一组翻转链表

给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。
k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
示例:
k==2

方法一、模拟法

我们需要把链表节点按照 k 个一组分组,所以可以使用一个指针 head 依次指向每组的头节点。这个指针每次向前移动 k 步,直至链表结尾。对于每个分组,我们先判断它的长度是否大于等于 k。若是,我们就翻转这部分链表,否则不需要翻转。
接下来问题转化为:
1.翻转k个子链表,注意首尾连接
2.巧妙构造头结点,方便操作链表

Swift

//k个一组翻转链表
    func reverseKGroup(_ head: ListNode?, _ k: Int) -> ListNode? {
        let dummyNode = ListNode(0)
        dummyNode.next = head
        var p:ListNode? = dummyNode
        
        var head = head
        while head != nil {
            var tail:ListNode? = p
            
            for _ in 0..<k {
                tail = tail?.next
                guard tail != nil else {return dummyNode.next}
            }
            
            let nex = tail?.next
            let result = reverseListNode(head, tail)
            head = result.0
            tail = result.1
            
            var res = head
            while let result = res {
                print(result.val)
                res = result.next
            }
            
            //链接反转后的链表
            p?.next = head
            tail?.next = nex
            p = tail
            head = nex
        }
        return dummyNode.next
    }

//翻转链表,返回新的头和尾
    func reverseListNode(_ head:ListNode?, _ tail:ListNode?) -> (ListNode?, ListNode?) {
        //记录未反转时最后一个元素的下一个,反转后保持链接状态
        var nextNode = tail?.next
        var p = head
        
        while nextNode !== tail {
            let nex = p?.next
            p?.next = nextNode
            nextNode = p
            p = nex
        }
        
        return (tail, head)
    }

OC

- (ListNodeOC *)reverseKGroup:(ListNodeOC *)head
                      inteval:(NSInteger)k {
    //创建哑巴节点
    ListNodeOC *dummyNode = [[ListNodeOC alloc] initWithVal:0];
    dummyNode.next = head;
    ListNodeOC *p = dummyNode;
    
    while (head != nil) {
        ListNodeOC *tail = p;
        
        for (NSInteger i=0; i<k; i++) {
            tail = tail.next;
            if (!tail) {
                return dummyNode.next;
            }
        }
        
        ListNodeOC *pre = tail.next;
        
        NSArray *result = [self reverseListNode:head tail:tail];
        head = result.firstObject;
        tail = result.lastObject;
        
        //链接首尾顺序
        p.next = head;
        tail.next = pre;
        p = tail;
        head = pre;
    }
    return dummyNode.next;
}

- (NSArray *)reverseListNode:(ListNodeOC *)head tail:(ListNodeOC *)tail {
    ListNodeOC *previ = tail.next;
    ListNodeOC *p = head;
    
    while (previ != tail) {
        ListNodeOC *nex = p.next;
        p.next = previ;
        previ = p;
        p = nex;
    }
    
    return @[tail, head];
}
  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jarlen John

谢谢你给我一杯咖啡的温暖

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值