算法刷题—链表的操作

算法

判断循环链表的入环节点(leetcode142)

方法一:使用哈希表,set集合,遍历链表的时候先判断一下是否存在该节点,如果存在那么就是第一个入环的节点

方法二:使用快慢指针,从头节点开始遍历,如果当快慢指针相遇的时候,那么就让快指针又从头节点开始遍历,但是这次一次只需要走一步,慢指针也走异步,当两个指针再次相遇的时候就是他们的入环节点了。

public class Solution {
    public ListNode detectCycle(ListNode head) {
        if (head == null || head.next == null || head.next.next == null) {
                return null;
        }
        ListNode n1 = head.next;
        ListNode n2 = head.next.next;
        while (n1 != n2) {
            if (n2.next == null || n2.next.next == null) {
                return null;
            }
            n2 = n2.next.next;
            n1 = n1.next;
        }
        n2 = head;
        while (n1 != n2) {
            n1 = n1.next;
            n2 = n2.next;
        }
        return n2;
    }
}

相交链表

在这里插入图片描述

方法一:使用HashSet,分别将A,B两个链表的node加入到链表中去,第二的链表加入时判断是否包含该节点,包含就证明他是第一个节点

ublic class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        HashSet<ListNode> set = new HashSet<>();
        while (headA != null) {
            set.add(headA);
            headA = headA.next;
        }
        while (headB != null) {
            if (set.contains(headB)) {
                return headB;
            }
            headB = headB.next;
        }
        return null;
    }
}

方法二:分别统计两个链表的长度,然后找出长的链表,先遍历他们的差值的长度,然后再将两个链表同时进行遍历,当他们遍历到节点相等就是相交的点。

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode cur1 = headA;
        ListNode cur2 = headB;
        int n = 0;
        while (cur1.next != null) {
            n++;
            cur1 = cur1.next;
        }
        while (cur2.next != null) {
            n--;
            cur2 = cur2.next;
        }
        if (cur1 != cur2) return null;
        cur1 = n > 0 ? headA : headB;
        cur2 = cur1 == headA ? headB :headA;
        n = Math.abs(n);
        while (n != 0) {
            n--;
            cur1 = cur1.next;
        }
        while (cur1 != cur2) {
            cur1 = cur1.next;
            cur2 = cur2.next;
        }
        return cur1;
    }
}

将链表按照某个值左右划分

比如给你一个链表:1,2,5,0,52,33,11,23
请你按照11划分,小于11的节点放在该节点的左边其他放在右边,请你以时间复杂度为O(n)完成该题目

/**
 * 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 sortList(ListNode head) {
        //六个节点,存储比较值的小于等于大于的值链表,最后将他们串起来就完成
        ListNode Startsn = null;
        ListNode Starten = null;
        ListNode Midsn = null;
        ListNode Miden = null;
        ListNode Endsn = null;
        ListNode Enden = null;
        //创建一个节点来保存没有遍历的节点
        ListNode next = null;
        while (head != null) {
            next = head.next;
            head.next = null;
            if (head.val < 1) {
                if (Startsn == null) {
                    Startsn = head;
                    Starten = head;
                } else {
                    Starten.next = head;
                    Starten = head;
                }
            } else if (head.val == 1) {
                if (Midsn == null) {
                    Midsn = head;
                    Miden = head;
                } else {
                    Miden.next = head;
                    Miden = head;
                }
            } else {
                if (Endsn == null) {
                    Endsn = head;
                    Enden = head;
                } else {
                    Enden.next = head;
                    Enden = head;
                }
            }
            head = next;
        }
        if (Startsn != null) {
            // 如果有小于区域
            Starten.next = Midsn;
            //下一步,谁去连大于区域的头,
            Miden = Miden == null ? Starten : Miden; 
        }
        if (Miden != null) {
            Miden.next = Endsn;
        }
        return Startsn != null ? Startsn : (Endsn != null ? Midsn : Endsn);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值