写在开头
前段时间比较懒散,给自己定下的刷题任务只坚持了几点就被我无限期“鸽置”了,希望使用写文章的方式记录解题过程,记录思路。方便自己倒回来看,也方便自己工作之后,晚上emo的时候倒回来看看曾经自己做过的努力和尝试。
这个专栏可能会随便一点吧,主要是作为记录,然后才是笔记。
大概就是这样。
BM1 反转链表
很常规的链表题,思路也很简单:
1. 进行特值判断,当所给链表的head == null || head.next == null 时,代表所给数据要么为空链表,要么该链表只有一个节点,将所给数据直接返回(return head)
2. 新建结点存储空位置、模拟头结点、头结点下一位置
3. 通过循环进行反转操作
4. 返回pre即可
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
public ListNode ReverseList(ListNode head) {
if(head == null || head.next == null){
//相当于return null
return head;
}
//新建节点存储空位置
ListNode pre = null;
//新建节点模拟头结点
ListNode cur = head;
//新建节点存储cur下一位置
ListNode temp = null;
while(cur != null){
temp = cur.next;
//cur.next 该指针向前指向pre位置,以实现反转
cur.next = pre;
//pre指向cur位置,实现pre向后移动
pre = cur;
//cur向后移动,指向temp位置
cur = temp;
}
//由于pre为反转前的最后位置,因此反转后处于第一位置,作为头结点
return pre;
}
}
BM2 链表内指定区间反转
思路同上一题没有什么大的差别,但是要注意这次反转是指定了范围的。因此要新建一个头结点,模拟创建一个新的链表,将要反转的区间反转之后再把所有的节点都复制到创建的模拟头结点所在的链表上。
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* }
*/
public class Solution {
/**
*
* @param head ListNode类
* @param m int整型
* @param n int整型
* @return ListNode类
*/
public ListNode reverseBetween (ListNode head, int m, int n) {
//要反转的长度
int len = n - m;
//创建虚拟头结点
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode pre = dummy;
ListNode cur = head;
for(int i = 1; i < m; i++){
pre = cur;
cur = cur.next;
}
for(int i = 0; i < len; i++){
ListNode temp = cur.next;
cur.next = temp.next;
temp.next = pre.next;
pre.next = temp;
}
return dummy.next;
}
}
BM3 链表中的节点每k个一组翻转
本题有多个解题方法,我比较笨,用的就是最简单、最直观的模拟法。
解题步骤在代码里的注释部分都有详细解释。
就不过多赘述了
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* }
*/
public class Solution {
/**
*
* @param head ListNode类
* @param k int整型
* @return ListNode类
*/
public ListNode reverseKGroup (ListNode head, int k) {
// 如果链表本身为 null,或者链表只有一个节点, 或者 k 为 1,则直接返回链表本身
if (head == null || head.next == null || k == 1) {
return head;
}
ListNode dummy = new ListNode(-1);
dummy.next = head;
// 反转链表的前序节点
ListNode pre = dummy;
// 反转链表组的头节点
ListNode leftNode = head;
// 反转链表组的尾节点
ListNode rightNode = leftNode;
// 用于计数节点个数是否达到 k
int count = 1;
while (rightNode != null && rightNode.next != null) {
count++;
// 遍历一次,就将 rightNode 后移一个节点
rightNode = rightNode.next;
// 满足 k 个节点,满足反转链表的条件
if (count == k) {
// 反转从 leftNode 开始的 k 个节点(只需要 k-1 次就可以反转完成)
for (int i = 1; i < k; i++) {
ListNode temp = leftNode.next;
leftNode.next = temp.next;
temp.next = pre.next;
pre.next = temp;
}
// 反转后,rightNode 会作为反转后链表的头节点,需要与 pre 拼接
pre.next = rightNode;
// 下一组反转链表的前序节点
pre = leftNode;
// 下一组反转链表的头节点
leftNode = leftNode.next;
// 下一组反转链表的尾节点,会随着遍历后移
rightNode = leftNode;
// 一组反转完成后,重新开始计数
count = 1;
}
}
return dummy.next;
}
}