力扣206题、92题、25题(反转链表)牛客1,2

206、反转链表

基本思想:

双指针迭代

具体实现:

1、申请两个指针,一个叫pre,一个叫cur

cur代表的是当前节点,pre是cur的前一个节点

刚开始,pre指向null,cur是第一个节点

然后cur和pre共同往后走,

cur每走完一步就要指向pre

cur变成none了,就迭代完了

2、cur如何往后走

tmp记录cur当前节点的下一个节点

tmp = cur.next

cur = tmp

代码:

/**
 * 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 reverseList(ListNode head) {
        ListNode prev = null;
        ListNode cur = head;
        ListNode temp = null;
        while (cur != null){
temp
= cur.next;//记录当前节点的下一个节点 cur.next = prev;//当前节点指向pre prev = cur;//pre和cur后移一位 cur = temp; } return prev; } }

 

#include<iostream>
using namespace std;
struct ListNode
{
    int val;
    ListNode* next;
};
ListNode* reverseList(ListNode* pHead)
{
    ListNode* pre = NULL;
    ListNode* cur = pHead;
    while (cur != NULL) {
        ListNode* temp = cur->next;
        cur->next = pre;
        pre = cur;
        cur = temp;
    }
    return pre;
}
void printList(ListNode* head) 
{
    while(head) 
    {
        cout << head->val;
        head = head->next;
        if (head)
            cout << "->";
    }
    cout << endl;
}
int main()
{
    ListNode* head = NULL;
    ListNode* cur = NULL;
    for (int i = 0; i <= 5; i++)
    {
        ListNode* node = new ListNode;
        node->val = i;
        node->next = NULL;
        if (head == NULL)
        {
            head = node;
            cur = node;
        } 
        else 
        {
            cur->next = node;
            cur = node;
        }
    }
    printList(head);
    printList(reverseList(head));
    return 0;
}

 

 

递归法

1.递归参数以及返回值

递归参数:前后指针

返回值:新链表的头结点

2.确认终止条件:

cur指针(走的快的指针)指向null,递归终止

3.单层递归逻辑

和上一种方法的思想一致

class Solution {
    public ListNode reverseList(ListNode head) {
        return reverse(null,head);
    }
    private ListNode reverse(ListNode prev, ListNode cur){
        if (cur == null){
            return prev;
        }
        ListNode temp = null;
       
        temp = cur.next;
        cur.next = prev;
//prev
= cur; //cur = temp; return reverse(cur, temp); } }

 

 

92、反转链表的一部分

基本思想:

将需要反转的的地方先反转,

然后与原来的链表拼接起来

具体实现:

left是需要反转的地方的第一个节点

right是最后一个

1、将pre放到left的前面一个节点

2、将curr放到right后面一个节点

3、切断连接

4、将子链表反转,用单调的方式

5、接回到原来的链表中

代码:

class Solution {
    public ListNode reverseBetween(ListNode head, int left, int right) {
        // 因为头节点有可能发生变化,使用虚拟头节点可以避免复杂的分类讨论
        ListNode dummyNode = new ListNode(-1);
        dummyNode.next = head;

        ListNode pre = dummyNode;
        // 第 1 步:从虚拟头节点走 left - 1 步,来到 left 节点的前一个节点
        // 建议写在 for 循环里,语义清晰
        for (int i = 0; i < left - 1; i++) {
            pre = pre.next;
        }

        // 第 2 步:从 pre 再走 right - left + 1 步,来到 right 节点
        ListNode rightNode = pre;
        for (int i = left; i < right + 1 ; i++) {
            rightNode = rightNode.next;
        }

        // 第 3 步:切断出一个子链表(截取链表)
        ListNode leftNode = pre.next;
        ListNode curr = rightNode.next;

        // 注意:切断链接
        pre.next = null;
        rightNode.next = null;

        // 第 4 步:同第 206 题,反转链表的子区间
        reverseLinkedList(leftNode);

        // 第 5 步:接回到原来的链表中
        pre.next = rightNode;
        leftNode.next = curr;
        return dummyNode.next;
    }

    private void reverseLinkedList(ListNode head) {
        // 也可以使用递归反转一个链表
        ListNode pre = null;
        ListNode cur = head;

        while (cur != null) {
            ListNode next = cur.next;
            cur.next = pre;
            pre = cur;
            cur = next;
        }
    }
}

 

 

 

public class Solution {
    /**
     * 
     * @param head ListNode类 
     * @param m int整型 
     * @param n int整型 
     * @return ListNode类
     */
    public ListNode reverseBetween (ListNode head, int m, int n) {
        ListNode dummyNode = new ListNode(-1);
        dummyNode.next = head;
        ListNode pre = dummyNode;
        ListNode cur = pre.next;
        for (int i = 1; i < m; i++) {
            pre = cur;
            cur = cur.next;
        }
        for (int i = m; i < n; i++) {
            ListNode tmp = cur.next;
            cur.next = tmp.next;
            tmp.next = pre.next;
            pre.next = tmp;
        }
        return dummyNode.next;
    }
}

 

 

递归思想

https://leetcode-cn.com/problems/reverse-linked-list-ii/solution/yi-bu-yi-bu-jiao-ni-ru-he-yong-di-gui-si-lowt/

25、k个一组反转链表

基本思想:

递归+迭代

1、递归:把前k个节点反转,后面的节点也是一条链表,

而且规模比原来链表小,就是子问题

子问题与原问题的结构相同

2、迭代:同206题反转链表

具体实现:

1、先反转以head开头的k个元素

2、将第k+1个元素作为head再递归调用

3、将上述两个过程的结果连接起来

就是反转完后的链表的尾结点连上下一次递归完后的新头节点

反转完后的链表的尾结点是原链表的头结点

代码:

class Solution:
    def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
        if head is None:
            return None
        a = b = head
        for _ in range(k):
            if b is None:
                return head
            b = b.next
        
        def reverse(a,b):
            pre = None
            cur = a
            next = a
            while cur != b:
                next = cur.next
                cur.next = pre
                pre = cur
                cur = next
            return pre

        newhead = reverse(a,b)
        a.next = self.reverseKGroup(b,k)
        return newhead

 

import java.util.*;
class ListNode{
    int val;
    ListNode next = null;
    ListNode(int val){
        this.val = val;
    }
}
public class reverseKlist{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        while (sc.hasNextLine()){
            String[] str = sc.nextLine().split(" ");
            int k = Integer.valueOf(sc.nextLine());
            ListNode pre = new ListNode(Integer.valueOf(str[0]));
            ListNode head = pre;
            for (int i=1;i<str.length;i++){
                ListNode node = new ListNode(Integer.valueOf(str[i]));
                pre.next = node;
                pre = node;
            }
            pre.next = null;
            head = reverse(head, k);
            while (head != null){
                System.out.print(head.val+" ");
                head = head.next;
            }
        }
    }
    public static ListNode reverse(ListNode head, int k){
        ListNode tmp = head;
        for (int i=1;i<k&&tmp!=null;i++)
            tmp = tmp.next;
        if (tmp == null) return head;
        ListNode Lhead = tmp.next;
        tmp.next = null;
        ListNode newHead = revK(head);
        ListNode newLHead = reverse(Lhead, k);
        head.next = newLHead;
        return newHead;
    }
    public static ListNode revK(ListNode head){
        ListNode tmp = null, pre = null;
        while (head != null){
            tmp = head.next;
            head.next = pre;
            pre = head;
            head = tmp;
        }
        return pre;
    }
}

 

posted @ 2021-03-07 22:08  最近饭吃的很多  阅读(85)  评论(0编辑  收藏  举报