2020年发生了湖北武汉肺炎疫情,居家不外出,so,每天按系列刷一些经典的题目。今天先从链表的5道题目走起。


206. Reverse Linked ListEasy

题目:翻转一个单链表。

Example:

 1->2->3->4->5->NULL

参考代码:

class Solution {    public ListNode reverseList(ListNode head) {        if(head==null || head.next==null)            return head;        ListNode pre = null;        ListNode p = head;        ListNode next;        while(p!=null){            next = p.next;            p.next = pre;            pre = p;            p= next;        }        return pre;    }}


160. Intersection of Two Linked Lists(Easy)

题目:求两个单链表的交点

举例:A链表和B链表有交叉点,返回值为c1。

Leetcode刷题之链表系列_java

思路1:暴力解法,两层循环,如果找到返回节点。否则返回空。

思路2:利用哈希表,遍历一个链表,存储到set集合中。然后遍历另一个链表,如果该节点在set中,则直接返回这个节点。遍历完没找到,则返回空。

思路3:计算两个链表的长度分别为m和n,长度较大的链表先走abs(m-n)步,然后两个链表一起往后走,判断节点是否相等。

参考代码(思路3):

public ListNode getIntersectionNode(ListNode headA,                          ListNode headB) {         int m= lengthOfList(headA);         int n =lengthOfList(headB);         ListNode pA = headA;         ListNode pB = headB;         if(m>n){//先走m-n步         int k = m-n;         for(int i=1;i<=k;i++)            pA = pA.next;        }         else{ //先走n-m步           int k = n-m;           for(int i=1;i<=k;i++)                pB = pB.next;        }        while(pA!=null && pB!=null){             if(pA==pB)                 return pA;            pA =pA.next;            pB =pB.next;        }       return null;    }public int lengthOfList(ListNode head){//辅助函数         if(head==null) return 0;         int mCount =0;         ListNode p = head;         while(p!= null){            mCount++;            p = p.next;        }    return mCount;}

141. Linked List Cycle(Easy)

题目:判断一个链表是否有环

举例:如下链表,-4节点的下一个节点又是2节点,返回true。


思路:采用快慢指针,快指针每次走两步,慢指针走一步,如果相遇则存在环。如果快指针遇到空结束,则返回false。

参考代码如下:

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

142. Linked List Cycle II(medium)

题目:返回一个带环链表的起始节点

举例:如下链表,-4节点的下一个节点又是2节点,返回2节点。

Leetcode刷题之链表系列_java_02

思路:使用快慢指针,相遇点到链表头节点的距离等于头结点到链表起始节点的距离。于是,我们从head节点和相遇点开始依次各走一步,直到再次相遇,这个点就是起始点。

参考代码如下:

 public ListNode detectCycle(ListNode head) {        if(head==null)            return null;        ListNode slow =head;        ListNode fast = head;        while(fast!=null && fast.next!=null){//先找到相遇点            slow = slow.next;            fast = fast.next.next;            if(fast == slow)                break;        }        if(fast==null ||fast.next ==null) //没有环            return null;        slow = head; //将slow从head节点开始遍历        while(slow!=fast){            slow = slow.next;            fast = fast.next;        }        return slow;    }

287. Find the Duplicate Number(Medium)

题目:寻找数组中的重复元素,元素个数n+1,每个元素取值范围为1-n。

举例:

 
 2

思路1:采用暴力求解法,两层for循环,如果找到返回对应元素。否则返回0 代表没找到。

思路2:采用哈希表法,遍历每个元素,去哈希表中查找看看是否存在,如果存在直接返回该元素。否则,将该元素加入哈希表中。

思路3:不断将当前元素值作为下一个下标,能得到一个数组环,见下面示例。然后使用快慢指针分别指向数组尾部, 快指针执行两次,慢指针执行一次直到快慢指针相遇。最后让慢指针从尾节点开始,依次和快指针每次走一步,当相遇的时候即重复的元素。整个解题的思路和上面这个循环链表的初始节点题目(141题)思路一样。

Leetcode刷题之链表系列_java_03

Leetcode刷题之链表系列_java_04

参考代码如下:

public int findDuplicate(int[] nums) {        if(nums==null||nums.length<=0)            return 0;        int n=nums.length;//数组长度        int slow =n-1;        int fast = n-1;        while(true){            slow = nums[slow]-1;//慢指针走一步            fast = nums[fast]-1;//快指针走两步            fast  =nums[fast]-1;            if(slow == fast)                break;        }        slow = n-1;        while(slow!=fast){            slow = nums[slow]-1;            fast = nums[fast]-1;        }        return slow+1;    }

总结: 今天先刷5道题目,这种链表环的思路很值得总结和体会。