LinkedList 总结

链表的题基本可以说是基础题,不涉及算法,要熟记他的一些基本操作,基本技巧。

链表的特点就是添加删除O(1),不费空间,比如重新组合一串数字,用array需要从新开一个数组,而链表不需要,只要改变指针就行。

缺点是访问的时候,最坏可能到O(n)。

我个人一般怕乱,所以不用双向表,就用单项表挺好的。

1,dummy大法,在什么情况的时候会引入dummy点呢?一般结构是 dummy.next = head, 所以dummy的作用就是一个伪头节点,在不知道head节点是否会变化的时候需要用dummy标记,以后返回的时候返回dummy.next。一般来说遇到需要head节点会变的时候就需要引入dummy点。

2,快慢指针。快慢指针可以用于:

  1)从后向前的链表删除。--快指针先走n步,然后快,慢指针再一起走,当快指针走到头的时候,就找到要删除的位置了。

  2)看链表是否有环。--快指针走2步,慢指针走1步,当快慢指针重叠的时候代表有环。此时将慢指针拉回起点,两个指针一起走,再相遇就知道环的长度。

  3)找中点。 -- 快走2步,慢走1步,快指针走到头,慢指针正好在1/2处。

基本操作:增(插入),删,查,翻转。

先定义链表(单向):

public class ListNode{

  int  val;

  ListNode  next;

  ListNode(int val){

    this.val = val;

    this.next = null;

  }

}

     -->A-->B--> 

1,增加(插入): 在AB中插入节点C

  A.next = C;

  C.next = B;

2,删除: 删除B节点

  while (A.next != null){

    A.next =A.next.next;

  }

3,查找:value=2的

  while (find != null && find.val != 2){

    find = find.next;

  }

4, 翻转:

  while (head != null){

    ListNode temp = head.next;

    head.next = prev;

    prev = head;

    head = temp;

  } 

  prev-->A-->B-->C prev先在A点之前(prev),然后防止以后找不到A.next(也就是B)要先拿个pointer记录下这个位置。然后操作A.next(也就是head.next)指向之前的点prev。

  prev<--A   (temp)-> B --> C  这时候A,B时断开的,肯定要再把B连到A上,那么这时候把prev移到A点,head移动到B上,准备下一次翻转。

 

常见错误:

1,构建一个链表时候,要有头节点(为了找到链表),还有有个tail节点,尾节点->null,tail.next = null

2, while loop里面,什么时候用while (head != null){} 什么时候用 while (head.next != null){}  ANS: 我个人的理解是这样:如果要把所有点都遍历一遍,那肯定是要做head != null判断,如果快慢指针的时候,还要加上fast.next != null。因为,指针head也好,curr也好,都是可以为null的,但是null是不会有next指针,null.next操作时非法的。如果要做删除,肯定是要判断head.next != null;

3, 做删除操作的时候,一定要去判断curr.next是不是要删的,以为单链表一定要记录要删除的前面的点才可以删除,所以curr要从dummy位置开始判断,这样curr.next才是从head开始的。

4, 做递归时,不能直接把一个curr当作入参进入helper函数,这时有两个解决办法:1,定义一个实参,作为全局变量,把这个传入helper,但是不建议,这样不安全;2, 定义一个类,CurrNode,在里面定义一个node,用的时候要申请一个node,传入helper,用的时候记住要currNode.node才能用这个node。

posted @ 2015-11-12 01:18  Tri_tri_tri  阅读(540)  评论(0)    收藏  举报