剑指offer(从尾到头打印链表、链表中环的入口节点、删除链表中重复的节点)

三、链表

1. 从尾到头打印链表

题目描述:

​ 输入一个不带头结点的单链表,按链表从尾到头的顺序返回一个ArrayList数组。

思路:

​ 莽。时间复杂度O(n),空间复杂度O(n)。

代码:

/**
*  struct ListNode {
*        int val;
*        struct ListNode *next;
*        ListNode(int x) :
*              val(x), next(NULL) {
*        }
*  };
*/
class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
        vector<int> vi;
        ListNode* p=head;
        while(p!=NULL){
            vi.push_back(p->val);
            p=p->next;
        }
        reverse(vi.begin(),vi.end());
        return vi;
    }
};

2. 链表中环的入口节点

题目描述:

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

思路:

​ 先说个定理:两个指针一个fast、一个slow同时从一个链表的头部出发,fast一次走2步,slow一次走1步,如果该链表有环,两个指针必然在环内相遇,此时只需要把其中的一个指针重新指向链表头部,另一个不变(还在环内),这次两个指针一次走一步,相遇的地方就是入口节点。

代码:

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead)
    {
        ListNode *fast=pHead,*slow=pHead;
        while(fast->next!=NULL){
            fast=fast->next->next;
            slow=slow->next;
            if(fast==slow){
                break;
            }
        }
        if(fast->next==NULL){
            return NULL;
        }else{
            fast=pHead;
            while(fast!=slow){
                fast=fast->next;
                slow=slow->next;
            }
            return fast;
        }
    }
};

3. 删除链表中重复的节点

题目描述:

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

思路:

​ 见代码。时间复杂度O(n),空间复杂度O(1)。

代码:

/*
 public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {
    public ListNode deleteDuplication(ListNode pHead)
    {
        if (pHead == null || pHead.next == null) {
            return pHead;
        }
        //自己构造一个头结点,可以避免单独讨论当第一二两个节点便开始重复的情况
        ListNode h = new ListNode(-1);
        h.next = pHead;
        ListNode pre = h;
        ListNode p = pre.next;
        while (p != null) {
            if (p.next != null && p.val == p.next.val) {
                while (p.next != null && p.val == p.next.val) {
                    p = p.next;
                }
                //退出循环时,p.next指向第一个不重复的节点
                p = p.next;
                pre.next = p;
            } else {
                pre = pre.next;
                p = p.next;
            }
        }
        return h.next;
    }
}
posted @ 2020-03-13 09:11  Java程序员的进阶之路  阅读(84)  评论(0编辑  收藏  举报