链表算法整理

来源:互联网 发布:航天数据股份有限公司 编辑:程序博客网 时间:2024/06/11 01:33

目录

1.LeetCode141 Linked List Cycle(判断链表是否带环)

2.LeetCode142 Linked List Cycle II(判断带环链表起始位置)

3.反转链表

4.合并排序链表(剑指Offer)

5.倒数第k个节点(剑指Offer)

6.LeetCode83 Remove Duplicates from Sorted List(删除排序链表中的重复元素)

7.LeetCode82 Remove Duplicates from Sorted List II(删除排序链表的重复元素2)

8.约瑟夫环

9.LeetCode21 Merge Two Sorted Lists(合并排序链表)


1.LeetCode141 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?

解答:

/** * Definition for singly-linked list. * class ListNode { *     int val; *     ListNode next; *     ListNode(int x) { *         val = x; *         next = null; *     } * } */public class Solution {    public boolean hasCycle(ListNode head) {      if((head==null)||(head.next==null))         return false;         ListNode fast=head,slow=head;          while(fast!=null&&fast.next!=null){          fast=fast.next.next;          slow=slow.next;          if(fast==slow) return true;}          return false;    }}


两个结点,slow每次前进一步,fast每次前进二步,如果链表存在环,则fast必定先进入环,而slow后进入环,两个指针必定相遇。(当然,fast先行头到尾部为NULL,则为无环链表),这里也要注意while的条件,防止出现空指针异常

另外一个链表带环问题:

求链表环起始位置

2.LeetCode142 Linked List Cycle II(判断带环链表起始位置)

Given a linked list, return the node where the cycle begins. If there is no cycle, return null.

Note: Do not modify the linked list.

Follow up:
Can you solve it without using extra space?

/**  * Definition for singly-linked list.  * class ListNode {  *     int val;  *     ListNode next;  *     ListNode(int x) {  *         val = x;  *         next = null;  *     }  * }  */  public class Solution {              public ListNode detectCycle(ListNode head) {                  ListNode slow = head;                  ListNode fast = head;                            while (fast!=null && fast.next!=null){                      fast = fast.next.next;                      slow = slow.next;                                            if (fast == slow){                          ListNode slow2 = head;                           while (slow2 != slow){                              slow = slow.next;                              slow2 = slow2.next;                          }                          return slow;                      }                  }                  return null;              }          }  

假设慢指针走了S,则快指针走了2S,慢指针最多转一圈,快指针最少转一圈。


 s = a + x;
 2s = a + nr + x;
 =>a + x = nr;                     =>a = nr - x;

我们可以推导一下:

n=1  a=r-x  

n=2  a=2r-x=r+r-x     如果同时走的化,一个新指针从head出发走r+r-x,则慢节点也会走r+r-x,转一圈再走了r-x的距离,正是在入口相遇。
……

3.反转链表

输入一个链表,反转链表后,输出链表的所有元素。

