剑指Offer:链表

1、删除链表中重复的结点
题目描述

在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5

方法1:

public class Linked {
    public static void main(String[] args) {

        ListNode pHead = new ListNode(1);
        ListNode nodeh = pHead;
        ListNode index = new ListNode(1);
        nodeh.next = index;
        nodeh = index;
        index = new ListNode(2);
        nodeh.next = index;

        Linked s = new Linked();
        ListNode list = s.deleteDuplication(null);
        System.out.println("list");
        while(list != null) {
            System.out.print(list.val + " ");
            list = list.next;
        }

    }

    private ListNode deleteDuplication(ListNode pHead) {

        if(pHead == null) return pHead;

        //创建一个节点,防止头节点被删除
        ListNode pre_head = new ListNode(-1);
        pre_head.next = pHead;
        //指向前一个节点
        ListNode pre = pre_head;
        ListNode cur = pHead;

        while(cur != null && cur.next != null) { //注意条件的顺序,否则不对,因为如果p为null,p.next肯定异常
            if(cur.val == cur.next.val) {
                int val = cur.val;
                //向后重复查找
                while(cur != null && val == cur.val) {
                    cur = cur.next;
                }
                //上个非重复值指向下一个非重复值:即删除重复值。
                pre.next = cur;
            } else {
                //如果当前节点和下一个节点值不等,则向后移动一位
                pre = cur;
                cur = cur.next;
            }
        }

        return pre_head.next;
    }
}

方法2 (三指针法):
采用三个指针来进行遍历,同时删除重复的节点,因为是有序的链表,我们就可以确定,重复的元素肯定是在一块链接,所以我们就可以,用三指针,我们这里就叫pre、cur、nex 分别代表的是前中后三个指针,我们在考虑的情况中,如果头节点开始就重复,我们就处理很起来多了一种情况就需要额外处理,所以我们添加一个头节点,变成带头节点,保证了头节点开始不会重复,那么我们就可以开是让pre指向带头的节点,cur指向pre的next,nex指向cur的next。

接下来我们就可以看cur是否和nex相等,相等就让nex继续向下走,不相等然后再处理删除,cur开始到nex中间节点都是要删除的(包含cur指向,不包含nex指向)删除,就用到了pre,删除完成让pre指向cur就可以了。

如果cur值与nex值不相等,那么就可以三个指针各自往前移动一个。

import java.util.ArrayList;
import java.util.HashSet;

class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}

public class Solution {

    public static void main(String[] args) {
        ListNode pHead = new ListNode(1);
        ListNode nodeh = pHead;
        ListNode index = new ListNode(1);
        nodeh.next = index;
        nodeh = index;
        index = new ListNode(1);
        nodeh.next = index;



        Solution s = new Solution();
        ListNode list = s.deleteDuplication(pHead);

        while(list != null) {
            System.out.print(list.val + " ");
            list = list.next;
        }

    }

    public ListNode deleteDuplication(ListNode pHead){

        if(pHead == null || pHead.next == null) {
            return pHead;
        }

        ListNode pre =  new ListNode(0);
        pre.next = pHead;
        ListNode pre_head = pre;
        ListNode cur = pHead;
        ListNode nex = pHead.next;

        while(nex != null) {
            while(nex != null && cur.val == nex.val) {
                nex = nex.next;
            }

            if(cur.next != nex) {
                while(cur != nex) {
                    pre.next = cur.next;
                    cur = cur.next;
                }
                if(nex != null) {
                    nex = nex.next;
                }
            } else {
                pre = cur;
                cur = nex;
                nex = nex.next;

            }
        }

        pre_head = pre_head.next;

        return pre_head;
    }
}
2、链表中环的入口节点

给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。

思路:

第一步,找环中相汇点。分别用p1,p2指向链表头部,

  • p1每次走一步,p2每次走二步,直到p1==p2找到在环中的相汇点。

通过141题,我们知道可以通过快慢指针来判断是否有环,现在我们假设两个指针相遇在z点,如图
在这里插入图片描述
那么我们可以知道fast指针走过a+b+c+b

slow指针走过a+b

那么2*(a+b) = a+b+c+b

所以a = c

那么此时让slow回到起点,fast依然停在z,两个同时开始走,一次走一步

那么它们最终会相遇在y点,正是环的起始点

public class Huan {

    public ListNode EntryNodeOfLoop(ListNode pHead) {
        if(pHead == null || pHead.next == null) {
            return pHead;
        }
        ListNode slow = pHead;
        ListNode fast = pHead;
        while(slow != null && fast != null) {
            slow = slow.next;
            fast = fast.next.next;
            if(slow == fast) {
                slow = pHead;
                while(slow != fast) {
                    slow = slow.next;
                    fast = fast.next;
                }
                return slow;
            }
        }
        return null;
    }
}

2、两个链表的第一个公共结点

题目描述
输入两个链表,找出它们的第一个公共结点
在这里插入图片描述

public class PublicNode {
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        if(pHead1 == null || pHead2 == null) return null;
        ListNode c1 = pHead1;
        ListNode c2 = pHead2;
        int n = 0;
        while(c1 != null) {
            n++;
            c1 = c1.next;
        }
        while(c2 != null) {
            n --;
            c2 =c2.next;
        }

        if(c1 != c2) {
            return null;
        }
        c1 = n > 0?pHead1:pHead2;
        c2 = c1==pHead1?pHead2:pHead1;
        n = Math.abs(n);
        while(n != 0) {
            n --;
            c1 = c1.next;
        }
        while(c1 != c2) {
            c1 = c1.next;
            c2 = c2.next;
        }

        return c1;
    }
}

3、复杂链表的复制
题目描述

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

import java.util.HashMap;
class RandomListNode {
    int label;
    RandomListNode next = null;
    RandomListNode random = null;

    RandomListNode(int label) {
        this.label = label;
    }
}

public class CopyListWithRand1 {

    public RandomListNode copyListWithRand1(RandomListNode head) {

        HashMap<RandomListNode,RandomListNode> map = new HashMap<RandomListNode,RandomListNode>();
        RandomListNode cur = head;
        while(cur != null) {
            map.put(cur,new RandomListNode(cur.label));
            cur = cur.next;
        }

        cur = head;
        while(cur != null) {
            map.get(cur).next = map.get(cur.next);
            map.get(cur).random = map.get(cur.random);
            cur = cur.next;
        }
        return map.get(head);
    }
}

猜你喜欢

转载自blog.csdn.net/yuming226/article/details/92726772