链表——单链表常见的五种操作

五种常见操作

以下代码都是针对引入哨兵的带头链表

1、单链表反转

原地反转

	public static Node reverseLinkList(Node head){
		if(head.next == null){
			return head;
		}
		Node prev = head.next;
		Node pcur = prev.next;
		while(pcur != null){
			prev.next = pcur.next;
			pcur.next = head.next;
			head.next = pcur;
			pcur = prev.next;
		}
		return head;
	}

头插法反转

	public static Node reverseLinkList(Node head){
		if(head.next == null){
			return head;
		}
		Node newHead = new Node();
		Node pcur = head.next;
	    Node curNextTmp = null;
		while(pcur != null){
			curNextTmp = pcur.next;
			pcur.next = newHead.next;
			newHead.next = pcur;
			pcur = curNextTmp;
		}
		return newHead;
	}

2、链表中环检测

快慢指针法

  • 两个指针同时从第一个数据节点开始,pFast每次移到两个节点,pSlow每次移到一个节点
  • pFast先到尾部即pFast == null,说明没有闭环
  • 如果有闭环 则最终两个指针会相遇即 pFast==pSlow
    public static boolean hasLoop(Node head){
        if(head.next==null){
            return false;
        }
        Node pFast = head.next;
        Node pSlow = head.next;
        while (pFast!=null&&pSlow!=null){
            pFast = pFast.next.next;
            pSlow = pSlow.next;
            if(pFast==null){
                //这个判断不能少,否则可能会陷入死循环
                return false;
            }else if(pFast==pSlow){
                return true;
            }
        }
        return false;
    }

3、两个有序链表合并

递归

  • 递归代码简洁,不递归通过迭代也可以通过两个指针遍历解决;
	public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if(l1==null&&l2==null){
            return null;
        }else if(l1==null){
            return l2;
        }else if(l2==null){
            return l1;
        }
        //递归
        ListNode l3;
        if(l1.val > l2.val){
            l3=l2;
            l3.next=mergeTwoLists(l1,l2.next);
        }else{
            l3=l1;
            l3.next=mergeTwoLists(l1.next,l2);
        }
        return l3;
        
        //迭代
        /*ListNode head = new ListNode(-1);
        ListNode pcur = head;
        while(l1!=null && l2!=null){
            if(l1.val<=l2.val){
                pcur.next = l1;
                l1 = l1.next;
            }else{
                pcur.next = l2;
                l2 = l2.next;
            }
            pcur = pcur.next;
        }
        pcur.next = l1==null?l2:l1;
        return head.next;*/

    }

4、删除链表倒数第 n 个节点

快慢指针法

  • 让fast指针先移动n个节点之后slow节点再加入一起向后移动,直至fast==null,此时slow指向的就时倒是第N个;
  • 链表为空或者n小于0或者超出链表长度返回null;
	public static Node removeNthFromEnd(Node head,int n){
        if(head.next==null || n<=0){
            return head;
        }
        //fast和slow都指向哨兵
        Node fast = head;
        Node slow = head;
        int count = 0;
        //循环结束条件要注意时fast.next!=null
        //如果时fast!=null,则n=1的时候会出问题
        //注意边界条件
        while (fast.next!=null){
            if(count<n){
                //这里至少会执行一次
                fast = fast.next;
                count++;
            }else{
                fast = fast.next;
                slow = slow.next;
            }
        }
        slow.next = slow.next.next;
        return head;
    }

5、求链表的中间节点

快慢指针法

  • fast每次移动两个节点,slow每次移动一个节点同时向尾部移动,fast.next==null时结束,此时slow指向中间节点
	public static Node middleNode(Node head) {
        if (head.next == null) {
            return head;
        }
        Node slow = head;
        Node fast = head;
        //长度可能为奇数和偶数,奇数结束fast==null,偶数结束fast.next==null
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }

熄灯

以上代码链表都是引入哨兵的带头链表

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小技工丨

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值