链表的题目(无题解,仅供复习)

Reverse LinkedList

方法1:三个指针

    public ListNode reverseList(ListNode head) {
        if(head == null){
            return null;
        }
        ListNode prev = null;
        ListNode curr = head;
        ListNode next;
        
        while(curr != null){
            next = curr.next;
            curr.next = prev;
            prev = curr;
            curr = next;
        }
        
        return prev;
    }

方法2:设置虚拟头结点,然后从头遍历原来的链表,每次都把原链表的节点插入到dummyHead后面。

    public ListNode reverseList(ListNode head) {
        if(head == null){
            return null;
        }
        ListNode dummyHead = new ListNode(-1);
        ListNode curr = head;
        while(curr != null){
            ListNode next = curr.next;
            curr.next = dummyHead.next;
            dummyHead.next = curr;
            curr = next;
        }
        
        return dummyHead.next;
    }

Reverse LinkedList II

方法1:基于上面的三指针法,注意把需要保存的节点都保存一下

    public ListNode reverseBetween(ListNode head, int m, int n) {
        ListNode prevHead = null;
        int i = 1;
        ListNode curr = head;
        
        while(i<m){
            prevHead = curr;
            curr = curr.next;
            i++;
        }
        ListNode prev = null;
        ListNode next = null;
        
        ListNode reverseTail = curr;
        
        while(i<=n){
            next = curr.next;
            curr.next = prev;
            prev = curr;
            curr = next;
            i++;
        }
        reverseTail.next = curr;
        
        if(prevHead != null){
            prevHead.next = prev;
            return head;
        }else{
            return prev;    
        }
        
    }

方法2:基于虚拟头结点

    public ListNode reverseBetween(ListNode head, int m, int n) {
        ListNode dummyHead = new ListNode(-1);
        dummyHead.next = head;
        int i; 
        //找到反转部分的dummyHead
        for(i = 0; i < m - 1; i ++){
            dummyHead = dummyHead.next;    
        }
        ListNode reverseTail = dummyHead.next;
        ListNode curr = dummyHead.next;
        ListNode next;
        while(i < n){
            next = curr.next;
            curr.next = dummyHead.next;
            dummyHead.next = curr;
            curr = next;
            i++;
        }
        
        reverseTail.next = curr;
        if(reverseTail != head){
            return head;
        }else{
            return dummyHead.next;
        }
    }

Remove Duplicates from Sorted List

    public ListNode deleteDuplicates(ListNode head) {
        if(head == null){
            return null;
        }
        ListNode prev = head;
        ListNode curr = head.next;
        
        while(curr != null){
            if(prev.val == curr.val){
                ListNode delNode = curr;
                prev.next = delNode.next;
                curr = delNode.next;
                delNode.next = null;
            }else{
                prev = curr;
                curr = curr.next;
            }
        }
        
        return head;
    }

Partition List

    public ListNode partition(ListNode head, int x) {
        ListNode lessDummyHead = new ListNode(-1);
        ListNode moreDummyHead = new ListNode(-1);
        
        ListNode curr = head;
        ListNode moreCurr = moreDummyHead;
        ListNode lessCurr = lessDummyHead;
        while(curr != null){
            ListNode next = curr.next;
            
            if(curr.val < x){
                lessCurr.next = curr;
                lessCurr = lessCurr.next;
            }else{
                moreCurr.next = curr;
                moreCurr = moreCurr.next;
            }
            
            curr = next;
        }
        lessCurr.next = moreDummyHead.next;
        moreCurr.next = null;
        
        return lessDummyHead.next;
    }

Odd Even Linked List

    public ListNode oddEvenList(ListNode head) {
        ListNode oddDummyHead = new ListNode(-1);
        ListNode evenDummyHead = new ListNode(-1);
        
        ListNode evenCurr = evenDummyHead;
        ListNode curr = head;
        int i = 1;
        while(curr != null){
            ListNode next = curr.next;
            if((i & 1) == 1){
                oddDummyHead.next = curr;
                oddDummyHead = oddDummyHead.next;
            }else{
                evenCurr.next = curr;
                evenCurr = evenCurr.next;
            }
            curr = curr.next;
            i++;
        }
        
        oddDummyHead.next = evenDummyHead.next;
        evenCurr.next = null;
        
        return head;
    }

Add Two Numbers

    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode curr1 = l1;
        ListNode curr2 = l2;
        ListNode newHead = new ListNode(0);
        
        ListNode curr =newHead;
        int carry = 0;
        while(curr1!= null || curr2 != null){
            int x = curr1!=null?curr1.val:0;
            int y = curr2!=null?curr2.val:0;
            int sum = x + y + carry;
            carry =sum/10;
            curr.next = new ListNode(sum%10);
            
            curr = curr.next;
            if(curr1 != null)curr1 = curr1.next;
            if(curr2 != null)curr2 = curr2.next;
        }

        
        if(carry == 1){
            curr.next =new ListNode(1);
        }
        return newHead.next;
    }

Add Two NumbersII

