24.两两交换链表中的节点
即第一个第二个换,第三个第四个换……
自己先思考了一个,while之前是对的(笑死)。while写完运行超时了
/**
* 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) {
ListNode* left;
ListNode* right;
ListNode* tmp;
ListNode* dummyHead = new ListNode();
dummyHead->next = head;
left = dummyHead;
if (left->next == nullptr || left->next->next == nullptr) {
;
} else if (left->next->next->next == nullptr) {
right = left->next->next;
tmp = left->next;
left->next = right;
left = left->next;
right->next = tmp;
left->next = nullptr;
} else {
while (left->next->next->next != nullptr) {
right = left->next->next;
tmp = left->next;
left->next = right;
left = right;
right->next = tmp;
}
}
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* swapPairs(ListNode* head) {
ListNode* left;
ListNode* right;
ListNode* tmp;
ListNode* tmp1;
ListNode* dummyHead = new ListNode();
dummyHead->next = head;
left = dummyHead;
if (left->next != nullptr)//上下范围我还是没界定好,这个要再想想。
;
while (left->next != nullptr &&
left->next->next != nullptr) {
right = left->next->next;
tmp = left->next;
tmp1 = right->next;
left->next = right;
right->next = tmp;
tmp->next = tmp1;
left = tmp;
}
return dummyHead->next;
}
};
while (left->next != nullptr && left->next->next != nullptr)再想一下这个范围,left换完之后始终在最左边,右边要参与交换的顶多2个节点,因此最多2个next
19.删除链表的倒数第N个节点
写的很顺,其实也不太顺,运行结果有几次不通过,看着结果又想了一遍,通过了运行,但没通过提交。
我的想法是:
倒数第几个,用双指针思想的话,就是当快指针到达NULL的时候,和慢指针相差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();
dummyHead->next = head;
ListNode* fast = dummyHead;
ListNode* cur = fast;
ListNode* slow = new ListNode();
int k = 0;
while (n--)
fast = fast->next;
while (fast != nullptr) {
slow = cur;
cur = cur->next;
fast = fast->next;
k++;//计算当前节点之前有多少个节点
}
if (k == 1)
dummyHead->next = nullptr;
if (k > 1) {
if (cur->next != nullptr)
slow->next = cur->next;
else {
slow->next = nullptr;
}
}
return dummyHead->next;
}
};
下面是卡哥的代码,真简洁干净啊
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* slow = dummyHead;
ListNode* fast = dummyHead;
n++; // fast再提前走一步,因为需要让slow指向删除节点的上一个节点
while(n-- && fast != NULL) {
fast = fast->next;
}
while (fast != NULL) {
fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next;
// ListNode *tmp = slow->next; C++释放内存的逻辑
// slow->next = tmp->next;
// delete tmp;
return dummyHead->next;
}
};
02.07. 链表相交(面试题)
这是我自己写的,没有通过运行,虽然想的思路问题不大,想到了交点不是数值相等,而是指针相等,但是容易忽略很多细节。
/**
* 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) {
int intersectVal = 0, skipA = 0, skipB = 0;
ListNode* curA = headA;
ListNode* curB = headB;
while (curA != NULL && curB != NULL) {
if(curA == curB)
{
intersectVal = curA->val;
break;
}
curA = curA->next;
skipA++;
curB = curB->next;
skipB++;
}
if(intersectVal==0)
cout<<"null";
else
{
cout<<"intersected at '"<<intersectVal<<"'";
}
}
return ;
};
卡子哥比我想得更全:
1.遍历2个链表求长度,后续让两个链表对齐
2.起点不同,对齐之后让curA(长的链)移动到,和curB (短的链)末尾对齐的位置
/我也是想了一下这是为什么,很简单,题目里给出的所有案例都是对其的,我没有关注到这点,所以定位完全错误/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* curA = headA;
ListNode* curB = headB;
int lenA = 0, lenB = 0;
while (curA != NULL) { // 求链表A的长度
lenA++;
curA = curA->next;
}
while (curB != NULL) { // 求链表B的长度
lenB++;
curB = curB->next;
}
curA = headA;
curB = headB;
// 让curA为最长链表的头,lenA为其长度
if (lenB > lenA) {
swap (lenA, lenB);
swap (curA, curB);
}
// 求长度差
int gap = lenA - lenB;
// 让curA和curB在同一起点上(末尾位置对齐)
while (gap--) {
curA = curA->next;
}
// 遍历curA 和 curB,遇到相同则直接返回
while (curA != NULL) {
if (curA == curB) {
return curA;
}
curA = curA->next;
curB = curB->next;
}
return NULL;
}
};
142.环形链表II
写两个while嵌套的时候我就知道会超时QAQ。时空复杂度我还是有些拿捏不住
/**
* 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*cur = head;
ListNode*cir = head;
int pos = -1;
while(cir != NULL){
pos = -1;
while(cur != NULL)
{ cur = cur->next;
if(cur->next == cir)
{
break;
}
}
cir = cir->next;
pos++;
}
return cir;
}
};
速度记下!!
仍旧是快慢指针,追及问题,快指针以每次2个单位的速度移动,慢指针是1个,他们最终一定在环里相遇(如果有)。因为进入环之后,快指针用相对于慢指针1个单位速度追它,因此是一定会追上的,不会跳过!!-相对位置始终在缩小1-
这个等式也有意思,慢指针一定只走了一圈就会被追上,为什么呢?
因为在慢指针走满一圈的时候,快指针已经走了2圈,他们的相对距离又总是在一个单位一个单位的缩小。所以在相遇的时候慢指针必定没走够一圈,而快指针必然已经绕了一圈。
看完快慢指针和追及问题后写的代码,但是还是超出限制时间,笑得,又是没加跳出循环的break,加完之后提交成功了。第一个while里一定要有break!!还有就是定义指针的时候,让他们有所指。
/**
* 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;
ListNode *index1=head;
ListNode *index2 = head;
int pos = -1;
while (fast != NULL && slow != NULL) {
fast = fast->next->next;
slow = slow->next;
if (fast == slow) {
index1 = fast;
pos = 0;
break;
}
}
while (index1 != index2) {
index1 = index1->next;
index2 = index2->next;
pos++;
}
if(pos == -1)
return NULL;
else
return index1;
}
};
卡子哥的循环嵌套更有意思点,看似双层嵌套,但是在追上的那一刻快慢指针就静止了,换成了相遇点和起点的指针出发。所以更快
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode* fast = head;
ListNode* slow = head;
while(fast != NULL && fast->next != NULL) {
slow = slow->next;
fast = fast->next->next;
// 快慢指针相遇,此时从head 和 相遇点,同时查找直至相遇
if (slow == fast) {
ListNode* index1 = fast;
ListNode* index2 = head;
while (index1 != index2) {
index1 = index1->next;
index2 = index2->next;
}
return index2; // 返回环的入口
}
}
return NULL;
}
};