Day18——双指针专题


16.反转链表

首先定义一个cur指针,指向头结点,再定义一个pre指针,初始化为null。

然后就要开始反转了,首先要把 cur->next 节点用tmp指针保存一下,因为开始反转的时候cur->next就改变值了。

接下来,就是循环走如下代码逻辑了,继续向后移动pre和cur指针。

最后,cur 指针已经指向了null,循环结束,链表也反转完毕了。 此时我们return pre指针就可以了,pre指针就指向了新的头结点。

指向谁 就等于谁

代码实现:

//双指针
class Solution {
       public ListNode reverseList(ListNode head) {
        ListNode pre = null;
        ListNode cur = head;
        ListNode temp = null;
        while (cur!=null){
            temp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = temp;
        }
        return pre;
    }
}
// 递归 
class Solution {
    public ListNode reverseList(ListNode head) {
        return reverse(null, head);//将prev置为null,cur置为head
    }
    private ListNode reverse(ListNode prev, ListNode cur) {
        if (cur == null) {
            return prev;
        }
        ListNode temp = null;
        temp = cur.next;// 先保存下一个节点
        cur.next = prev;// 反转
        // 更新prev、cur位置
        return reverse(cur, temp);// prev = cur; cur = temp;
    }
}

17.两两交换链表中的节点

1.如下图所示:

先将cur虚拟头节点指向节点2,其次节点2指向节点1,最后节点1指向节点3,交换链表之前将节点1和节点3用临时节点记录,之后完成步骤一二三,第一轮交换完成后,cur往后移动二位,准备下一轮交换,最后返回cur.next即头节点。

image-20221014201154519

image-20221014203832850

代码实现:

//虚拟头节点
class Solution {
 public ListNode swapPairs(ListNode head) {
        ListNode dummy = new ListNode(0);//设置一个虚拟头节点
        dummy.next = head;//将虚拟头节点指向head,这样方便后续操作。
        ListNode cur = dummy;//用cur临时指针来代替虚拟头节点
     
        while(cur.next!=null&&cur.next.next!=null){//分别排除偶数和奇数
            ListNode temp = cur.next;//记录临时节点
            ListNode temp1 = cur.next.next.next;//记录临时节点
            
            cur.next = cur.next.next;//步骤一
            cur.next.next = temp;//步骤二
            temp.next = temp1;//步骤三
            
            cur = cur.next.next;//cur移动两位,准备下一轮交换
        }
        return dummy.next;//返回头节点
    }
}
// 递归版本
class Solution {
    public ListNode swapPairs(ListNode head) {
        // base case 退出提交
        if(head == null || head.next == null) return head;
        // 获取当前节点的下一个节点
        ListNode next = head.next;
        // 进行递归
        ListNode newNode = swapPairs(next.next);
        // 这里进行交换
        next.next = head;
        head.next = newNode;
        return next;
    }
} 

18.删除链表的倒数第N个节点

思路:

1.循环遍历,只要快慢指针相差 n 个结点即可

2.因为删除某个节点,需要知道这个节点的上一个节点,fastIndex要执行n+1步的位置来判断,所以fastIndex.next指向null,循环结束,这时候slow在删除节点的上一个节点,执行删除操作。

代码实现:

class Solution {
   public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummmyNode = new ListNode(0);//创建虚拟头节点
        dummmyNode.next = head;//让虚拟头节点的next指向head
        ListNode fastIndex = dummmyNode;//定义快指针
        ListNode slowIndex = dummmyNode;//定义慢指针
        for(int i = 0;i < n;i++){//循环遍历,只要快慢指针相差 n 个结点即可
            fastIndex = fastIndex.next;
        }
        while (fastIndex.next!=null){//因为删除某个节点,需要知道这个节点的上一个节点,slow才能指向删除节点的上一个节点
            fastIndex = fastIndex.next;//快指针后移
            slowIndex = slowIndex.next;//慢指针后移
        }
        slowIndex.next = slowIndex.next.next;//删除第n个节点
        return dummmyNode.next;//返回头节点
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值