这题可以不停手动reverse,但是用栈更美观一些感觉....

    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        Stack<Integer> s1 = new Stack<>();
        Stack<Integer> s2 = new Stack<>();
        
        ListNode curr1 = l1;
        ListNode curr2 = l2;
        
        while(curr1 != null){
            s1.push(curr1.val);
            curr1 = curr1.next;
        }
        
        while(curr2 != null){
            s2.push(curr2.val);
            curr2 = curr2.next;
        }
        
        ListNode dummyHead = new ListNode(0);
        int carry = 0;
        ListNode curr = dummyHead;
        Stack<Integer> s = new Stack<>();
        while((!s1.isEmpty()) || (!s2.isEmpty())){
            int x = s1.isEmpty()?0:s1.pop();
            int y = s2.isEmpty()?0:s2.pop();
            int sum = x + y + carry;
            
            carry = sum/10;
            s.push(sum%10);
        }
        
        if(carry == 1){
            s.push(1);
        }
        while(!s.isEmpty()){
            curr.next = new ListNode(s.pop());
            curr = curr.next;
        }
        
        
        return dummyHead.next;
              
    }

Remove Linked List Elements

设置虚拟头结点,这是链表中的常用的技巧,否则如果第一个节点满足条件,不使用dummyHead,那将需要对头结点特殊处理。

    public ListNode removeElements(ListNode head, int val) {
        ListNode dummyHead = new ListNode(0);
        dummyHead.next = head;
        ListNode prev = dummyHead;
        while(prev!=null){
            ListNode curr = prev.next;
            if(curr!=null && curr.val == val){
                prev.next = curr.next;
                curr.next = null;
            }else{
                prev = prev.next;
            }
        }
        
        return dummyHead.next;
    }

Remove Dumplicates from Sorted List

    public ListNode deleteDuplicates(ListNode head) {
        if(head == null){
            return null;
        }
        
        ListNode dummyHead = new ListNode(0);
        dummyHead.next = head;
        
        ListNode prev = dummyHead;
        ListNode curr = head;
        
        while(curr != null){
            ListNode next = curr.next;
            if(next != null && next.val == curr.val){
                while(next != null && next.val == curr.val){
                    ListNode delNode = next;
                    curr.next = delNode.next;
                    next = next.next;
                    delNode.next = null;
                }
                prev.next = next;
            }else{
                prev = curr;
            }
            
            curr = next;
        }
        
        return dummyHead.next;
    }

Swap Nodes In Pairs

    public ListNode swapPairs(ListNode head) {
        if(head == null){
            return null;
        }
        ListNode dummyHead = new ListNode(0);
        dummyHead.next = head;
        ListNode p = dummyHead;
        while(p != null && p.next != null){
            ListNode node1 = p.next;
            if(node1.next == null){
                break;
            }
            ListNode node2 = node1.next;
            
            ListNode next = node2.next;
            
            node2.next = node1;
            node1.next = next;
            p.next = node2;
            p = node1;
        }
        
        return dummyHead.next;
    }

Insertion Sort List

    public ListNode insertionSortList(ListNode head) {
        if(head == null){
            return null;
        }
        ListNode dummyHead = new ListNode(0);
        dummyHead.next = head;
        
        ListNode originNode = head.next;
        //把链表分割成两部分
        head.next = null;
        
        while(originNode != null){
            
            ListNode prevSorted = dummyHead;
            ListNode newNode = originNode;
            
            while(prevSorted.next != null && prevSorted.next.val <= newNode.val){
                prevSorted = prevSorted.next;
            }
            
            originNode = originNode.next;
            newNode.next = prevSorted.next;
            prevSorted.next = newNode;
        }
        
        return dummyHead.next;
    }

Remove Nth Node From End Of List

快慢指针法去找倒数第N个节点

    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummyHead = new ListNode(0);
        dummyHead.next = head;
        ListNode fast = dummyHead;
        ListNode slow = dummyHead;
        for(int i = 0; i < n; i ++){
            fast = fast.next;
        }
        
        while(fast.next!=null){
            fast = fast.next;
            slow = slow.next;
        }
        
        ListNode delNode = slow.next;
        slow.next = delNode.next;
        delNode.next = null;
        return dummyHead.next;
    }

Rotate List

这个题画几个图就能明白题意,其实就是把倒数K个旋转一下,挪到前头去,但是需要注意的问题是,K有可能大于节点数,所以先遍历一遍,因为k可能大于链表节点数,所以遍历一次拿到节点总数,再用k去求余。然后可以直接循环length - k%length次拿到倒数第K+1个节点,然后进行相关的更改指向的操作就可以了。

    public ListNode rotateRight(ListNode head, int k) {
        if(head == null || head.next == null || k == 0){
            return head;
        }    
        
        ListNode dummyHead = new ListNode(0);
        dummyHead.next = head;
        
        ListNode p = dummyHead;
        int length = 0;
        
        while(p.next!=null){
            p = p.next;
            length ++;
        }
        
        if(k%length == 0){
            return head;
        }
        
        ListNode tail = p;
        
        p = dummyHead;
        
        for(int i = 0; i < length - k%length; i++){
            p=p.next;
        }
        ListNode newHead = p.next;
        p.next = null;
        
        tail.next = dummyHead.next;
        dummyHead.next = newHead;
        return dummyHead.next;
    }

还有 143 和 148 234

Middle of the Linked List

快慢指针法去找中间节点,还是加上dummyHead更好理解一些。慢的一次走一步,快的一次走两步,那么快的走过的路就是慢的的两倍。奇数和偶数个节点有不同的返回情况,画个图分析一下就可以了。

    public ListNode middleNode(ListNode head) {
        ListNode dummyHead = new ListNode(0);
        dummyHead.next = head;
        ListNode fast = dummyHead;
        ListNode slow = dummyHead;
        while(fast != null && fast.next!=null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        if(fast == null){
            return slow;
        }
        return slow.next;
    }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容