leetcode-链表-第一周

leetcode

leetcode-141-环形链表

题目大意:给定一个链表,判断该链表是存在环;

1、快慢指针

  • 设定一个快指针,一个慢指针。

  • 若有环,且慢指针在环外,快指针出不去,将一直在环中循环,直到慢指针入环,被快指针追上,相遇;

  • 若无环,快指针将到达链表尾部;


public class Solution {

    public boolean hasCycle(ListNode head) {

        if(head == null || head.next == null)return false;

        ListNode fast = head;

        ListNode slow = head;

        while(fast != null && fast.next != null){

            fast = fast.next.next;

            slow = slow.next;

            if(fast == slow)return true;

        }

        return false;

    }

}

2、哈希 set

  • 若有环,环内节点会走到两次或以上;

public class Solution {

    public boolean hasCycle(ListNode head) {

        if(head == null || head.next == null)return false;

        Set<ListNode> set = new HashSet<>();

        while(head != null){

            if(set.add(head));

            else return true;

            head = head.next;

        }

        return false;

    }

}

leetcode-160-相交链表

题目大意:找到两个链表的相交的起始节点

如下图节点

此节点为 c1;

1、 暴力解法


public class Solution {

    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {

        if(headA == null || headB == null)return null;

        for(ListNode la = headA; la != null; la = la.next){

            for(ListNode lb = headB; lb != null; lb = lb.next){

                if(la == lb)return la;

            }

        }

        return null;

    }

}

2、 双指针

  • a = a 非共同部分的长度,

  • b = b 非共同部分的长度

  • all =共同部分的长度

  • 故 a+b+all = b+a=all

  • 则可用双指针,当指针 a 循环完 a 链表则调到 b 链表首,当 a 第二次经过共同部分时,b 肯定也恰好到达共同部分;


public class Solution {

    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {

        if(headA == null || headB == null)return null;

        ListNode la = headA,lb = headB;

        boolean f = false;

        while(la != null){

            if(la == lb)return la;

            la = la.next;

            lb = lb.next;

            if(la == null && !f){

                f = !f;

                la = headB;

            }

            if(lb == null)lb = headA;

        }

        return null;

    }

}

leetcode-203-移除链表

题意:删除链表中的一个值;

ps:我的思路简单循环即可,但是自己的代码很蠢;


class Solution {

    public ListNode removeElements(ListNode head, int val) {

        while(head != null && head.val == val )head = head.next;

        if(head == null)return null;

        ListNode q, pre = head;//可以只用p.next省略掉麻烦的pre;

        if(head.next != null) q = head.next;

        else return head;

        while(q != null){

            if(q.val == val){//如果此节点要删除,则pre节点不动;

                pre.next = q.next;

                q = q.next;

            }

            else{

                pre = q;

                q = q.next;

            }

        }

        return head;

    }

}

用 q.next 代替 q, q 代替 pre;少写一个 pre,代码简介易懂,还不麻烦;


class Solution {

    public ListNode removeElements(ListNode head, int val) {

        while(head != null && head.val == val )head = head.next;

        if(head == null)return null;

        ListNode q = head;

        while(q.next != null){

            if(q.next.val == val){

                q.next = q.next.next;

            }

            else{

                q = q.next;

            }

        }

        return head;

    }

}

递归做法,现在对递归的掌握还没熟练的应用进各个习题,对每个题目的第一个反应就是暴力,自己很愚蠢,总学不会(哪有总是学,天天玩。分明就是自己不刷题),慢慢来吧;


class Solution {

    public ListNode removeElements(ListNode head, int val) {

        if(head == null)return null;

        head.next = removeElements(head.next,val);//通过该函数的返回值,一个个连起来;

        if(head.val == val)return head.next;

        return head;

    }

}

leetcode-206-反转链表

示例:

**输入**: 1->2->3->4->5->NULL

**输出**: 5->4->3->2->1->NULL

愚蠢的我,还是不会做递归


class Solution {

    public ListNode reverseList(ListNode head) {

        if(head == null)return null;

        ListNode prev = null, curr = head;

        while(curr != null){

            ListNode temp = curr.next;

            curr.next = prev;

            prev = curr;

            curr = temp;

        }

        return prev;

    }

}

2、递归

leetcode 官方题解:

假设列表为:

n1​→…→ nk−1 ​→ nk ​→ nk+1​ →…→ nm ​→ ∅

节点 nm - nk+1 已经反转,我们在 nk 位置;

n1 ​→…→ nk−1 ​→ nk ​→ nk+1 ​←…← nm

我们希望 nk+1 的下一个节点指向 nk​。

所以,nk​.next.next = nk​。

要小心的是 n1​ 的下一个必须指向 Ø 。如果你忽略了这一点,你的链表中可能会产生循环。如果使用大小为 2 的链表测试代码,则可能会捕获此错误。

