两两交换,奇数怎么处理呢?最后一个不交换?
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
//在这段代码中,Solution 类中的 swapPairs 函数被声明为返回 ListNode* 类型的指针。函数返回类型的 * 符号表示返回一个指向 ListNode 类型对象的指针。
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* cur = dummyHead;
while ((cur->next != nullptr) && (cur->next->next != nullptr)) {
ListNode* tmp = cur->next;
ListNode* tmp1 = cur->next->next->next;
cur->next = cur->next->next;
cur->next->next = tmp;
cur->next->next->next = tmp1;
cur = cur->next->next;
}
// delete dummyHead;
return dummyHead->next;
}
};
遍历求长度、删除第len-n+1个,分删除的是首节点和非首节点两类
添加虚拟头结点可以改进,不用分类
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
// 添加虚拟头结点
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
// 遍历求长度
ListNode* cur = dummyHead;
int len =0;
while (cur) {
cur = cur->next;
len++;
}
int number = len - n + 1; // 倒数第n个为整数第len-n+2个
// 删除第number个.
ListNode* cur2 = dummyHead;
for (int i = 1; i < number - 1; i++) {
cur2 = cur2->next; // 指向需要删除的前1项
}
ListNode* tmp = cur2->next;
cur2->next = tmp->next;
return dummyHead->next;
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
// 双指针法
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* fast = dummyHead;
ListNode* slow = dummyHead;
for (int i = 0; i < n + 1; i++) {
fast = fast->next;
}
while (fast) {
fast = fast->next;
slow = slow->next;
}
ListNode* tmp = slow->next;
slow->next = tmp->next;
delete tmp;
// delete dummyHead;
return dummyHead->next;
// 自己的方法:直接法
// // 添加虚拟头结点
// ListNode* dummyHead = new ListNode(0);
// dummyHead->next = head;
// // 遍历求长度
// ListNode* cur = dummyHead;
// int len =0;
// while (cur) {
// cur = cur->next;
// len++;
// }
// int number = len - n + 1; // 倒数第n个为整数第len-n+2个
// // 删除第number个.
// ListNode* cur2 = dummyHead;
// for (int i = 1; i < number - 1; i++) {
// cur2 = cur2->next; // 指向需要删除的前1项
// }
// ListNode* tmp = cur2->next;
// cur2->next = tmp->next;
// return dummyHead->next;
}
};
暴力法,双层循环,判断两个链表每个节点的下一个节点,是否相同,不大可行,复杂度太高
怎么判断哪个链表长,哪个链表短?除了分两类讨论还有别的办法嘛?
答:swap交换头结点,交换链表长度,始终让A链表长度大于等于B链表
求完长度之后应该将curA重新指向链表头
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* curA = headA;
ListNode* curB = headB;
int lenA = 0;
int lenB = 0;
while (curA) {
curA = curA->next;
lenA++;
}
while (curB) {
curB = curB->next;
lenB++;
}
curA = headA; // 求完长度之后应该将curA重新指向链表头
curB = headB;
if (lenB > lenA) {
swap (lenA, lenB);
swap (curA, curB);
}
int subLen = lenA - lenB;
while (subLen--) {
curA = curA->next;
}
while (curA) {
if (curA == curB) {
return curA;
}
curA = curA->next;
curB = curB->next;
}
return NULL;
}
};
没想法
本质上是一个数学问题,画图解出来答案之后,代码就很好写了
不能为了图省事,将本来用于循环的指针另作他用
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode* fast = head;
ListNode* slow = head;
while (fast != nullptr && fast->next != nullptr) {
fast = fast->next->next;
slow = slow->next;
if (fast == slow) {
ListNode* index1 = head; // 这里需重新定义两个节点,如果重新使用fast和slow,next执行一次之后就跳出循环了
ListNode* index2 = fast;
index1 = index1->next;
index2 = index2->next;
if (index1 == index2) {
return index1;
}
}
}
return NULL;
}
};
在C++中,NULL和nullptr都用于表示空指针,但它们在语义上有一些区别。
NULL是一个宏定义,通常被定义为整数0。在较早的C++版本中,NULL被用作表示空指针的常量。然而,NULL的使用存在一些问题,因为它可以被隐式地转换为整数类型,这可能导致一些不明确或错误的行为。
nullptr是C++11引入的新关键字,专门用于表示空指针。nullptr是一个特殊的字面量,不会被隐式转换为其他类型,因此可以更安全地用于指针比较和函数重载等场景。使用nullptr可以避免一些与NULL相关的潜在问题。
下面是一个简单的示例,说明了NULL和nullptr之间的区别:
#include
void foo(int i) {
std::cout << "foo(int)" << std::endl;
}
void foo(char* ptr) {
std::cout << "foo(char*)" << std::endl;
}
int main() {
foo(NULL); // 输出 "foo(int)",存在二义性,编译器可能会选择不同的重载版本
foo(nullptr); // 输出 "foo(char*)",nullptr被精确匹配到foo(char*)重载版本
return 0;
}
在上述示例中,使用NULL作为参数调用foo函数会导致二义性,因为NULL可以被隐式转换为整数类型,因此foo(int)和foo(char*)两个重载版本都是可行的。而使用nullptr作为参数调用foo函数,nullptr只能匹配到foo(char*)重载版本,因为nullptr类型为nullptr_t,只能精确匹配指针类型。
总之,为了避免潜在的问题和提供更好的类型安全性,建议在C++中使用nullptr代替NULL来表示空指针。