1、链表数据结构
内存利用率高;动态分配
2、链表类定义
单向链表节点
public calss ListNode {
int val =0;
ListNode next = null;
public void Node(int val_) {
this.val = val_;
this.next = null;
}
}
单向链表类:
public class LinkedList {
private ListNode head = null;
private ListNode tail = null;
private int size = 0;
public void LinkedList() {
head = null;
tail = null;
size = 0;
}
}
LinkedList构造函数用默认构造函数就可以,可以不实现。
3、链表的操作
1)添加add,2)按索引删除remove,3)取值get,4)修改set,5)按值删除removeByValue
public class LinkedList {
private ListNode head = null;
private ListNode tail = null;
private int size = 0;
/////////////////////////////getEntry//////////////////////////////
public ListNode getEntry(int index) {
if (index < 0 || index >= size) {
return null;//或者抛出异常
}
ListNode cur = head;
while (index-- != 0) {
cur = cur.next;
}
return cur;
}
///////////////////add////////////////////
public void add(int index, int value) {
if (index <0 || index > size) {
return;//抛出异常
}
size++;
LiseNode newNode = new ListNode(value);
if (index == 0) {
newNode.next = head.next;
head.next = newNode;
return;
}
ListNode pre = getEntry(index - 1);
newNode.next = pre.next;
pre.next = newNode;
}
//////////////////////remove////////////////////////
public void remove(int index) {
if (index < 0 || index >= size) {
return;///抛出异常
}
size--;
if(index == 0) {
head = head.next;
return;
}
ListNode pre = getEntry(index - 1);
pre.next = pre.next.next;
}
////////////////////////get////////////////////
public int get(int index) {
if (index < 0 || index >= size) {
return 0;///抛出异常
}
ListNode cur = getEntry(index);
return cur.val;
}
/////////////////////set/////////////////////////////
public void set(int index, int value) {
if (index < 0 || index >= size) {
return;//抛出异常
}
ListNode cur = getEntry(index);
cur.val = value;
}
/////////////////////////removeByValue/////////////////////////////
public void removeByValue(int value) {
///暂时先不实现了。找到所有值相等的节点删除。
}
}
可以使用dummy节点来消除head节点无前驱的问题。
public void add(int index, int value) {
if (index < 0 || index >= size) {
return;///抛出异常
}
size++;
ListNode dummy = new ListNode();
dummy.next = head;
LiseNode pre = dummy;
while (index-- != 0) {
pre = pre.next;
}
ListNode newNode = new ListNode(value);
newNode.next = pre.next;
pre.next = newNode;
head = dummy.next;
}
public void remove(int index) {
if (index < 0 || index >= size) {
return;//抛出异常
}
size--;
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode pre = dummy;
while (i-- != 0) {
pre = pre.next;
}
pre.next = pre.next.next;
head = dummy.next;
}
3、链表应用count related
1)linkedlist length
public int getLength(ListNode head) {
ListNode cur = head;
int length = 0;
while(cur != null) {
length++;
cur = cur.next;
}
return length;
}
2)Kth node from the end
Given a linked list, return the kth node from the end. Linked list will never beempty and k will always be valid.
Examples:
Input: 1->4->2->3, 2
Output: 2
Input: 3->5->9->6->8, 3
Output: 9
k is counted from 0 or 1?
method 1:
public LinkedList getTargetNode(ListNode head, int k) {
int length = 0;
length = getLength(head);
ListNode cur = head;
for (int i = 0; i < length - k; i++) {
cur = cur.next;
}
return cur;
}
时间复杂度:n + n - k = 2 * n - k
method 2:
public ListNode getTargetNode(ListNode head, int k) {
ListNode curForward = head;
ListNode curPost = head;
int i = 0;
while (i < k) {
curForward = curForward.next;
i++;
}
/***
*while (k-- != 0) {curForward = curForward.next}
***/
while (curForward != null) {
curForward = curForward.next;
curPost = curPost.next;
}
return curPost;
}
时间复杂度:k + 2 * (n-k) = 2 * n - k
3、middle node
Given a linked list, return the middle node. Linked list will never be empty.
Examples:
Input: 1->4->2->3
Output: 4
Input: 3->5->9->6->8
Output: 9
method 1:
public ListNode getMiddleNode(ListNode head) {
ListNode cur = head;
int length = getLength(head);
int i = (length - 1) / 2;
while (i-- != 0) {
cur = cur.next;
}
return cur;
}
method 2:
public ListNode getMiddleNode(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while (fast.next != null && fast.next.next != null) {
fast = fast.next;
slow = slow.next;
}
return slow;
}
4、Linked List Cycle
Given a linked list, define if there is a cycle in it.
Examples:
Input: 1->4->2->3
Output: false.
Input: 3->5->9->3(original)
Output: true
public boolean findListCycle(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while (fast != null && fast.next != null) {
if (fast.next == slow) {/******中间差一步时,下一个循环是slow走一步,fast走两步,相遇*******/
return true;
}
slow = slow.next;
fast = fast.next.next;
}
return false;
}
链表的环入口节点分析:http://blog.csdn.net/cyuyanenen/article/details/51712420