在解决链表问题时创建一个额外的节点是一个好习惯吗?
Is creating an extra node when solving linked list question a good habit?
最近,我一直在研究 LeetCode 上的链表问题,我注意到在处理链表(如排序链表)时,人们有时会创建一个 虚拟节点 和 return dummy->next
。这是一个非常方便的行为,但是这样做会不会有任何不好的结果(比如说,如果我最后删除它以避免内存泄漏)?或者,是否有任何情况使此行为不合适?
下面的代码是一个例子,ohead
是我的dummy节点:
/**
* 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* oddEvenList(ListNode* head) {
ListNode *ohead = new ListNode, *ehead = new ListNode;
ListNode *optr = ohead, *eptr = ehead;
bool isOdd = true;
for(auto ptr = head; ptr; ptr = ptr->next){
if(isOdd){
optr->next = ptr;
optr = optr->next;
}
else{
eptr->next = ptr;
eptr = eptr->next;
}
isOdd = !isOdd; //update isOdd
}
optr->next = ehead->next;
eptr->next = nullptr;
return (ohead->next);
}
};
没有,新建节点没有问题。因为解决 LeetCode 问题最重要的是算法的效率(时间和内存复杂度)。添加一个新节点是恒定的时间和内存,不会改变解决方案的复杂性。
这是一个 O(N) 时间和 O(1) space 解决方案,可以通过 LeetCode 的“在线法官”来解决您要解决的问题:
class Solution {
public:
ListNode* oddEvenList(ListNode* head) {
if (!head) {
return head;
}
ListNode* odd = head;
ListNode* even_head = head->next;
ListNode* even = even_head;
while (even && even->next) {
odd->next = odd->next->next;
even->next = even->next->next;
odd = odd->next;
even = even->next;
}
odd->next = even_head;
return head;
}
};
参考资料
更多详情,您可以查看Discussion Board。有很多公认的解决方案、解释、各种语言的高效算法,以及 time/space 复杂性分析。
-
-
最近,我一直在研究 LeetCode 上的链表问题,我注意到在处理链表(如排序链表)时,人们有时会创建一个 虚拟节点 和 return dummy->next
。这是一个非常方便的行为,但是这样做会不会有任何不好的结果(比如说,如果我最后删除它以避免内存泄漏)?或者,是否有任何情况使此行为不合适?
下面的代码是一个例子,ohead
是我的dummy节点:
/**
* 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* oddEvenList(ListNode* head) {
ListNode *ohead = new ListNode, *ehead = new ListNode;
ListNode *optr = ohead, *eptr = ehead;
bool isOdd = true;
for(auto ptr = head; ptr; ptr = ptr->next){
if(isOdd){
optr->next = ptr;
optr = optr->next;
}
else{
eptr->next = ptr;
eptr = eptr->next;
}
isOdd = !isOdd; //update isOdd
}
optr->next = ehead->next;
eptr->next = nullptr;
return (ohead->next);
}
};
没有,新建节点没有问题。因为解决 LeetCode 问题最重要的是算法的效率(时间和内存复杂度)。添加一个新节点是恒定的时间和内存,不会改变解决方案的复杂性。
这是一个 O(N) 时间和 O(1) space 解决方案,可以通过 LeetCode 的“在线法官”来解决您要解决的问题:
class Solution {
public:
ListNode* oddEvenList(ListNode* head) {
if (!head) {
return head;
}
ListNode* odd = head;
ListNode* even_head = head->next;
ListNode* even = even_head;
while (even && even->next) {
odd->next = odd->next->next;
even->next = even->next->next;
odd = odd->next;
even = even->next;
}
odd->next = even_head;
return head;
}
};
参考资料
更多详情,您可以查看Discussion Board。有很多公认的解决方案、解释、各种语言的高效算法,以及 time/space 复杂性分析。