注:以下代码均为c++
1
思路:
cpp
//注:这里的链表都没有头节点
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummy = new ListNode(-1); //因为有可能删除第一个节点,所以建一个头节点指向第一个节点,便于将第一个节点与其他节点统一处理。
dummy->next = head;
ListNode* first = dummy, *second = dummy;
while(n--) //first先走n步
first = first->next;
while(first->next){ //first走到头时,second走到倒数n+1个
first = first->next;
second = second->next;
}
second->next = second->next->next;
return dummy->next;
}
2
思路:
"伪装"
我们知道要想删除当前节点必须知道它的上一节点,但我们只有当前要删除的节点地址,无法找到上一节点。
所以,我们将要删除的node伪装成下一个点,再将下一个点删掉。
cpp
void deleteNode(ListNode* node) {
//node->val = node->next->val;
//node->next = node->next->next;
// 可以将上面两句话合并为一句话,因为链表的数据结构为结构体,其存储的val和next的地址是相邻的,
// 我们将当前节点的val,next复制为下一节点的val,next,可以一起操作。
*(node) = *(node->next); //当前节点的地址 = 下一节点的地址
}
3
思路:
cpp
ListNode* deleteDuplicates(ListNode* head){
ListNode* cur = head;
while(cur){
if(cur->next && cur->next->val == cur->val)
cur->next = cur->next->next;
else
cur = cur->next;
}
return head;
}
4
cpp
ListNode* deleteDuplicates(ListNode* head) {
//设头节点
ListNode* h = new ListNode();
h->next = head;
ListNode* first, *second; //first指向不重复节点的尾部, second寻找下一个不重复节点
first = h;
second = first->next;
while(second && second->next){
if(second->val == second->next->val){
while(second->next && second->val == second->next->val)
second = second->next;
second = second->next;
}
else{
first->next = second;
first = second;
second = second->next;
}
}
first->next = second;
return h->next;
}
5
思路:
cpp
ListNode* rotateRight(ListNode* head, int k) {
if(head == NULL)
return head;
int n = 0;
for(ListNode* p = head; p; p = p->next)
n++;
k = k % n;
ListNode* first, *second;
first = head;
second = head;
while(k--)
second = second->next;
while(second->next){
first = first->next;
second = second->next;
}
second->next = head;
head = first->next;
first->next = NULL;
return head;
}
6
思路:
cpp
//2 建立头节点,因为对第一个节点进行操作,所以设置头节点来处理较为容易
ListNode* swapPairs(ListNode* head){
ListNode* dummy = new ListNode();
dummy->next = head;
ListNode* p = dummy;
while(p->next && p->next->next){
ListNode *a = p->next, *b = p->next->next;
p->next = b;
a->next = b->next;
b->next = a;
p = a;
}
return dummy->next;
}
7
思路:
cpp
ListNode* reverseList(ListNode* head) {
if(head == NULL || head->next == NULL)
return head;
ListNode* p = head, *q = p->next, *t = q->next;
while(t){
q->next = p;
p = q;
q = t;
t = t->next;
}
q->next = p; //这一步容易遗忘,当t=NULL时没有进入循环,直接退出了,需要补充一句。
head->next = NULL;
head = q; //也可以不要这一句,直接返回q
return head;
}
8
思路:
cpp
ListNode* reverseBetween(ListNode* head, int left, int right) {
if(left == right)
return head;
int i;
//建立头节点
ListNode* dummy = new ListNode();
dummy->next = head;
head = dummy;
//找到first和second的位置,first->next是第一个要翻转的点,second是最后一个要翻转的点。
ListNode* first = head, *second;
for(i = 1; i < left; i++)
first = first->next;
second = first->next;
for(i = 1; i <= right - left; i++)
second = second->next;
//翻转
ListNode* p = first->next, *q = p->next, *t = q->next;
while(t != second->next){
q->next = p;
p = q;
q = t;
t = t->next;
}
q->next = p;
first->next->next = t;
first->next = second;
return head->next;
}
9
思路:
cpp
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* p = headA, *q = headB;
while(p != q){ //注意这个while循环内部一定是if-else,这种结构的语句,不然会出现问题。
if(p == NULL)
p = headB;
else
p = p->next;
if(q == NULL)
q = headA;
else
q = q->next;
}
return p;
}
10
思路1:哈希表 (我看这道题的第一个想法)
一个非常直观的思路是:我们遍历链表中的每个节点,并将它记录下来;一旦遇到了此前遍历过的节点,就可以判定链表中存在环。借助哈希表可以很方便地实现。
思路2:快慢指针
(1)
快指针:一次走两步(红色)
慢指针:一次走一步(蓝色)
快慢指针一起走,假设当慢指针走到b点时,快指针走到c'点,那么快慢指针将在c点相遇。
(2)
快慢指针相遇后,将慢指针指向链表头部,快慢指针均一次走一步,快慢指针将在b点相遇,即环的起始点。
cpp
ListNode *detectCycle(ListNode *head) {
ListNode *quick = head, *slow = head;
//注意开始需要将quick和slow走起来,因为如果开始不走,quick=slow,无法进入下面while循环
if(quick == NULL || (quick != NULL && quick->next == NULL))
return NULL;
quick = quick->next->next;
slow = slow->next;
while(quick != slow && quick && quick->next){ //注意quick和quick->next需要判空
quick = quick->next->next;
slow = slow->next;
}
if(quick != slow) //如果遇到空就说明不是环,返回NULL
return NULL;
slow = head;
while(quick != slow){
quick = quick->next;
slow = slow->next;
}
return quick;
}