一、单链表的建立和遍历:html
1java 2node 3面试 4app 5ide 6测试 7ui 8this 9spa 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
|
上方代码中,这里面的Node节点采用的是内部类来表示(33行)。使用内部类的最大好处是能够和外部类进行私有操做的互相访问。
注:内部类访问的特色是:内部类能够直接访问外部类的成员,包括私有;外部类要访问内部类的成员,必须先建立对象。
为了方便添加和遍历的操做,在LinkList类中添加一个成员变量current,用来表示当前节点的索引(03行)。
这里面的遍历链表的方法(20行)中,参数node表示从node节点开始遍历,不必定要从head节点遍历。
二、求单链表中节点的个数:
注意检查链表是否为空。时间复杂度为O(n)。这个比较简单。
核心代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
四、查找单链表中的中间结点:
一样,面试官不容许你算出链表的长度,该怎么作呢?
思路:
和上面的第2节同样,也是设置两个指针first和second,只不过这里是,两个指针同时向前走,second指针每次走两步,first指针每次走 一步,直到second指针走到最后一个结点时,此时first指针所指的结点就是中间结点。注意链表为空,链表结点个数为1和2的状况。时间复杂度为 O(n)。
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
上方代码中,当n为偶数时,获得的中间结点是第n/2 + 1个结点。好比链表有6个节点时,获得的是第4个节点。
判断单链表是否有环:
这里也是用到两个指针,若是一个链表有环,那么用一个指针去遍历,是永远走不到头的。
所以,咱们用两个指针去遍历:first指针每次走一步,second指针每次走两步,若是first指针和second指针相遇,说明有环。时间复杂度为O (n)。
方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
完整版代码:(包含测试部分)
这里,咱们还须要加一个重载的add(Node node)方法,在建立单向循环链表时要用到。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
|
检测单链表是否有环的代码是第50行。
88行:咱们将头结点继续往链表中添加,此时单链表就环了。最终运行效果为true。
若是删掉了88行代码,此时单链表没有环,运行效果为false。
取出有环链表中,环的长度:
咱们平时碰到的有环链表是下面的这种:(图1)
上图中环的长度是4。
但有可能也是下面的这种:(图2)
此时,上图中环的长度就是3了。
那怎么求出环的长度呢?
|
完整版代码:(包含测试部分)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
|
运行效果:
若是将上面的104至122行的测试代码改为下面这样的:(即:将图2中的结构改为图1中的结构)
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
运行结果:
若是把上面的代码中的第8行删掉,那么这个链表就没有环了,因而运行的结果为0。
一,问题描述
请本身构造一个简单的有序单链表,而后实现删除链表中的重复结点。好比:
二,问题分析
首先要实现一个单链表,所以须要定义一个节点类Node。其次,实现向链表中添加结点的方法(使用尾插法)addNode
删除重复结点的实现思路:
定义两个指针:pre 和 next。初始时,pre指向链表中的第一个元素,next指向链表中的第二个元素。若是 pre 的值与 next 的值不相等,则两个指针分别都向后移一个结点;若相等,则删除 next 指针指向的结点便可。
三,整个代码实现
// delete duplicated nodes in increased list public class MyLinkedList { private class Node{ int ele; Node next; public Node(int ele) { this.ele = ele; next = null; } } private Node head; private Node tail; //采用尾插法添加结点 public void addNode(int ele){ Node newNode = new Node(ele); if(tail != null) tail.next = newNode; else{// first node head = newNode; } tail = newNode; } //删除有序单链表中的重复结点 public void delDuplicatedNode(){ if(head == null) return; Node pre,next; pre = head; next = head.next; while(next != null) { if(pre.ele != next.ele) { pre = next; next = next.next; }else{//delete next point node Node delNode = next; pre.next = next.next; next = next.next; delNode.next = null;//avoid memory leak // delNode = null; } } } @Override public String toString() { if(head == null) return "null"; Node current = head; StringBuilder sb = new StringBuilder(); while(current != null){ sb.append(current.ele + " "); current = current.next; } return sb.toString(); } //hapjin test public static void main(String[] args) { MyLinkedList mylist = new MyLinkedList(); int[] eles = {1,2,3,3,4,4,5}; for (int ele : eles) { mylist.addNode(ele); } System.out.println("before del: " + mylist); mylist.delDuplicatedNode(); System.out.println("after del: " + mylist); } }