LeetCode链表-反转&有无环

1 反转链表

题目:https://leetcode-cn.com/problems/reverse-linked-list/
思路:把每个链表next 指向前驱节点即可,类似链表头插入法

class Solution {
    public ListNode reverseList(ListNode head) {
        if(head==null||head.next==null) {
            return head;
        }
        //前一个节点,一开始为空
        ListNode prev=null;
        //当前节点
        ListNode cur=head;
        while(cur!=null){
            ListNode next=cur.next;
            cur.next=prev;
            //节点后移
            prev=cur;
            cur=next;
        }
        return prev;
    }
}

反转链表指定位置:https://leetcode-cn.com/problems/reverse-linked-list-ii/
思路:找到要反转的部分,对该部分进行反转,要保留前驱和后继节点。


class Solution {
    public ListNode reverseBetween(ListNode head, int left, int right) {
        //几种场景不用处理
        if (head == null || head.next == null || right == left) {
            return head;
        }
        ListNode vHead = new ListNode(-1);
        vHead.next = head;
        ListNode cur = vHead;
        ListNode startPre = null, end = null, start = null;
        int count = 0;
        while (cur != null) {
            count++;
            //找到要反转开始前驱,由于加了一个虚拟头
            if (left == count) {
                startPre = cur;
            }
            // 找到要反转的结尾
            if (count == right + 1) {
                end = cur;
                //记录end next 节点
                cur = cur.next;
                end.next = null;
                break;
            }
            cur = cur.next;
        }
        start = startPre.next;
        startPre.next = reverse(start);
        if (start != null) {
            //end next 节点为开始节点反转后的后继节点
            start.next = cur;
        }
        return vHead.next;

    }

    private ListNode reverse(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode cur = head, prev = null;
        while (cur != null) {
            ListNode next = cur.next;
            cur.next = prev;
            prev = cur;
            cur = next;
        }
        return prev;
    }
}

2 两两交换链表

题目:https://leetcode-cn.com/problems/swap-nodes-in-pairs/
思路:用两个指针分别移动,要考虑到边界问题

  public ListNode swapPairs(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode slow = head, fast = head.next;
        ListNode newHead = head.next;

        while (fast != null && slow != null) {
            ListNode next = fast.next;
            fast.next = slow;
            slow.next = next;
            //判断接下来有没有两个,如果有两个,要连接到反转后的
            if (next != null && next.next != null) {
                slow.next = next.next;
            }
            //后移
            slow = next;
            if (slow != null) {
                fast = slow.next;
            }
        }
        return newHead;
    }

3 判断链表有没有环

题目:https://leetcode-cn.com/problems/linked-list-cycle/
思路1:有环说明会访问重复节点记录,使用set 记录访问过的节点,如果节点有重复说明有环存在

 public class Solution {
        public boolean hasCycle(ListNode head) {
            if (head == null || head.next == null) {
                return false;
            }
            Set<ListNode> set = new HashSet<>();
            ListNode p = head;
            while (p != null) {
                if (set.contains(p)) {
                    return true;
                }
                set.add(p);
                p = p.next;
            }
            return false;
        }
    }

思路2:快慢指针法,快指针比慢指针多走一步,如果有环的的话,快慢指针一定能相遇(在环里可能转了几个圈)

public class Solution {
    public boolean hasCycle(ListNode head) {
        if(head==null||head.next==null){
            return false;
        }
        ListNode slow=head,fast=head.next;
        while(slow!=fast){
            if(fast==null || fast.next==null) {
                return false;
            }
            fast=fast.next.next;
            slow=slow.next;
        }
        return true;
    }
}

题目:https://leetcode-cn.com/problems/linked-list-cycle-ii/
思路1:使用set记录访问过的节点,如果第一次找到重复的地方,就说明有环的节点头。

public class Solution {
    public ListNode detectCycle(ListNode head) {
        if (head == null || head.next == null) {
            return null;
        }
        Set<ListNode> set = new HashSet<>();
        ListNode cur = head;
        while (cur != null) {
            if (set.contains(cur)) {
                return cur;
            } else {
                set.add(cur);
            }
            cur = cur.next;
        }
        return null;
    }
}

思路1:快慢指针法,待补充

4 总结

链表思考要动手画下图,引入虚拟节点,可以适当简化代码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值