回顾一下上一节的链表反转
1.虚拟结点反转法
2.直接反转法
区域反转问题
解决思路:
1.选定好区间,直接用反转法反转
2.走到指定的区域直接反转
穿针引线法
public ListNode reverseBetween(ListNode head, int left, int right) { // 因为头节点有可能发生变化,使用虚拟头节点可以避免复杂的分类讨论 ListNode dummyNode = new ListNode(-1); dummyNode.next = head; ListNode pre = dummyNode;//错误的地方,写成了head // 第 1 步:从虚拟头节点走 left - 1 步,来到 left 节点的前一个节点 // 建议写在 for 循环里,语义清晰 for (int i = 0; i < left - 1; i++) {//错误的地方,i=1 pre = pre.next; } // 第 2 步:从 pre 再走 right - left + 1 步,来到 right 节点 ListNode rightNode = pre; for (int i = 0; i < right - left + 1; i++) {//错误的地方,i=1 rightNode = rightNode.next; } // 第 3 步:切出一个子链表 ListNode leftNode = pre.next; ListNode succ = rightNode.next; // 思考一下,如果这里不设置next为null会怎么样 rightNode.next = null; // 第 4 步:同第 206 题,反转链表的子区间 reverseLinkedList(leftNode); // 第 5 步:接回到原来的链表中 //想一下,这里为什么可以用rightNode pre.next = rightNode; leftNode.next = succ; 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; } }
错误点!!!,一开始没有考虑到头节点,结果在循环时出现了空指针问题
头插法
1234
public ListNode reverseBetween(ListNode head, int left, int right) { // 设置 dummyNode 是这一类问题的一般做法 ListNode dummyNode = new ListNode(-1); dummyNode.next = head; ListNode pre = dummyNode; for (int i = 0; i < left - 1; i++) { pre = pre.next; } //记录左结点 ListNode cur = pre.next; 2 //记录结点,起记录作用(向虚拟节点一样) ListNode next; for (int i = 0; i < right - left; i++) { //记录下一个结点 next = cur.next; 3 4 //记录下下一个节点 cur.next = next.next; 2---》4 //将洗一个结点指向左结点 next.next = pre.next; 3---》2 //直接将指向左结点下一个 pre.next = next; 1---》3 1---》4 } 1---》3---》2---》4 1---》4---》3---》2 return dummyNode.next; }
关键点:将前面两个进行反转过后---就可以将后面的结点插入到前面去
解决思路:
1.先将前两个后面的值记录下来
2.开始改变指针方向(从后到前改变)
两两交换链表中的节点
public ListNode swapPairs(ListNode head) { ListNode dummyHead = new ListNode(0); dummyHead.next = head; ListNode temp = dummyHead; while (temp.next != null && temp.next.next != null) { //记录前后结点 ListNode node1 = temp.next; ListNode node2 = temp.next.next; //将转变前面结点指针 temp.next = node2; //转变后面结点指针 node1.next = node2.next; //转变中间结点指针 node2.next = node1; //修改指针 temp = node1; } return dummyHead.next; }