链表是一个重要的数据结构,常见的链表又分为单向链表和双向链表,各自都有很多应用场景。下面一起来看看吧:

 

链表的特点和适用场景

链表特点:

(1)链表是一种特殊的存储结构,物理存储空间不连续,需要额外的信息(指针)指向下一个结点的地址,开销大

(2)与数组不相同,链表可以动态的添加元素和删除元素。

(3)链表增加和删除时较快,查询需要遍历,与数组相比较,相对较慢。

链表适用场景:

(1)增删频繁的场合

(2)在链表头部和尾部插入或删除的时间复杂度为O(1),在中间插入或删除的需要先查找到相应的位置,再进行操作,若存在既增删又有查找的场合,常常会和栈、队列等结合一起使用。


实例解析


题目1:旋转链表

题目描述:给定一个链表,旋转链表,将链表每个节点向右移动 ķ 个位置,其中 ķ 是非负数。

示例:

输入: 1-> 2-> 3-> 4-> 5-> NULL,k = 2

输出: 4-> 5-> 1-> 2-> 3-> NULL

解释:

向右旋转1步:5-> 1-> 2-> 3-> 4-> NULL

向右旋转2步:4-> 5-> 1-> 2-> 3-> NULL

注:下面代码可左右滑动查看


public ListNode rotateRight(ListNode head, int k) {
if(head == null || k == 0){
return head;
}
ListNode cursor = head;
ListNode tail = null;
int length = 1;
while(cursor.next != null){
cursor = cursor.next;
length++;
}
int loop = length - (k % length);
tail = cursor; //指向尾结点
cursor.next = head; //改成循环链表
cursor = head; //指向头结点
for(int i = 0; i < loop; i++){ //开始循环
cursor = cursor.next;
tail = tail.next;
}
tail.next = null; //改成单链表
return cursor; //返回当前头
}

题目2:反转链表

题目描述:给定一个链表,旋转链表,将链表每个节点向右移动 ķ 个位置,其中 ķ 是非负数。

示例:

输入: 1-> 2-> 3-> 4-> 5-> NULL

输出: 5-> 4-> 3-> 2-> 1-> NULL

注:下面代码可左右滑动查看


public static ListNode reverseListIterative(ListNode head) {
ListNode prev = null; //前指针节点
ListNode curr = head; //当前指针节点
//每次循环,都将当前节点指向它前面的节点,然后当前节点和前节点后移
while (curr != null) {
ListNode nextTemp = curr.next; //临时节点,暂存当前节点的下一节点,用于后移
curr.next = prev; //将当前节点指向它前面的节点
prev = curr; //前指针后移
curr = nextTemp; //当前指针后移
}
return prev;
}

题目3:环形链表

题目描述:给定一个链表,判断链表中是否有环。为了表示给定链表中的环,我们使用整数pos来表示链表尾连接到链表中的位置(索引从0开始)。如果pos是-1,则在该链表中没有环。

示例:

输入:head = [3,2,0,-4],pos = 1

输出:真

解释:链表中有一个环,其尾部连接到第二个节点。

算法专题 之 链表_链表

注:下面代码可左右滑动查看


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



- END -算法专题 之 链表_时间复杂度_02

算法专题 之 链表_时间复杂度_03

算法专题 之 链表_结点_04