leetcode 链表系列

1、 反转链表

https://leetcode.com/problems/reverse-linked-list/solution/

Assume that we have linked list 1 → 2 → 3 → Ø, we would like to change it to Ø ← 1 ← 2 ← 3.

While you are traversing the list, change the current node’s next pointer to point to its previous element. Since a node does not have reference to its previous node, you must store its previous element beforehand. You also need another pointer to store the next node before changing the reference. Do not forget to return the new head reference at the end!

  • 当要反转链表的时候,需要改变当前节点的后继节点指针指向当前节点的前驱节点,由于在单链表中一个节点不会保存他的前驱节点,所以需要一个临时变量来保存他的前驱节点(pre)
  • 同样需要另一个指针(temp)来保存当前节点的后继节点,否则在你反转指向(当前节点的后继节点指针指向当前节点的前驱节点)以后,链表就断了
  • 最后需要返回的是pre 指针
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode pre = null;
        ListNode current = head;
        ListNode temp = null;
        while(current != null){
            temp = current.next;
            current.next = pre;
            pre = current;
            current = temp;
        }
        return pre;
    }
}

2、 链表中间段逆序

https://leetcode.com/problems/reverse-linked-list-ii/

  • 找出四个关键节点,当逆序完成后把逆序的那部分连接回原来的链表
  • 将head节点移动m-1次,到开始逆序的节点
  • 将中间段逆序
  • 拼接逆序的链表和原来的链表
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseBetween(ListNode head, int m, int n) {
        int changeLength = n - m + 1;
        ListNode resultHead = head;
        ListNode preHead = null;
        while(head != null  && ((m-1) > 0)){
            preHead = head;
            head = head.next;
            m--;
        }
        ListNode modify_last_tail = head;
        ListNode new_head = null;
        while(head != null && changeLength > 0){
            ListNode next = head.next;
            head.next = new_head;
            new_head = head;
            head = next;
            changeLength --;
        }
        modify_last_tail.next = head;
        if(preHead != null){
            preHead.next = new_head;
        }else{
            resultHead = new_head;
        }
        return resultHead;
    }
}

3、 合并有序链表

https://leetcode.com/problems/merge-two-sorted-lists/

  • 首先需要一个头节点来保存新链表的头
  • 需要有两个指针分别指向两个链表
  • 还需要一个指针来操纵新链表,控制新节点的加入
  • 判断两个链表头结点谁小,谁就转移到新链表的最后
  • 被转移头结点的链表的首指针向后移动一下
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode head = new ListNode(0);
        ListNode pre = head;
        while(l1 != null && l2 != null){
            if(l1.val <= l2.val){
                pre.next = l1;
                l1 = l1.next;
            }else{
                pre.next = l2;
                l2 = l2.next;
            }
            pre = pre.next;
        }
        if(l1 != null){
            pre.next = l1;
        }
        if(l2 != null){
            pre.next = l2;
        }
        return head.next;
    }
}

4、求两个链表的交叉点

https://leetcode.com/problems/intersection-of-two-linked-lists/

  • 最直观的方法就是把一个链表放入set ,遍历另一个链表,每个节点都去set中判断,是否存在,这个太简单直接忽略
  • 如果不能用set,从题目给定的情境下去挖掘潜在的逻辑就是如果两个链表有交叉点,那说明从交叉点以后,链表是重合的,也就是说交叉点只可能出现在倒数m(n 代表长链表的长度,m代表短链表长度)个节点之内,那我们可以去把两个链表的头结点去对齐,将较长链表的头指针移动到和短链表头指针对其的地方,再同步向后遍历比较
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        int lengthA = getLengthOfList(headA);
        int lengthB = getLengthOfList(headB);
        if(lengthA >= lengthB){
            headA = forwardList(headA,lengthA - lengthB);
        }else{
            headB = forwardList(headB,lengthB - lengthA);
        }
        ListNode intersection = null;
        while(headA != null){
            if(headA == headB){
                return headA;
            }
            headA = headA.next;
            headB = headB.next;
        }
        return null;
    }
    
    public ListNode forwardList(ListNode head,int step){
        while(step > 0){
           head = head.next; 
            step --;
        }
        return head;
    }
    
    public int getLengthOfList(ListNode head){
        int length = 0;
        
        while(head != null){
            head = head.next;
            length ++;
        }
        return length;
    }
}

5、判断链表是否有环

https://leetcode.com/problems/linked-list-cycle-ii/

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        ListNode meet = null;
        
        while(fast != null){
            fast = fast.next;
            slow = slow.next;
            if(fast == null){
                return null;
            }
            
            fast = fast.next;
            if(fast == slow){
                meet = fast;
                break;
            }
        }
        while(meet != null && head != null){
            if(meet == head){
                return meet;
            }
            meet = meet.next;
            head = head.next;
        }
        return null;
        
        
    }
}

6、链表划分

https://leetcode.com/problems/partition-list/

  • 最后一定要把 morePos.next = null; 否则链表出现环,测试的过程中循环遍历,会直到耗尽内存
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode partition(ListNode head, int x) {
        ListNode less = new ListNode(0);
        ListNode more = new ListNode(0);
        ListNode lessPos = less;
        ListNode morePos = more;
        while(head != null){
            if(head.val < x){
                lessPos.next = head;
                lessPos = head;
            }else{
                morePos.next = head;
                morePos = head;
            }
            head = head.next;
        }
        lessPos.next = more.next;
        morePos.next = null;
        return less.next;
        
    }
}

7、带随机指针链表的深度拷贝

https://leetcode.com/problems/copy-list-with-random-pointer/

/**
 * Definition for singly-linked list with a random pointer.
 * class RandomListNode {
 *     int label;
 *     RandomListNode next, random;
 *     RandomListNode(int x) { this.label = x; }
 * };
 */
public class Solution {
    public RandomListNode copyRandomList(RandomListNode head) {
        if(head == null){
            return null;
        }
        RandomListNode pos = head;
        HashMap<RandomListNode,Integer> nodeMap = new HashMap<RandomListNode,Integer>();
        List<RandomListNode> cloneList = new ArrayList<RandomListNode>();
        int i = 0;
        while(pos != null){
            cloneList.add(new RandomListNode(pos.label));
            nodeMap.put(pos,i);
            pos = pos.next;
            i ++;
        }
        cloneList.add(null);
        pos = head;
        i = 0;
        while(pos != null ){
            cloneList.get(i).next = cloneList.get(i + 1);
            if(pos.random != null){
                int id = nodeMap.get(pos.random);
                cloneList.get(i).random = cloneList.get(id);
            }
            i ++;
            pos = pos.next;
        }
        if(cloneList.size() == 0){
            return null;
        }
        return cloneList.get(0);
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值