力扣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; } }
递归思想
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; } }