【leetcode】Linked List —— easy(java)

来源:互联网 发布:生死疲劳 知乎 编辑:程序博客网 时间:2024/05/19 18:10

链表easy部分包括内容有:

  1. 判断是否存在环、判断是否是回文;
  2. 删除给定结点、删除倒数第n个结点、删除重复结点、删除值与给定值相等的结点;
  3. 反转单链表、拼接两个有序链表、交换每两个相邻结点、找出两个链表有交集的起点。

【141】 Linked List Cycle

  • 题目
    Given a linked list, determine if it has a cycle in it.
    Follow up:
    Can you solve it without using extra space?
    给定一个链表,判断它是否存在环。(不用额外的空间)

  • 思路
    快慢指针。若存在环,则快指针必定在某一刻超过慢指针一圈,即追上慢指针。

  • 代码

public class Solution {    public boolean hasCycle(ListNode head) {        if (head == null || head.next == null) {            return false;        }        ListNode slow = head;        ListNode fast = head.next;        while (fast != null && fast.next != null) {            if (slow == fast) {                return true;            } else {                slow = slow.next;                fast = fast.next.next;            }        }        return false;    }}

【234】Palindrome Linked List

  • 题目
    Given a singly linked list, determine if it is a palindrome.
    Follow up:
    Could you do it in O(n) time and O(1) space?
    给定单链表,判断是不是回文。(用O(n)的时间复杂度和O(1)的空间复杂度)

  • 思路
    如果没有限定O(1)的空间复杂度,则可以利用栈或者利用容器。而此刻有限定,则只能反转链表后再进行判定。

  • 代码

public class Solution {    public boolean isPalindrome(ListNode head) {        if (head == null || head.next == null) {            return true;        }        ListNode med = head;        ListNode tail = head.next;        while (tail != null && tail.next != null) {            med = med.next;            tail = tail.next.next;        }        if (tail == null) {//是奇数个            tail = reverseList(med);        } else {//是偶数个            tail = reverseList(med.next);        }        while (head != med.next) {            if (head.val != tail.val) {                return false; //之前忘了是值比较            } else {                head = head.next;                tail = tail.next;            }        }        return true;    }    ListNode reverseList(ListNode head) {        if (head == null || head.next == null) {            return head;        }        ListNode pre = head;        ListNode cur = head.next;        ListNode q;        while (cur.next != null) {            q = cur.next;            cur.next = pre;            pre = cur;            cur = q;        }        cur.next = pre;        return cur;    }}

离bug free差一步:忘了是值比较(代码中打注释的语句)


【237】 Delete Node in a Linked List

  • 题目
    Write a function to delete a node (except the tail) in a singly linked list, given only access to that node.
    Supposed the linked list is 1 -> 2 -> 3 -> 4 and you are given the third node with value 3, the linked list should become 1 -> 2 -> 4 after calling your function.
    在链表中删除给定结点,该结点不为最后一个。

  • 思路
    给定结点node,设node的下一个结点为p,则把p的值赋给node,然后删去结点p即可。

  • 代码
public class Solution {    public void deleteNode(ListNode node) {        ListNode p = node.next;        node.val = p.val;        node.next = p.next;    }}

【19】Remove Nth Node From End of List

  • 题目
    Given a linked list, remove the nth node from the end of list and return its head.
    For example,
    Given linked list: 1->2->3->4->5, and n = 2.
    After removing the second node from the end, the linked list becomes 1->2->3->5.
    给定一个链表,删除这个链表的倒数第n个结点并且返回它的头。

  • 思路
    用两个指针找到要删除结点的前一个结点,将两个指针间距设置为n,当后面一个指针到尾结点,前面一个指针的位置就是我们要找的,然后删除需要删除的结点。【对于删除第一个结点的情况,一种方法是单独考虑,另一种方法是加头结点】

  • 代码

public class Solution {    public ListNode removeNthFromEnd(ListNode head, int n) {        if (head == null) {            return null;        }        ListNode p = head;        ListNode q = head;        while (n > 0) {            q = q.next;            n--;        }        if (q == null) {            return head.next; //删除第一个结点的情况        }        while (q.next != null) {            p = p.next;            q = q.next;        }        p.next = p.next.next;        return head;    }}

距离bug free差一步:忘了考虑删除第一个结点的情况。


【83】Remove Duplicates from Sorted List

  • 题目
    Given a sorted linked list, delete all duplicates such that each element appear only once.
    For example,
    Given 1->1->2, return 1->2.
    Given 1->1->2->3->3, return 1->2->3.
    给定一个排好序的链表,删除所有重复的结点。

  • 思路
    设置p=head,若p的值和p的下一个结点的值相等则删去p的下一个结点,若不等则p指向下一个结点。

  • 代码
public class Solution {    public ListNode deleteDuplicates(ListNode head) {        if (head == null || head.next == null) {            return head;        }        ListNode p = head;        while (p.next != null) {            if (p.val == p.next.val) {                p.next = p.next.next;            } else {                p = p.next;            }        }        return head;    }}

【203】Remove Linked List Elements

