• LinkedList_LeetCode019


    019题:

    第一种方法:暴力解,借鉴002创建一个新的ListNode存储答案,先遍历原ListNode获得他的长度并把他放入map,然后读取map并创建出答案来。

    其中创建的这个节点的第一位置其实是一个哑节点(dummy node)。用于简化某些极端情况!
        public static ListNode Ssozh_removeNthFromEnd(ListNode head, int n){
    //        ListNode.pprint(head);
            Map<Integer,Integer> map = new HashMap<>();
            ListNode tmp = head;
            int cnt = 0;
            for(;;){
                if (tmp.next != null) {
                    map.put(cnt,tmp.val);
                    tmp=tmp.next;
                    cnt++;
                } else {
                    map.put(cnt,tmp.val);
    //                System.out.println(head.val);
                    break;
                }
            }
    //        System.out.println(cnt);
            int j = 0;
            ListNode ans = new ListNode(0); // this one will be remove
            ListNode node = ans ;
            for(;;){
                if(j == cnt + 1) break;
                if(j == cnt + 1 - n) {
                    j++;
                    continue;
                }
                node.next  = new ListNode(map.get(j));
                node = node.next;
                j++;
                System.out.println("j="+j);
            }
            return ans.next;
        }
    

    这种解法的内存占用大,用时慢。对于内存占用大,可以把创建一个新的ans链表改为在原链表上更改的方法。

    方法二:依然是暴力解,但是对方法一进行了改进,将创建一个ListNode改为在head上直接改。

    //        ListNode.pprint(head);
            ListNode tmp = head;
            int cnt = 0; // len of head and 0 is start number.
            for(;;){
                if (tmp.next != null) {
                    tmp=tmp.next;
                    cnt++;
                } else {
                    break;
                }
            }
            if(n == cnt+1) return head.next; // if n == len ?
            int j = 0;
            ListNode node = head; // in fact this var 'node' could be replace with var 'tmp' and could be turn into dummy. 
            for(;;){
                    if(j == cnt +1- n){
                    node.next = node.next.next;
                    break;
                    }
                    node = node.next;
                    j++;
                    }
            return head;
    

    这里需要注意的是,上面无论是tmp,node都是引用,而ans其实是一个深拷贝的操作。这里面是没有浅拷贝的!
    上面两种方法都是用了两次遍历,第三种方法比第二种方法快只用了一次遍历,但实质上这三种方法都是O(L)的时间复杂度。

    第三种方法:双指针法,先一个指针走n步,然后第二个指针和第一个一次走到头。

        public static ListNode removeNthFromEnd(ListNode head, int n){
            ListNode dummy = new ListNode(0);
            dummy.next = head;
            ListNode first = dummy;
            ListNode second = dummy;
            for(int i=0;i<n+1;i++){
                first = first.next; // move n times
            }
            while(first.next!=null){
                first =first.next;
                second = second.next;
            }
            second.next = second.next.next;
            return dummy.next;
        }
    

    以上就是LeetCode019的三种解法,其中与链表相关的还有LeetCode002,与双指针相关的还有011MaxArea。后面会把这些相关的都一起写一下。

  • 相关阅读:
    cors 详解
    网站性能优化实战——从12.67s到1.06s的故事
    浏览器渲染引擎
    window.location.reload(false);window.location.reload(true);history.Go(0)区别
    微信小程序image组件中aspectFill和widthfix模式应用详解
    git commit -m 与 git commit -am的区别
    git add详解
    Genymotion 解决虚拟镜像下载速度特别慢的问题
    使用Struts+Hibernate开发学生信息管理系统
    ZipInputStream的用法
  • 原文地址:https://www.cnblogs.com/SsoZhNO-1/p/12233256.html
Copyright © 2020-2023  润新知