刷题:Link

Carl
CyC2018

CyC2018

1、找到两个链表相交的点,L160

    // 思路: a + c + b = b + c + a 
    public class Solution {
        public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
            ListNode p1 = headA;
            ListNode p2 = headB;
            while(p1 != p2) {
                p1 = p1 == null ? headB : p1.next;
                p2 = p2 == null ? headA : p2.next;
            }
            return p1;
        }
    }

2、链表反转,L206

    // 思路:利用循环指针去反转链表,一个个链接反转
    class Solution {
        public ListNode reverseList(ListNode head) {
            if (head == null) return null;
            ListNode pre = null;
            ListNode cur = head;
            while (cur.next != null) {
                ListNode next = cur.next;
                cur.next = pre;
                pre = cur;
                cur = next;
            }
            cur.next = pre;
            return cur;
        }
    }

    // 思路:递归处理
    class Solution1 {
        public ListNode reverseList(ListNode head) {
            if (head == null || head.next == null) return head;
            ListNode ret = reverseList(head.next);
            head.next.next = head;
            head.next = null;
            return ret;
        }
    }

3、归并两个有序的链表,L21

    // 思路:递归
    class Solution {
        public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
            if (l1 == null)
                return l2;
            if (l2 == null)
                return l1;
            if (l1.val > l2.val) {
                l2.next = mergeTwoLists(l1, l2.next);
                return l2;
            } else {
                l1.next = mergeTwoLists(l1.next, l2);
                return l1;
            }
        }
    }

    // 思路:迭代,用两个循环变量指针,和一个指向合并结果的指针作为循环变量
    class Solution1 {
        public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
            if (l1 == null) return l2;
            if (l2 == null) return l1;
            ListNode res = new ListNode(-1);
            ListNode p = res;
            while (l1 != null && l2 != null) {
                if (l1.val > l2.val) {
                    p.next = l2;
                    l2 = l2.next;
                } else {
                    p.next = l1;
                    l1 = l1.next;
                }
                p = p.next;
            }
            if (l1 != null) p.next = l1;
            if (l2 != null) p.next = l2;
            return res.next;
        }
    }

4、从有序链表中删除重复节点,L83

// 用pre慢指针和快指针做比较,判断是否相等
class Solution {
        public ListNode deleteDuplicates(ListNode head) {
            if (head == null) return head;
            ListNode pre = head;
            ListNode p = head.next;
            while (p != null) {
                if (p.val == pre.val) {
                    pre.next = p.next;
                } else {
                    pre = p;
                }
                p = p.next;
            }
            return head;
        }
    }

    // 思路:递归
    class Solution1 {
        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;
        }
    }

5、删除链表的倒数第 n 个节点,L19

    // 思路:用快慢指针,快指针比满指针快n步,当fast.next == null时,说明slow指向倒数前n个指针的前一个
    class Solution {
        public ListNode removeNthFromEnd(ListNode head, int n) {
            ListNode fast = head;
            while (n-- > 0) {
                fast = fast.next;
            }
            if (fast == null) {
                return head.next;
            }
            ListNode slow = head;
            while (fast.next != null) {
                fast = fast.next;
                slow = slow.next;
            }
            slow.next = slow.next.next;
            return head;
        }
    }

6、交换链表中的相邻结点,L24

    // 注意要考虑前一个节点,设立一个虚头结点作为最开始的pre指针,并以此为循环变量
    class Solution {
        public ListNode swapPairs(ListNode head) {
            if (head == null || head.next == null) return head;
            ListNode newHead = new ListNode(-1);
            newHead.next = head;
            ListNode pre = newHead;

            while (pre.next != null && pre.next.next != null) {
                ListNode l1 = pre.next;
                ListNode l2 = pre.next.next;
                l1.next = l2.next;
                l2.next = l1;
                pre.next = l2;
                pre = l1;
            }
            return newHead.next;
        }
    }

7、链表求和,L445

    // 先反转列表然后在运算,得到结果在反转,比用栈快
    class Solution {
        public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
            l1 = reverseList(l1);
            l2 = reverseList(l2);
            int carry = 0;
            ListNode newHead = new ListNode(-1);
            ListNode p = newHead;
            while (l1 != null || l2 != null || carry != 0) {
                int x = 0;
                int y = 0;
                if (l1 != null) {
                    x = l1.val;
                    l1 = l1.next;
                }
                if (l2 != null) {
                    y = l2.val;
                    l2 = l2.next;
                }
                int sum = x + y + carry;
                ListNode newNode = new ListNode(sum % 10);
                p.next = newNode;
                p = p.next;
                carry = sum / 10;
            }

            return reverseList(newHead.next);
        }

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

