物理上(内存)不一定连续
逻辑上连续的一种结构
链表的分类
单向 双向
带头 不带头
循环 非循环
public class MySingleList implements iList {
class Solution{
public ListNode middleNode(ListNode head){
ListNode slow=head;
ListNode fast=head;
while(fast!=null&&fast.next!=null){//不可以反转,当后端先判断的时候会导致fast为空。
slow=slow.next;
fast=fast.next.next;
}
System.out.println(slow.next);
return slow;
}
}
static class ListNode {
public int val;
public ListNode next;
public ListNode(int val) {
this.val = val;
}
}
//链表的属性 链表的头节点
public ListNode head;//null
public void createList() {
ListNode node1 = new ListNode(12);
ListNode node2 = new ListNode(23);
ListNode node3 = new ListNode(34);
ListNode node4 = new ListNode(45);
node1.next = node2;
node2.next = node3;
node3.next = node4;
this.head = node1;
}
@Override
public void display() {
ListNode cur = head;//防止head最后定义表头时候为空
while (cur != null) {//cur为空则停止循环
System.out.print(cur.val + " ");//打印他的数值
cur = cur.next;//下移
}
System.out.println();
}
public void display(ListNode newHead) {
ListNode cur = newHead;
while (cur != null) {
System.out.print(cur.val + " ");
cur = cur.next;
}
System.out.println();
}
/**
* 求当前链表 是否存在Key
*
* @param key
* @return
*/
@Override
public boolean contains(int key) {
ListNode cur = head;
while (cur != null) {
if (cur.val == key) {
return true;
}
cur = cur.next;
}
return false;
}
/**
* 求当前链表 有多少个节点
*
* @return
*/
@Override
public int size() {
int count = 0;//cur走到空
ListNode cur = head;
while (cur != null) {
count++;
cur = cur.next;
}
return count;
}
@Override
public void addFirst(int data) {
ListNode node = new ListNode(data);
node.next = this.head;
this.head = node;
}
@Override
public void addLast(int data) {
ListNode node = new ListNode(data);
if (head == null) {
head = node;
} else {
ListNode cur = head;
while (cur.next != null) {
cur = cur.next;
}
cur.next = node;//cur走到了最后一个节点的位置
}
}
@Override
public void addIndex(int index, int data) throws IndexException {
if (index < 0 || index > size()) {
throw new IndexException("index不合法的: " + index);
}
ListNode node = new ListNode(data);
if (head == null) {
head = node;
return;
}
if (index == 0) {
addFirst(data);
return;
}
if (index == size()) {
addLast(data);
return;
}
//中间插入
ListNode cur = searchPrevIndex(index);
node.next = cur.next;
cur.next = node;
}
private ListNode searchPrevIndex(int index) {
ListNode cur = head;
int count = 0;
while (count != index - 1) {
cur = cur.next;
count++;
}
return cur;
}
@Override
public void remove(int key) {
if (head == null) {
return;
}
if (head.val == key) {
head = head.next;
return;
}
ListNode cur = findPrevKey(key);
if (cur == null) {
return;//没有你要删除的数字
}
ListNode del = cur.next;
cur.next = del.next;
}
private ListNode findPrevKey(int key) {
ListNode cur = this.head;
while (cur.next != null) {
if (cur.next.val == key) {
return cur;
} else {
cur = cur.next;
}
}
return null;
}
@Override
public void removeAllKey(int key) {
if(head == null) {
return;
}
ListNode prev = head;
ListNode cur = head.next;
while (cur != null) {
if(cur.val == key) {
prev.next = cur.next;
cur = cur.next;
}else {
prev = cur;
cur = cur.next;
}
}
//除了头节点都删除完成了之后再运行如果放在前面的情况下,如果12都是想删除的数据。就会造成数据删除补干净,第二个删除不了
if(head.val == key) {
head = head.next;
}
}
@Override
public void clear() {
head = null;
}
public ListNode reverseList() {
if(head == null) {return head;}
if(head.next == null) { return head;}
ListNode cur = head.next;
head.next = null;
while(cur != null) {
ListNode curNext = cur.next;
cur.next = head;
head = cur;
cur = curNext;
}
return head;
}
public ListNode middleNode() {
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
public ListNode findKthToTail(ListNode head,int k) {//让fast先走k-1步,然后fast和slow一起走,最后返回slow的值就是倒数的值
if(k <= 0) {
return null;
}
if(head == null) {//防止头指针为0
return null;
}
ListNode fast = head;
ListNode slow = head;
int count = 0;
while(count != k-1) {
if(fast.next != null) {//防止那个数字超过链表长度
fast = fast.next;
count++;
}else {
return null;
}
}
while(fast.next != null) {
fast = fast.next;
slow = slow.next;
}
return slow;
}
public ListNode partition(int x) {
// write code here
//定义一个cur 指向链表的头节点
ListNode cur = head;
ListNode bs = null;
ListNode be = null;
ListNode as = null;
ListNode ae = null;
//使用cur来遍历 所有的节点
while (cur != null) {
if(cur.val < x) {
if(bs == null) {
bs = cur;
be = cur;
}else {
be.next = cur;
be = be.next;
}
}else {
// >= x
if(as == null) {
as = cur;
ae = cur;
}else {
ae.next = cur;
ae = ae.next;
}
}
cur = cur.next;
}
if(bs == null) {
return as;
}
be.next = as;
if(as != null) {
ae.next = null;
}
return bs;
}
public boolean chkPalindrome() {
// write code here
if(head == null) {
return true;
}
//1. 找中间节点
ListNode fast = head;
ListNode slow = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
//2.翻转
ListNode cur = slow.next;
while (cur != null) {
ListNode curNext = cur.next;
cur.next = slow;
slow = cur;
cur = curNext;
}
//3.一个往前 一个往后
while (slow != head) {
if(slow.val != head.val) {
return false;
}
//偶数情况
if(head.next == slow) {
return true;
}
head = head.next;
slow = slow.next;
}
return true;
}
public boolean hasCycle() {
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
if(fast == slow) {
return true;
}
}
return false;
}
public ListNode detectCycle() {
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
if(fast == slow) {
break;
}
}
if(fast == null || fast.next == null) {
//因为循环条件退出
return null;//证明连环都没有
}
slow = head;
while(slow != fast) {
fast = fast.next;
slow = slow.next;
}
return slow;
}
}
public class IndexException extends RuntimeException {
public IndexException(String s) {
System.out.println(s);
}
}
public interface iList {
void addFirst(int data);
void addLast(int data);
void addIndex(int index,int data);
boolean contains(int key);
void remove(int key);
void removeAllKey(int key);
int size();
void clear();
void display();
}
这里的headA和headB指的是两个独立链表,而headA=headA.next;指的是下一个next域里面的所有head下面的值,而cur=head则是将head的值替换到cur。两个易搞混,应该细细品味。
环形链表中,
快指针的速度是慢指针的2倍,路程也是二倍。
2. 假设 快指针 只走了一圈就和慢指针相遇了
3.假设起始点 到 入口点距离为X,相遇点到入口点距离为Y环的长度为C
经过计算X=(N-1)+Y,当N=1的时候,相遇点和起始点道入口路程相同
public ListNode detectCycle() {
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
if(fast == slow) {
break;
}
}
if(fast == null || fast.next == null) {
//因为循环条件退出
return null;//证明连环都没有
}
slow = head;
while(slow != fast) {
fast = fast.next;
slow = slow.next;
}
return slow;
}