0. 自建链表
class ListNode{
int val;
ListNode next;
ListNode(int val){
this.val=val;
}
}
Scanner sc = new Scanner(System.in);
String[] str = sc.nextLine().split(" ");
//链表头
ListNode head = new ListNode(0);
//链表尾先指向头
ListNode tail = head;
for(int i=0;i
1. 删除节点:
- 删除链表的倒数第N个节点
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
/*
删除链表的倒数第N个节点
7.22
*/
//创建新链表存储,保存head节点,先循环计算链表的长度,再循环跳过倒数第n个节点
//判断空
if(head == null){
return null;
}
//创建新链表存储
ListNode node = new ListNode(0);
node.next = head;
//计算链表长度
int len = 0;
ListNode cur = head;
while(cur != null){
len++;
cur = cur.next;
}
//重置cur指向node,将节点存入node链表
cur = node;
int index = 0;
//循环找到倒数第n个节点前的节点
for(int i=0;i
- 删除重复不保留
class Solution {
public ListNode deleteDuplicates(ListNode head) {
/*
删除排序链表中的重复元素,不保留
7.24
*/
//双指针
//判断空
if(head == null){
return null;
}
//暂存head
ListNode node = new ListNode(0);
node.next = head;
ListNode cur = node;
while(cur.next != null && cur.next.next != null){
//如果出现重复
if(cur.next.val == cur.next.next.val){
ListNode temp = cur.next;
//判断空
while(temp != null && temp.next != null && temp.val == temp.next.val){
temp = temp.next;
}
cur.next = temp.next;
}else{
cur = cur.next;
}
}
return node.next;
}
}
- 删除重复保留
class Solution {
public ListNode deleteDuplicates(ListNode head) {
/*
删除排序链表的重复元素,保留
7.24
*/
//双指针
//判断空
if(head == null){
return null;
}
ListNode cur = head;
while(cur != null && cur.next != null){
if(cur.val == cur.next.val){
cur.next = cur.next.next;
}else{
cur = cur.next;
}
}
return head;
}
}
- 返回倒数第K个节点
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
//快指针先走k,然后快慢指针一起走,跳出while循环时,慢指针就是倒数第K个节点
ListNode fast = head;
ListNode slow = head;
//快指针先走k
while(k-- > 0){
fast = fast.next;
}
//一起走
while(fast != null){
fast = fast.next;
slow = slow.next;
}
//当跳出while循环时,slow指针就是倒数第K个节点
return slow;
}
}
2. 合并链表:
- 合并两个有序链表
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
/*
合并两个有序链表
7.22
*/
//创建新链表存储,分治合并,补录
ListNode node = new ListNode(0);
ListNode cur = node;
while(l1 != null && l2 != null){
if(l1.val < l2.val){
cur.next = l1;
l1 = l1.next;
}else{
cur.next = l2;
l2 = l2.next;
}
cur = cur.next;
}
//补录
if(l1 != null){
cur.next = l1;
}
if(l2 != null){
cur.next = l2;
}
return node.next;
}
}
- 合并K个有序链表
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
/*
合并K个排序链表
7.22
*/
//分治 + 合并
if(lists.length == 0){
return null;
}
return Merge(lists,0,lists.length-1);
}
public ListNode Merge(ListNode[] lists,int start,int end){
//递归出口
if(start == end){
return lists[start];
}
//提取数组中点
int middle = start + (end - start)/2;
//递归形成左右链表
ListNode left = Merge(lists,start,middle);
ListNode right = Merge(lists,middle+1,end);
//合并
return MergeTwo(left,right);
}
public ListNode MergeTwo(ListNode left,ListNode right){
ListNode node = new ListNode(0);
ListNode cur = node;
while(left != null && right != null){
if(left.val < right.val){
cur.next = left;
left = left.next;
}else{
cur.next = right;
right = right.next;
}
cur = cur.next;
}
if(left != null){
cur.next = left;
}
if(right != null){
cur.next = right;
}
return node.next;
}
}
3. 翻转链表:
- 两两交换链表节点
class Solution {
public ListNode swapPairs(ListNode head) {
/*
两两交换链表节点
7.22
*/
//递归翻转,翻转后的尾指向翻转前的头
//递归出口
if(head == null || head.next == null){
return head;
}
ListNode pre = head;
ListNode tail = head.next;
//pre.next指向tail.next递归
pre.next = swapPairs(tail.next);
//tail.next指向pre
tail.next = pre;
//翻转后tail是链表头
return tail;
}
}
- K个一组翻转链表
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
/*
K个一组翻转链表
7.22
*/
//递归翻转
//递归出口
if(head == null || head.next == null){
return head;
}
ListNode cur = head;
//for循环到第k个节点的前一个节点
for(int i=0;i
- 翻转m到n的链表
class Solution {
public ListNode reverseBetween(ListNode head, int m, int n) {
/*
反转从m到n的链表
7.25
*/
//先遍历找到m节点,反转从m到n的节点,拼接头尾
//判断空
if(head == null){
return null;
}
ListNode node = new ListNode(0);
node.next = head;
ListNode cur = node;
//for循环找到第m个节点的前一个节点cur
for(int i=1;i
- 翻转链表
class Solution {
public ListNode reverseList(ListNode head) {
/*
反转链表
7.26
*/
//双指针,递归
//递归出口
// if(head == null || head.next == null){
// return head;
// }
// //递归到最后一个节点
// ListNode cur = reverseList(head.next);
// //head.next.next拼接head
// head.next.next = head;
// head.next = null;
// return cur;
ListNode pre = null;
ListNode next = null;
while(head != null){
next = head.next;
head.next = pre;
pre = head;
head = next;
}
return pre;
}
}
4. 环形链表:
- 判断有无环
public class Solution {
public boolean hasCycle(ListNode head) {
/*
判断链表是否有环
7.23
*/
//方法一:哈希Set存节点
//方法二:快慢指针
// Set set = new HashSet<>();
// while(head != null){
// if(set.contains(head)){
// return true;
// }
// set.add(head);
// head = head.next;
// }
// return false;
//判断head和head.next是否为null,如果是,必定无环
if(head == null || head.next == null){
return false;
}
ListNode fast = head;
ListNode slow = head;
while(true){
//无环
if(fast == null || fast.next == null){
return false;
}
//快走2慢走1
fast = fast.next.next;
slow = slow.next;
//如果fast能追上slow,说明有环,break
if(fast == slow){
break;
}
}
return true;
}
}
- 返回环入口
public class Solution {
public ListNode detectCycle(ListNode head) {
/*
判断链表是否有环,并找出
7.23
*/
//方法一:哈希Set
//方法二:双指针
// Set set = new HashSet<>();
// while(head != null){
// if(set.contains(head)){
// return head;
// }
// set.add(head);
// head = head.next;
// }
// return null;
if(head == null || head.next == null){
return null;
}
ListNode fast = head;
ListNode slow = head;
while(true){
//无环
if(fast == null || fast.next == null){
return null;
}
//快走2慢走1
fast = fast.next.next;
slow = slow.next;
//如果fast能追上slow,说明有环,break
if(fast == slow){
break;
}
}
fast = head;
while(fast != slow){
fast = fast.next;
slow = slow.next;
}
return fast;
}
}
5. 其他
- 两数相加
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
/*
两数相加
7.22
*/
//柱式相加,node存入十位,node.next存个位
//carry进位为0
return add(l1,l2,0);
}
public ListNode add(ListNode l1,ListNode l2,int carry){
//递归出口
if(l1 == null && l2 == null && carry == 0){
return null;
}
//如果l1为null,置为0
if(l1 == null){
l1 = new ListNode(0);
}
if(l2 == null){
l2 = new ListNode(0);
}
//sum
int sum = l1.val + l2.val + carry;
//创建节点
ListNode node = new ListNode(sum%10);
//拼接递归结果
node.next = add(l1.next,l2.next,sum/10);
return node;
}
}
- 回文链表
class Solution {
public boolean isPalindrome(ListNode head) {
/*
回文链表
7.23
*/
//先快慢指针找到中点,分割左右两条链表。再翻转后半链表,与前半链表逐一比较
ListNode node = new ListNode(0);
//保存head节点
node.next = head;
ListNode fast = node;
ListNode slow = node;
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
}
//fast作为后半链表的头节点
fast = slow.next;
//断开后半
slow.next = null;
slow = node.next;
//翻转后半
ListNode pre = null;
ListNode next = null;
while(fast != null){
next = fast.next;
fast.next = pre;
pre = fast;
fast = next;
}
//while比较
while(pre != null){
if(pre.val != slow.val){
return false;
}
pre = pre.next;
slow = slow.next;
}
return true;
}
}