先说下一个节点的结构:一个val域和一个next域
public class ListNode {
int val;
ListNode next = null;
public ListNode(int val) {
this.val = val;
}
}
一、已知链表的头节点,将链表进行逆序。(不可以申请额外的空间)
public static ListNode reverseList(ListNode node) {
ListNode pre = null;
ListNode pNext = null;
while(node != null) {
pNext = node.next;
node.next = pre;
pre = node;
node = pNext;
}
return pre;
}
二、已知链表的头节点,将链表从位置m到n逆序。注意:1<=m<=n<=链表长度(不允许申请额外空间)
思路:主要是要找到逆序的头节点和尾巴,以及头节点的前驱节点,和尾节点的后置节点
注意:如果m=1,说明是从第一个节点开始,那么就需要修改头节点
public static ListNode reverseListBetween(ListNode node,int m,int n) {
int index = 1;
ListNode p = node;
ListNode pre = null;
while(index <= n) {
if(index == m) {
ListNode temp = p;
ListNode tempPre = null;
ListNode tempNext = null;
for(int i = m;i <= n;i++) {//开始进行节点的逆序
tempNext = temp.next;
temp.next = tempPre;
tempPre = temp;
temp = tempNext;
}
if(pre == null) {//说明是从头节点就开始翻转
p.next = temp;
node = tempPre;//修改下头节点
}else {
pre.next = tempPre;
p.next = temp;
}
index = n;
}
pre = p;
p = p.next;
index++;
}
return node;
}
三、求两个链表公共的节点,若没有则返回null
解题思路:给个图就能知道!!!!从相同的位置开始判断。交点之后都是相同的。
public static ListNode getIntersectionNode(ListNode node1,ListNode node2) {
//先求两个链表的长度
int len1 = getLengthOfList(node1);
int len2 = getLengthOfList(node2);
//将指针移动到相同的位置
if(len1 > len2) {
for(int i = 0; i < len1 - len2;i++)
node1 = node1.next;
}else {
for(int i = 0; i < len2 - len1;i++)
node2 = node2.next;
}
//找相同的节点
while(node1 != null && node2 != null) {
if(node1 == node2)
return node1;
node1 = node1.next;
node2 = node2.next;
}
return null;
}
public static int getLengthOfList(ListNode node) {
int len = 0;
ListNode p = node;
while(p != null) {
len++;
p = p.next;
}
return len;
}
四、判断一个链表中是否有环,若有则返回环的入口,若没有则返回null
思路:设置快慢指针。
public static ListNode detectCycle(ListNode node) {
ListNode fast = node;
ListNode low = node;
while(low!=null && fast!=null && low.next != null && fast.next !=null) {
low = low.next;
fast = fast.next.next;
if(low == fast) {
//设置一个指针从头节点开始
ListNode temp = node;
while(temp != low) {
temp = temp.next;
low = low.next;
}
return temp;
}
}
return null;
}
五、链表划分:给定一个值x,将所有小于x的节点放在大于或等于x的节点前,且要保持这些节点原来的相对位置
解题思路:若是数组的话,实际上修改下排序的规则,并选择一种稳定的排序即可,但是链表采用排序的方式就会稍微复杂。实际上可以设置两个节点,遍历链表,将小于x的节点连接到一个节点,将大于或等于x的节点连接到另外一个节点,最后再将两个链表合并。
public static ListNode partition(ListNode node,int val) {
ListNode A = new ListNode(val);
ListNode B = new ListNode(val);
ListNode p1 = A;
ListNode p2 = B;
while(node != null) {
if(node.val < val) {
p1.next = node;
p1 = p1.next;
}else {
p2.next = node;
p2 = p2.next;
}
node = node.next;
}
p1.next = B.next;
p2.next = null;
return A.next;
}
六、复杂链表的复制。
结点结构有三部分:一个值域 一个next域,一个随即域 ,指向任意节点。
public class RandomListNode {
int val;
RandomListNode next = null;
RandomListNode random = null;
public RandomListNode(int val) {
this.val = val;
}
}
public static RandomListNode copyRandomListNode(RandomListNode node) {
if(node == null)
return null;
//先复制节点
RandomListNode p = node;
while(p != null) {
RandomListNode temp = new RandomListNode(p.val);
temp.next = p.next;
p.next = temp;
p = p.next.next;
}
//复制节点的指向
p = node;
while(p != null) {
if(p.random != null) {
p.next.random = p.random.next;
}
p = p.next.next;
}
//拆分
p = node;
RandomListNode head = p.next;
RandomListNode t = head;
while(t.next != null) {
p.next = t.next;
t.next = t.next.next;
p = p.next;
t = t.next;
}
p.next = null;
return head;
}
七、两个排序链表的合并,合并后任然是有序的
public static ListNode mergeTwoLists(ListNode node1,ListNode node2) {
if(node1 == null)
return node2;
if(node2 == null)
return node2;
ListNode p = null;
if(node1.val < node2.val) {
p = node1;
node1 = node1.next;
}else {
p = node2;
node2 = node2.next;
}
ListNode t = p;
while(node1 != null && node2 != null) {
if(node1.val < node2.val) {
t.next = node1;
node1 = node1.next;
}else {
t.next = node2;
node2 = node2.next;
}
t = t.next;
}
//退出时,至少有一个链表结束遍历了
if(node1 != null) {
t.next = node1;
}
if(node2 != null) {
t.next = node2;
}
return p;
}
八、链表的k逆序问题:每k个节点之间进行逆序,最后不足k个节点不逆序
public static ListNode reverseK(ListNode node,int k) {
//判断是否有k个节点,不足k个节点 直接返回头节点
int index = 0;
ListNode p = node;
while(p != null) {
index++;
p = p.next;
}
if(index < k)
return node;
p = node;
ListNode temp = p;//保存下当前的头节点
ListNode pre = null;
ListNode pNext = null;
for(int i = 0; i < k;i++) {
pNext = p.next;
p.next = pre;
pre = p;
p = pNext;
}
//新的头节点为pre;
temp.next = reverseK(p,k);//当前k个节点的尾节点的下一个为下k个节点逆序后的头节点
return pre;
}
九、删除链表中指定的值,返回清除后的头节点
注意:是否删除的头节点
public static ListNode clearList(ListNode node,int val) {
ListNode p = node;
ListNode pre = null;
while(p != null) {
if(p.val == val) {
//判断是否是头节点
if(p == node) {
node = p.next;
p = node;
}else {
pre.next = p.next;
p = p.next;
}
}else {
pre = p;
p = p.next;
}
}
return node;
}
十、判断链表是否是回文
public static boolean isPalindrome(ListNode node) {
ArrayList list = new ArrayList<>();
ListNode p = node;
while(p != null) {
list.add(p);
p = p.next;
}
for(int i = 0; i < list.size()/2;i++) {
if(list.get(i).val != list.get(list.size()-1-i).val)
return false;
}
return true;
}
感觉差不多了 反正链表很简单 就这样吧