与传统的ArrayList 以及是数组不同, 在Java中采用LinkedList 的一大好处就是在数据结构的中部或者是头部插入数值的时候所消耗的空间时间复杂度都能大大减小;
public class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
}
上述代码是标准的单链表结构 , 这个节点里面包含了当前节点所存储的数据信息和下一个节点的地址信息。
在LeetCode或者是面试的时候所面对的有关LinkedList的题目就是一下的几个:
1. 在已有的链表当中在指定位置插入或者是删除节点
(1). 给出当前节点,需要删除当前的节点
思路:把当前节点的下一个节点的信息复制到当前节点,把当前节点的下一个节点设置成下下个节点
代码操作如下
public void deleteNode(ListNode node) {
node.val=node.next.val;
node.next=node.next.next;
}
(2). 给出指定节点,需要你在当前节点之后插入一个新的节点
思路: 新建一个节点,复制, 新节点的next=插入节点next
public void addNode(int x,ListNode add){
ListNode nln=new ListNode(x);
nln.next=add.next;
add.next=nln;
}
2.完成了一些基本操作之后我们开始一些比较高级的操作
(1).判断在linked List里面是否存在环状结构
这个问题有两个解法
第一个解法是利用快慢指针
public boolean hasCycle(ListNode head) {
//to judege if a Linked List has a cycle
if (head == null) {
return false;
}
//快慢指针 快指针一次走两步 慢指针一次走一步
ListNode fast = head;
ListNode slow = head;
while (fast.next != null) {
fast = fast.next;//后移一个位置
if (fast.next == null) {
return false;
} else {
fast = fast.next;//后移一个位置
slow = slow.next;
if (fast == slow) {
return true;
}
}
}
return false;
}
另一個解法是利用HashSet
public boolean hasCycle1(ListNode head) {
HashSet hs = new HashSet<ListNode>();
while (head != null) {
if (hs.contains(head)) {
return true;
} else {
hs.add(head);
}
head=head.next;
}
return false;
}
但是第二个解法需要用到了额外的存储空间, 同时这个HashMap or HashSet 也是面试的时候经常会遇到的问题,这个下节继续讲解
(2). 翻转LinkedList
主要思路 利用一个窗口横扫的思路来对链表进行处理
三个指针分别维prev,curr,和当条件满足的时候创建的nextTmp
首先第一步把原来的链表头连接到null 来进行reverse, 此时的prev是null,curr是head=1, nextTmp是2
把curr.next 设定成为prev 当第一步完成之后变成了有两个链表 一个是1-->null; 另外一个是2-->3-->4-->5
第一步操作完成之后所有指针向后移动一位
prev=curr;
curr=curr.next;
代码如下
public ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode curr = head;
while (curr != null) {
ListNode nextTemp = curr.next;
curr.next = prev;
prev = curr;
curr = nextTemp;
}
return prev;
}