leetcode 19 和leetcode 83

19. Remove Nth Node From End of List
问题描述:Given a linked list, remove the nth node from the end of list and return its head.
题目规定了你可以认为n总是有效的,并尽可能只遍历链表一次就完成操作。
分析时首先可以想到的基本思路是找到倒数第n个节点然后删去,进一步思考后发现寻找倒数第n个节点比较麻烦,但是倒数第n个节点也就是整数第L-n+1个节点,L是整个链表的长度,因此,一个基本的思路就是遍历链表一次,找出链表的长度,在找到第L-n个节点p, 之后p -> next = p-> next -> next;free(p ->next);就可以了。
但是这个方案相当于遍历了链表两次,如何只遍历一次呢?
倒数第n个节点,也就是距离最后一个节点有n-1个节点。思考明白这一层关系,思路就来了,首先通过一个指针first,从head开始向后移动n个节点,此时停下,再设置一个指针second指向head,之后同步的移动first指针和second指针直到到达链表末尾,那么此时,first指针指向链表最后一个节点,second指针指向倒数第n个节点的前一结点。之后通过second -> next = second -> next -> next;free(second -> next)即可。
思路理清楚了,就是代码实现中的细节问题了。
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
    struct ListNode* pre = head;
    struct ListNode* nex = head;
    struct ListNode* ans;
    for (int i = 0; i < n; ++i)
    {
        nex = nex -> next;
    }
    
    if (nex == NULL)
    {
        ans = head -> next;
        free(head);
        return ans;
    }
    
    while (nex -> next != NULL)
    {
        pre = pre -> next;
        nex = nex -> next;
    }
    free(pre -> next);
    pre -> next = pre -> next -> next;
    return head;

}
同时,在题目的讨论区中有一种利用二重指针的方法,我没怎么理解到。http://blogread.cn/it/article/6243?f=wb 转一下这篇文章,以后再细细了解吧。
leetcode 83问题描述:Given a sorted linked list, delete all duplicates such that each element appear only once.For example,
Given 1->1->2, return 1->2.
Given 1->1->2->3->3, return 1->2->3.

本题的坑点在于理解题意,本题给出的测试用例的值相同的节点都是相邻的!而自己理解的是值相同的节点的分布式随机的。这就绕了很大的弯路。如果是值相同的点都是相邻的,就很好解决。
struct ListNode* deleteDuplicates(struct ListNode* head) {
        if (head)
        {
            struct ListNode* p = head;
            while(p -> next)
            {
                if (p -> val != p -> next -> val)
                {
                    p = p -> next;
                }
                else
                {
                    struct ListNode* tmp = p -> next;
                    p -> next = p -> next -> next;
                    free(tmp);
                }
            }
        }
        return head;
}
代码中标红的代码需要注意,此处只需要将p节点指向在下一节点即可,不要用p = p -> next -> next。写成这样的话,在free了tmp节点之后,原先p节点的next指针就变得不预测,没有指向,造成内存泄漏。
同时,还有一种递归的方法,需要对递归一定的理解和熟悉。观察了上面的方法后,我们发现每一个节点做的动作都是一样的,先判断本节点与下一节点的值是否相同,如果不相同则指针移动到下一节点,如果相同,则移动到下一节点的后一个节点。因此,通过递归的方式了一写出更加简洁的代码。
public ListNode deleteDuplicates(ListNode head) {
        if(head == null || head->next == null)return head;
        head->next = deleteDuplicates(head->next);
        return head->val == head->next->val ? head->next : head;
}
在做leetcode上的试题时,一般不需要将不用的节点free掉或者delete掉,因为只有确定是malloc的节点才需要在不用之后立刻释放点。但是在leetcode的试题中没有这样的表述和要求。因此,不需要再这方面进行纠结。当然严格要求自己是好的,就看自己的习惯了。
阅读更多
文章标签: leetcode
个人分类: leetcode
上一篇leetcode 237和leetcode 206
下一篇leetcode 268r
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