1、反转链表
题目描述:输入一个链表,反转链表后,输出新链表的表头。
解题方法:递归方法,非递归方法
图解:
链表 5—>4—>3—>2—>1—>null
反转成:1—>2—>3—>4—>5—>null
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
//递归写法
public class Solution1 {
public ListNode ReverseList(ListNode head) {
if(head == null || head.next == null) return head;
ListNode newHead = ReverseList(head.next);//逐个反转
head.next.next = head;//让head下一个结点的next指向head;
head.next = null;//当前结点指向null;
return newHead;
}
}
//非递归写法
public class Solution2 {
public ListNode ReverseList(ListNode head){
if(head == null || head.next == null) return head;
ListNode newHead = null;
while(head != null){
ListNode tmp = head.next;//1
head.next = newHead;//2
newHead = head;//3
head = tmp;//4
}
return newHead;
}
}
2、判断链表是否有环
解题思路:快慢指针,有环必然存在指针相等
public boolean hasCycle(ListNode head) {
if(head == null || head.next == null) return false;
ListNode slow = head;
ListNode fast = head.next;
while(fast != null && fast.next != null) {//重点理解
if(slow == fast) return true;
slow = slow.next;
fast = fast.next.next;
}
return false;
}
3、合并有序链表
public ListNode mergeTwoLists (ListNode l1, ListNode l2) {
if(l1 == null ) return l2;
if(l2 == null) return l1;
if(l1.val <= l2.val){
l1.next = mergeTwoLists(l1.next,l2);
return l1;
}else{
l2.next = mergeTwoLists(l1,l2.next);
return l2;
}
}
//优化递归
public ListNode mergeTwoLists(ListNode linked1, ListNode linked2) {
//只要有一个为空,就返回另一个
if (linked1 == null || linked2 == null)
return linked2 == null ? linked1 : linked2;
//把小的赋值给first
ListNode first = (linked2.val < linked1.val) ? linked2 : linked1;
first.next = mergeTwoLists(first.next, first == linked1 ? linked2 : linked1);
return first;
}
4、删除链表倒数第n个结点
解题思路:
删除倒数第k个结点,就是删除顺数第(链表长度-n)个结点;
快慢指针法,将快指针设定为第n个结点处,慢指针在第1个结点,当快指针指向尾结点时,此时删掉慢指针指向的结点。
例如:链表1—>2—>3—>4—>5—>6—>7—>null,n=3,删除5这个结点
public ListNode removeNthFromEnd (ListNode head, int n) {
//利用快慢指针,快指针指向k处,慢指针指向head处,当快指针指向最后一个结点
if(head == null){return null;}
ListNode fast = head;
ListNode slow = head;
ListNode prev = null;
for(int i = 1;i < n;i++){//fast先走n-1步
if(fast.next == null){
return null;
}
fast = fast.next;
}
//执行后,fast指向3这个结点
while(fast.next != null){
fast = fast.next;
prev = slow;//标记删除结点的前一个结点
slow = slow.next;
}
//执行后,fast指向7这个结点,prev指向4这个结点,slow指向5这个结点
if(prev == null){
head = head.next;
}else{
prev.next = prev.next.next;//删除5这个结点
}
return head;
}
5、删除链表中重复节点
题目描述:给出一个升序排序的链表,删除链表中的所有重复出现的元素,只保留原链表中只出现一次的元素。(链表是有序的)
解题思路:创建一个新的节点,同时注意不同连续节点的重复处理。
public ListNode deleteDuplicates (ListNode head) {
if(head == null || head.next == null){
return head;
}
ListNode root = new ListNode(Integer.MAX_VALUE);
root.next = head;
ListNode pre = root;
ListNode cur = root;
while(cur != null){
while(cur.next != null && cur.val == cur.next.val){//找出重复节点
cur = cur.next;
}
cur = cur.next;//判断重复节点的后序节点是否也是重复的
if(cur != null && cur.next != null && cur.val == cur.next.val){
continue;//终止当前循环,执行下一次循环
}
//没有重复值
pre.next = cur;
pre = pre.next;
}
return root.next;
}
}