刚学的递归,这题又没想出来。想到用递归,确不知道怎么做


class Solution {

    public ListNode reverseList(ListNode head) {

        if(head == null || head.next == null)return head;

        ListNode p = reverseList(head.next);

        head.next.next = head;

        head.next = null;

        return p;

    }

}

leetcode-234-回文链表

**示例 1:

输入: 1->2

输出: false

输入: 1->2->2->1

输出: true

双指针牛批大法:

利用快慢指针,将前半段反转;


class Solution {

    public boolean isPalindrome(ListNode head) {

        if(head == null || head.next == null)return true;

        ListNode fast = head,slow = head;

        ListNode pre = head, prepre = null;

        while(fast != null && fast.next != null){

            pre = slow;

            slow = slow.next;

            fast = fast.next.next;

            pre.next = prepre;

            prepre = pre;

        }

        if(fast != null)slow = slow.next;//当为奇数时,跳过中间的数;

        while(pre != null && slow != null){

            if(pre.val != slow.val)return false;

            pre = pre.next;

            slow = slow.next;

        }

        return true;

    }

}

leetcode-876-链表的中间节点

题意:

删除链表的中间节点,当为偶数数时,删除第二个中间节点;

ps:利用上一道题的快慢指针很好做,正好学到;


class Solution {

    public ListNode middleNode(ListNode head) {

        ListNode fast = head,slow = head;

        while(fast != null && fast.next != null){

            fast = fast.next.next;

            slow = slow.next;

        }

        return slow;

    }

}

另一种解法是将其链表全部放入数组,然后返回 a[length/2];

leetcode-1290-二进制的链转整数

输入:head = [1,0,1] > 输出:5

解释:二进制数 (101) 转化为十进制数 (5)


class Solution {

    public int getDecimalValue(ListNode head) {

        int ans = 0 , cnt = 1;

        ListNode p = reverseList(head);

        while(p != null){

            ans += p.val * cnt;

            cnt *= 2;

            p = p.next;

        }

        return ans;

    }

    public ListNode reverseList(ListNode head){

        if(head == null || head.next == null) return head;

        ListNode p = reverseList(head.next);

        head.next.next = head;

        head.next = null;

        return p;

    }

}

熟悉了下反转操作。最后看题解可以不反转,人啊,我的第一反应就是先反转链表,曰了;

我好蠢


class Solution {

    public int getDecimalValue(ListNode head) {

        int ans = 0;

        while(head != null){

            ans = ans * 2 + head.val;

            head = head.next;

        }

        return ans;

    }

}

leetcode-19-删除链表的倒数第 N 个节点

示例

给定一个链表: 1->2->3->4->5, 和 n = 2.

当删除了倒数第二个节点后,链表变为 1->2->3->5.

利用前面学的递归知识,真是很开心的就用上了,fighting!!


class Solution {

    int idx = 0;

    public ListNode removeNthFromEnd(ListNode head, int n) {

        if(n == 0)return head;

        if(head == null)return null;

        head.next = removeNthFromEnd(head.next,n);

        idx ++;

        if(idx == n)return head.next;

        return head;

    }

}

官方题解:双指针

利用快指针先走 n+1 步,最后快指针到末尾时,慢指针刚好到达要删的节点之前;


class Solution {

    public ListNode removeNthFromEnd(ListNode head, int n) {

        ListNode dump = new ListNode(0);//创建一个dump是防止快指针走n+1步后超过null 和 方便删除头结点,因为由题得n不会大于head的长度。

        dump.next = head;

        ListNode slow = dump, fast = dump;

        for(int i = 0; i <= n ; i++){

            fast = fast.next;

        }

        while(fast != null){

            fast = fast.next;

            slow = slow.next;

        }

        slow.next = slow.next.next;

        return dump.next;

    }

}

leetcode-24-两两交换链表中的结点


给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。

你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

给定 1->2->3->4, 你应该返回 2->1->4->3.


class Solution {

    public ListNode swapPairs(ListNode head) {

        ListNode dump = new ListNode(0);//利用上一题的思想。

        dump.next = head;

        ListNode head1 = head,prev = dump;

        while(head1 != null && head1.next != null){

            ListNode temp = head1.next.next;

            prev.next = head1.next;

            head1.next.next = head1;

            head1.next = temp;

            prev = head1;

            head1 = temp;

        }

        return dump.next;

    }

}

递归做法:


class Solution {

    public ListNode swapPairs(ListNode head) {

        if(head == null || head.next == null)return head;

        ListNode next = head.next;

        head.next = swapPairs(next.next);//上一个结点的下一个指向返回的这个

        next.next = head;//第二个结点指向第一个结点;

        return next;//返回值,为第二个结点

    }

}

发布了97 篇原创文章 · 获赞 3 · 访问量 9418

猜你喜欢

转载自blog.csdn.net/foolishpichao/article/details/103801237
今日推荐