zoukankan      html  css  js  c++  java
  • Remove Duplicates from Sorted List II 解答(有个比較特殊的case leetcode OJ没有覆盖)

             昨天被考了一道数据结构题,当时的实现比較一般。回来翻看leetcode,果然是上面的题。遂解之。

    accept之后翻看discuss别人的解法。发现非常多能够accept的代码都过不了我设计的一个case。网上搜了一些别人的代码,也过不了。遂有这篇博客,与君交流

             题目是这种:
            Given a sorted linked list, delete all nodes that have duplicate numbers, leaving onlydistinct numbers from the original list.
             For example,Given 1->2->3->3->4->4->5, return 1->2->5.Given 1->1->1->2->3, return 2->3.

            

            当时拿到这个题目,一眼首先想到的就是类似于手游《糖果粉碎传奇》的连续消除的画面。一个比較强的case浮入脑海:
            输入:1->2->3->3->3->5->6->2->2->6->5->2->7
            输出:1->7

            分析:当3 和 第一段连续的2 被消除后,链表变成1->2->5->6->6->5->2->7;
                        此时出现了连续的6。遂须要消除6,结果是1->2->5->5->2->7。
                        同理消除5和2之后剩下1->7

             可是不管是leetcode里面的discuss还是网上搜到的别人能够accept的代码。都不是上面的这样的输出,得到的输出一般例如以下:
             输出1:1 2 5 6 6 5 2 7
             输出2:1 2 5 5 2 7 
             当然,不知道是题目表意不明,或者是case太弱,可是题目明显写着‘distinct’。当然我觉得我的case应该是对的。遂我来讲一下我的思路和做法。

    就拿 1->2->3->3->3->5->6->2->2->6->5->2->7 这个case举例。

             

            在这个题目中。链表是单链表。那么我们用指针遍历链表的时候,是无法回头的,这是个明显的限制条件。可是在这个case中,当删掉3和第一段连续2的之后链表变成1->2->5->6->6->5->2->7。不论你的代码怎么实现,此时你的指针可能在第一个6或者第一个5那里,当链表继续删除连续节点的时候,指针是不得不回头的。否则不可以删除出现的两个5的连续节点。既然这样,题目的解法基本思路可以确定:递归或者栈,当然,两者是想通的。只是栈的实现会方便一些(当时做这个题的时候硬着头皮写递归,没写好,哈哈)。

            用堆的方式解题,思路是比較简单的:
    1、将头节点放入栈中,设置变量flag=false(flag表示栈顶节点是否须要被删除),检查下个节点
    2、假设当前节点是NULL,则跳到第4步;
          假设当前节点跟栈顶节点同样。则跳过链表上这个节点,flag=true,继续运行第2步。
          假设跟栈顶节点值不同。则跳到第3步;
    3、假设flag是true,那么把栈顶节点pop掉,flag置false。
          假设flag是false,把当前节点压入栈中,检查下个节点;
          运行第2步;
    4、假设flag是true,则pop掉栈顶节点
    5、链表的检查到此结束。栈内的节点就是结果链表的逆序存储。又一次组织一下便可
    6、注意:栈仅仅须要存节点的指针

            复杂度分析:时间复杂度能够简单分析一下,由于每一个节点要么被push要么被丢掉,push也有可能被pop,一共就这三种操作,每种最多运行一次,所以我们能够觉得时间复杂度是O(n)。空间复杂度,最坏情况下会把整个链表的指针都放到栈里面,最好情况下是结果链表的长度,所以空间复杂度是O(n)


    最后是我的代码:

    struct ListNode {
      int val;
      ListNode *next;
      ListNode(int x) : val(x), next(NULL) {}
    };
    
    class Solution {
     public:
      ListNode* deleteDuplicates(ListNode* head) {
        if (head == NULL) return NULL;
    
        stack<ListNode *> stk;
        bool flag = false;
        ListNode * cur = head;
        while (cur != NULL) {
          if (stk.empty()) {
              stk.push(cur);
              cur = cur->next;
              flag = false;
          } else if (cur->val == stk.top()->val) {
            flag = true;
            // because we don't know how the program frame manage the memory,
            // so i didn't free the  duplicate ListNode
            cur = cur->next;
            continue;
          } else if (flag) {
            stk.pop();
            flag = false;
          } else {   
            stk.push(cur);
            cur = cur->next;
          }   
        }   
        if (flag) stk.pop(); 
        
        // the remaining node in the stack is the result
        ListNode * res = NULL;
        while(!stk.empty()) {
          ListNode* t = stk.top();
          stk.pop();
          if (res == NULL) {
            res = t;
            res->next = NULL;
          } else {
            t->next = res;
            res = t;
          }
        } 
        return res;
      }
    };



  • 相关阅读:
    曹工说Redis源码(8)--面试时,redis 内存淘汰总被问,但是总答不好
    曹工说JDK源码(4)--抄了一小段ConcurrentHashMap的代码,我解决了部分场景下的Redis缓存雪崩问题
    曹工说JDK源码(3)--ConcurrentHashMap,Hash算法优化、位运算揭秘
    曹工说JDK源码(2)--ConcurrentHashMap的多线程扩容,说白了,就是分段取任务
    曹工说JDK源码(1)--ConcurrentHashMap,扩容前大家同在一个哈希桶,为啥扩容后,你去新数组的高位,我只能去低位?
    曹工说Spring Boot源码(29)-- Spring 解决循环依赖为什么使用三级缓存,而不是二级缓存
    曹工说mini-dubbo(2)--分析eureka client源码,想办法把我们的服务提供者注册到eureka server(上)
    @Spring Boot程序员,我们一起给程序开个后门吧:让你在保留现场,服务不重启的情况下,执行我们的调试代码
    python处理txt大文本文件
    Matlab读写文件时的定位
  • 原文地址:https://www.cnblogs.com/yfceshi/p/6938240.html
Copyright © 2011-2022 走看看