/* public class ListNode {     int val;     ListNode next = null;      ListNode(int val) {         this.val = val;     } }*/  public class Solution {      public ListNode ReverseList(ListNode head) {          if(head==null)              return null;             ListNode pre = null;             ListNode next = null;          while(head!=null){              next=head.next; //防止head.next结点丢失              head.next=pre;  //可以放心把head.next指向前一节点了              pre=head;       //然后把pre 和 head往后移一位              head=next;                }      return pre; //当head是空的时候,返回pre就可以了  }}  
4.合并排序链表(剑指Offer)
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

/* public class ListNode {     int val;     ListNode next = null;      ListNode(int val) {         this.val = val;     } }*/  public class Solution {      public ListNode Merge(ListNode list1,ListNode list2) {          if(list1==null)              return list2;          if(list2==null)              return list1;          ListNode t=null;          if(list1.val<list2.val)             {               t=list1;               t.next=Merge(list1.next,list2);                      }          else              {              t=list2;              t.next= Merge(list1,list2.next);              }          return t;      }  }  
5.倒数第k个节点(剑指Offer)
/* public class ListNode {     int val;     ListNode next = null;      ListNode(int val) {         this.val = val;     } }*/  public class Solution {      public ListNode FindKthToTail(ListNode head,int k) {           if(head==null||k==0)            return null;                              //防止链表是空   或者倒数第0个结点        ListNode p1=head;                             //倒数越界        ListNode p2=head;                                     int i=1;        while(i<k){                                        //从1个节点去第k个节点,就是往前走k-1步            if(p1.next==null)                              //主要是防止K大于了链表的长度,p1.next是空,说明将要越界了。                return null;            p1=p1.next;            i++;        }        while(p1.next!=null){            p1=p1.next;            p2=p2.next;        }        return p2;        }  }  
这个题的思路是设立两个结点,让第一个先走到k节点,然后两个节点同时往后走,当第一个结点走到最后一个结点时,第二个正好走到倒数第K个节点。
1 2 3 4 5  求倒数第2个节点    2  1      3    2        4      3          5        4  
6.LeetCode83 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.

注意:这里是排序好的!

/**  * Definition for singly-linked list.  * public class ListNode {  *     int val;  *     ListNode next;  *     ListNode(int x) { val = x; }  * }  */    class Solution {      public ListNode deleteDuplicates(ListNode head) {          if(head==null||head.next==null)           return head;                     //     如果链表为空或只有一个节点,返回null或这个节点就可以          ListNode temp=head;                                while(temp.next!=null){           //     如果当前结点的下一个节点不为空,比较当前结点和下一个结点          if(temp.next.val==temp.val)              temp.next=temp.next.next;     //     如果当前结点和下一个结点相同,直接将下一个节点改为下下结点          else              temp=temp.next;               //     如果不同,继续往后          }          return head;      }  }  
7.LeetCode82 Remove Duplicates from Sorted List II(删除排序链表的重复元素2)
Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.

For example,
Given 1->2->3->3->4->4->5, return 1->2->5.
Given 1->1->1->2->3, return 2->3
class Solution {      public ListNode deleteDuplicates(ListNode head) {              if (head == null) return null;            if (head.next != null && head.val == head.next.val) {              //如果当前结点和他下一结点相等                 while (head.next != null && head.val == head.next.val) {                     head = head.next;                                          //head一直往后          }          return deleteDuplicates(head.next);                            //把这一段的舍去,然后判断剩下的      } else {          head.next = deleteDuplicates(head.next);                       //如果不相等保留,从下一个结点继续判断      }      return head;                                                             }  }  
8.约瑟夫环(程序员面试金典)

第一个问题:

约瑟夫问题是一个非常著名的趣题,即由n个人坐成一圈,按顺时针由1开始给他们编号。然后由第一个人开始报数,数到m的人出局。现在需要求的是最后一个出局的人的编号。

给定两个int nm,代表游戏的人数。请返回最后一个出局的人的编号。保证n和m小于等于1000。

解答:
import java.util.*;  public class Joseph {      public int getResult(int n, int m) {                LinkedList<Integer> test=new LinkedList<Integer>();   //注意链表初始化,别忘了()          for (int i=1;i<=n;i++)          {test.add(i);}          int start=0;          while(test.size()>1){                                 //注意链表长度取法              int need=(start+m-1)%test.size();              test.remove(need);              start=need%test.size();              }              return test.get(0);      }   }      
⑴int need=(start+m-1)%test.size();
是为了防止m>test.size();
第一次while,如果m=15,而test.size()=10,这样要删除的结点是4
⑵如何数到5开始出局,链表长度是10
第一次while:
need=4
test.remove(4)  test.size()=9
start=4%9 是4  start=4,也就是第二次while 从start=4开始了。
⑶这里start=need%test.size();是为了防止删除的是最后一个结点
比如数到10开始出局,链表长度是10
第一次while:
need=9
test.remove(9) test.size()=9
start如果直接和need相等,则start=9 链表已经没有下标9的了,9%9=0,回归到下标0

9.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.

class Solution {    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {        if(l1==null)            return l2;        if(l2==null)            return l1;        ListNode  test;        if(l1.val>l2.val)        { test=l2;          test.next=mergeTwoLists(l1,l2.next);        }        else  //这里为什么得用ELSE我也不清楚了,我本来用的if结果leetcode报错了         {               test=l1;             test.next=mergeTwoLists(l1.next,l2);         }        return test;     }}



原创粉丝点击