8、回文链表,L234

    // 快慢指针,然后反转后半部分进行比较,注意快慢指针的起始值,快慢指针效率最高
    class Solution {
        public boolean isPalindrome(ListNode head) {
            if (head == null || head.next == null) return true;
            ListNode fast = head.next;
            ListNode slow = head;
            while (fast != null && fast.next != null) {
                fast = fast.next.next;
                slow = slow.next;
            }
            slow = slow.next;

            ListNode newHead = reverseList(slow);
            while (newHead != null) {
                if (newHead.val != head.val) return false;
                head = head.next;
                newHead = newHead.next;
            }
            return true;
        }
        public ListNode reverseList(ListNode head) {
            ListNode newHead = new ListNode(-1);
            while (head != null) {
                ListNode next = head.next;
                head.next = newHead.next;
                newHead.next = head;
                head = next;
            }
            return newHead.next;
        }
    }

    // 递归解法二,用类变量记录
    class Solution2 {
        private ListNode front;
        public boolean isPalindrome(ListNode head) {
            front = head;
            return palindrome(head);
        }
        public boolean palindrome(ListNode curNode) {
            if (curNode != null) {
                if (!palindrome(curNode.next)) {
                    return false;
                }
                if (curNode.val != front.val) {
                    return false;
                }
                front = front.next;
            }
            return true;
        }
    }

    // 递归解法,很巧妙,不用反转列表,但是时间和空间效率不高
    class Solution1 {
        public boolean isPalindrome(ListNode head) {
            if (head == null || head.next == null) {
                return true;
            }
            ListNode newHead = new ListNode(-1);
            newHead.next = head;
            return palindromeList(head, newHead);
        }

        public boolean palindromeList(ListNode h1, ListNode h2) {
            if (h1 == null) {
                return true;
            }
            boolean first = palindromeList(h1.next, h2);
            boolean second;
            if (h1.val == h2.next.val) {
                second = true;
                h2.next = h2.next.next;
            } else {
                second = false;
            }
            return second && first;
        }
    }

9、分隔链表,L725

    // 优化循环,注意最后切断的时候置为null
    class Solution {
        public ListNode[] splitListToParts(ListNode head, int k) {
            ListNode[] res = new ListNode[k];
            ListNode p = head;
            int length = 0;
            while (p != null) {
                length++;
                p = p.next;
            }
            int size = length / k;
            int mod = length % k;
            for (int i = 0; i < k && head != null; i++) {
                int curSize = size + (mod-- > 0 ? 1 : 0);
                res[i] = head;
                for (int j = 1; j < curSize; j++) {
                    head = head.next;
                }
                ListNode next = head.next;
                head.next = null;
                head = next;
            }
            return res;
        }
    }

10、链表元素按奇偶聚集,L328

    // 记录odd,even的尾指针
    class Solution {
        public ListNode oddEvenList(ListNode head) {
            if (head == null || head.next == null) return head;
            ListNode odd = head;
            ListNode even = head.next;
            ListNode evenHead = even;

            while (even != null && even.next != null) {
                odd.next = odd.next.next;
                even.next = even.next.next;
                odd = odd.next;
                even = even.next;
            }
            odd.next = evenHead;
            return head;
        }
    }

Carl

1、移除链表中的元素,L203

// 迭代实现
class Solution {
    public ListNode removeElements(ListNode head, int val) {
        ListNode newHead = new ListNode(-1);
        newHead.next = head;
        ListNode p = newHead;
        while (p != null && p.next != null) {
            if (p.next.val == val) {
                p.next = p.next.next;
            } else {
                p = p.next;
            }
        }
        return newHead.next;
    }
}

// 递归
class Solution {
    public ListNode removeElements(ListNode head, int val) {
        if (head == null) return null;
        head.next = removeElements(head.next, val);
        return head.val == val ? head.next : head;
    }
}

2、环形链表入口,L142

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

推荐阅读更多精彩内容