  • 题目
    Remove all elements from a linked list of integers that have value val.
    Example
    Given: 1 –> 2 –> 6 –> 3 –> 4 –> 5 –> 6, val = 6
    Return: 1 –> 2 –> 3 –> 4 –> 5
    删除链表中所有值与给定值相等的结点。

  • 思路
    设置头结点,让p的下一个结点的值与给定值相比较,若相等则删除p的下一个结点,否则p指向下一个结点。

  • 代码
public class Solution {    public ListNode removeElements(ListNode head, int val) {        if (head == null) {            return null;        }        ListNode newhead = new ListNode(0);        newhead.next = head;        ListNode p = newhead;        while (p.next != null) {            if (p.next.val == val) {                p.next = p.next.next;            } else {                p = p.next;            }        }        return newhead.next;    }}

【206】 Reverse Linked List

  • 题目
    Reverse a singly linked list.
    Hint:
    A linked list can be reversed either iteratively or recursively. Could you implement both?
    反转单链表。(要求迭代与递归的方式都会)

  • 思路
    通过s和head反转,用temp暂存下一个要反转的结点。

  • 代码(迭代)

public class Solution {    public ListNode reverseList(ListNode head) {        ListNode s = null;        while (head != null) {            ListNode temp = head.next;            head.next = s;            s = head;            head = temp;        }        return s;    }}
  • 代码(递归)
public class Solution {    public ListNode reverseList(ListNode head) {        if (head == null) {            return head;        }        ListNode newhead = head;        while (head.next != null) {            head = head.next;        }        reverse(newhead);        return head;    }    ListNode reverse(ListNode l) {        if (l.next == null) {            return l;        }        ListNode tail = reverse(l.next);        tail.next = l;        l.next = null;        return l;    }}

【21】Merge Two Sorted Lists

  • 题目
    Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.
    合并两个排序的链表,并将其作为新链表返回。 新链表应该通过将前两个链表的结点拼接在一起来进行。

  • 思路
    比较2个链表中指针结点的值的大小,小的接入新链表,并指向下一个结点,继续进行比较,直到所有结点都接入新链表。

  • 代码

public class Solution {    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {        ListNode head = new ListNode(0);        ListNode p = head;        while (l1 != null && l2 != null) {            if (l1.val < l2.val) {                p.next = l1;                l1 = l1.next;            } else {                p.next = l2;                l2 = l2.next;            }            p = p.next; //忘了这步        }        if (l1 == null) {            p.next = l2;        } else if (l2 == null) {            p.next = l1;        }        return head.next;    }}

离bug free 还差一步:忘了p=p.next;


【*24】Swap Nodes in Pairs

  • 题目
    Given a linked list, swap every two adjacent nodes and return its head.
    For example,
    Given 1->2->3->4, you should return the list as 2->1->4->3.
    Your algorithm should use only constant space. You may not modify the values in the list, only nodes itself can be changed.
    给定一个链表,交换每两个相邻结点并且返回头。

  • 思路
    加入头结点,方便统一步骤进行循环。利用3个指针进行交换及向后遍历。

  • 代码

public class Solution {    public ListNode swapPairs(ListNode head) {        ListNode newhead = new ListNode(0);        newhead.next = head;        ListNode pre = newhead;        while (pre.next != null && pre.next.next != null) {            ListNode p1 = pre.next;            ListNode p2 = p1.next;            pre.next = p2;            p1.next = p2.next;            p2.next = p1;            pre = p1;        }        return newhead.next;    }}

【*160】Intersection of Two Linked Lists

  • 题目
    Write a program to find the node at which the intersection of two singly linked lists begins.
    Notes:
    If the two linked lists have no intersection at all, return null.
    The linked lists must retain their original structure after the function returns.
    You may assume there are no cycles anywhere in the entire linked structure.
    Your code should preferably run in O(n) time and use only O(1) memory.
    找到两个单链表的交集开始的结点。

  • 思路
    把链表A的尾结点指向链表B的头结点,则形成了一个带环的链表C(如果两个链表有交汇点,则必定有环)。这样题目就转化为求环的起始位置的问题了,即【142】 Linked List Cycle II问题。对于链表C,设置快慢指针,慢指针走一步而快指针走两步,当慢指针走了m步到达环起始位置的时候,快指针走了2m步,超出了起始位置m步,设环共有N个结点,则快指针要比慢指针多走N-m步才能追上慢指针。所以当追上的时候,快慢指针都在距离起始位置N-m步的位置,这时,指针再走m步就能到达起始位置。所以重新令慢指针到头结点位置,快指针在原地,用同样的步调向前走,两个指针重合的位置就是环的起始位置。

  • 代码

public class Solution {    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {        if (headA == null || headB == null) {            return null;        }        ListNode head = headA;        while (head.next != null) {            head = head.next;        }        head.next = headB;        ListNode result = listCycleII(headA);        head.next = null;        return result;    }    private ListNode listCycleII(ListNode head) {        ListNode slow = head;        ListNode fast = head.next;        while (slow != fast) {            if (fast == null || fast.next == null) {                return null;            }            slow = slow.next;            fast = fast.next.next;        }        slow = head;        fast = fast.next;        while (slow != fast) {            fast = fast.next;            slow = slow.next;        }        return slow;    }}
0 0