struct ListNode {
int val; //这个成员变量存储节点的值,它的类型是整数。
ListNode* next; //这是一个指针,指向下一个 ListNode 类型的节点,用于连接链表中的下一个元素
ListNode() : val(0), next(nullptr) {} //这是一个无参构造函数,当没有提供初始值时,它会创建一个值为 0,next 指针为 nullptr 的节点。
ListNode(int x) : val(x), next(nullptr) {} //单参构造
ListNode(int x, ListNode* next) : val(x), next(next) {}
};
用数组输入
ListNode* vector_Createlist(vector<int> v, int n)
{
cout << "Input ListNode:" << endl;
//int Inputnum;
ListNode* head, * nodetemp, * node; //建立三个节点指针
head = nullptr;
nodetemp = nullptr;
for(int i = 0;i<n;i++)
{
node = new ListNode;//创建新节点,调用了 ListNode 的默认构造函数,该构造函数将 ListNode 对象的 val 成员初始化为 0,next 成员初始化为 nullptr
node->val = v[i];
if (head == nullptr) {
head = node;
}
else {
nodetemp->next = node;
}
nodetemp = node;
nodetemp->next = nullptr;
}
return head;
}
void PrintList(ListNode* head)
{
cout << "printList" << endl;
ListNode* current = head;//声明了一个指针 current,并初始化它指向链表的头节点 head。current 将用于遍历链表的每个节点。
while (current != nullptr) {
cout << current->val << " ";
current = current->next;
}
cout << endl;
}
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例 1:
输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
示例 2:
输入:l1 = [], l2 = []
输出:[]
示例 3:
输入:l1 = [], l2 = [0]
输出:[0]
使用递归方法
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2)//21 合并两个有序链表
{
if (list1 == nullptr)
{
return list2;
}
else if (list2 == nullptr)
{
return list1;
}
else if (list1->val < list2->val)
{
list1->next = mergeTwoLists(list1->next, list2);
return list1;
}
else
{
list2->next = mergeTwoLists(list1, list2->next);
return list2;
}
}
判断链表是否有环
bool hasCycle(ListNode* head)//141.环形链表
{
unordered_set<ListNode*> set;//将指针存放在哈希表中
ListNode* current = head;
while (current != nullptr)
{
if (set.count(current))//set元素唯一,所以set.count()是0或1,1是true,遇到重复,有环
{
return true;
}
set.insert(current);
current = current->next;
}
return false;
}
ListNode* reverseList(ListNode* head) {
ListNode* prev = nullptr;
ListNode* curr = head;
while (curr) {
ListNode* next = curr->next;//next 指向与 curr->next 相同的内存位置,即head的下一个节点
curr->next = prev;
prev = curr;//移动prev指针到curr指针同位置
curr = next;//更新curr指针
}
return prev;
}
很考验对链表的理解
找的一个视频讲解206.反转链表
给你一个链表的头节点 head 。删除 链表的 中间节点 ,并返回修改后的链表的头节点 head 。
长度为 n 链表的中间节点是从头数起第 ⌊n / 2⌋ 个节点(下标从 0 开始),其中 ⌊x⌋ 表示小于或等于 x 的最大整数。
对于 n = 1、2、3、4 和 5 的情况,中间节点的下标分别是 0、1、1、2 和 2 。
关键在于找中间节点位置用快慢指针
ListNode* deleteMiddle(ListNode* head)//2095.删除链表中间节点
{
if (head == nullptr || head->next == nullptr)//输入的链表是空或是有一个元素
{
return nullptr;
}
ListNode* fast = head;
ListNode* slow = head;
ListNode* pre = nullptr;
while (fast != nullptr && fast->next != nullptr )//双指针找中间节点的条件
{
fast = fast->next->next;
pre = slow;
slow = slow->next;//快慢指针找到中间元素
}
pre->next = pre->next->next;
return head;
}
while (fast != nullptr && fast->next != nullptr )//双指针找中间节点的条件
{
fast = fast->next->next;
slow = slow->next;//快慢指针找到中间元素
}
奇数和偶数个数节点结果
给定单链表的头节点 head ,将所有索引为奇数的节点和索引为偶数的节点分别组合在一起,然后返回重新排序的列表。
第一个节点的索引被认为是 奇数 , 第二个节点的索引为 偶数 ,以此类推。
请注意,偶数组和奇数组内部的相对顺序应该与输入时保持一致。
你必须在 O(1) 的额外空间复杂度和 O(n) 的时间复杂度下解决这个问题。
用两个指针相互向后移动,注意条件
ListNode* oddEvenList(ListNode* head) {
if (head == nullptr || head->next == nullptr) {
return head;
}
ListNode* odd = head;
ListNode* even = head->next;
ListNode* evenHead = even; // 保存偶数节点的头指针
while (even != nullptr && even->next != nullptr) {
odd->next = even->next;
odd = odd->next;
even->next = odd->next;
even = even->next; // 当代码执行 even = even->next 时,如果 even->next 是 nullptr,则 even 将被赋值为 nullptr,不会出错
}
odd->next = evenHead; // 将偶数节点连接到奇数节点末尾
return head;
}
在一个大小为 n 且 n 为 偶数 的链表中,对于 0 <= i <= (n / 2) - 1 的 i ,第 i 个节点(下标从 0 开始)的孪生节点为第 (n-1-i) 个节点 。
比方说,n = 4 那么节点 0 是节点 3 的孪生节点,节点 1 是节点 2 的孪生节点。这是长度为 n = 4 的链表中所有的孪生节点。
孪生和 定义为一个节点和它孪生节点两者值之和。
给你一个长度为偶数的链表的头节点 head ,请你返回链表的 最大孪生和 。
输入:head = [5,4,2,1]
输出:6
解释:
节点 0 和节点 1 分别是节点 3 和 2 的孪生节点。孪生和都为 6 。
链表中没有其他孪生节点。
所以,链表的最大孪生和是 6 。
用数组做
int pairSum(ListNode* head)//2130.链表最大孪生和
{
vector<int> v;
ListNode* node = head;
while (node != nullptr)
{
v.push_back(node->val);
node = node->next;
}
int n = v.size();
int max_sum = INT_MIN;
for (int i = 0; i < n / 2; i++)
{
v[i] = v[i] + v[n - 1 - i];
max_sum = max(max_sum, v[i]);
}
return max_sum;
}
快慢指针找到链表中心,后半部分链表反转,这样前后部分都可以同时向后移动求和
int pairSum1(ListNode* head)//2130.链表最大孪生和
{
if (head == nullptr || head->next == nullptr) return 0;
ListNode* slow = head;
ListNode* fast = head->next;
while (fast != nullptr && fast->next != nullptr)//快慢指针找中心节点固定写法
{
slow = slow->next;
fast = fast->next->next;
}
slow = slow->next;//翻转从中心slow下一个开始
ListNode* pre = nullptr;
ListNode* curr = slow;
while (curr)//链表翻转,注意反转完头节点是pre
{
ListNode* next = curr->next;
curr->next = pre;
pre = curr;
curr = next;
}
int max_sum = INT_MIN;
while (pre)
{
max_sum = max(max_sum, head->val + pre->val);
pre = pre->next;
head = head->next;
}
return max_sum;
}