哨兵节点ListNode prehead = new ListNode(0);ListNode prev = prehead; 的用法
哨兵节点简介
哨兵节点是做链表题目时经常用到的写法,由于在对链表进行重新排列、打断、合并等等操作时,链表的头节点往往会发生移动变得“破朔迷离”,故在一开始我们设定一个哨兵节点,这可以在最后让我们比较容易地返回合并后的链表。
常见写法
ListNode a = new ListNode(0);
ListNode b = a;
- 这两句代码的意义
因为a和b都是指针,b=a的意思是b与a指向同一个结点,那么改变b指向的链表结点时,由于b和a指向同一个节点,b也会改变。 - 这两句代码的作用
在对链表的操作中,链表的头节点head往往会发生移动,这样我们将难以找到最终链表的头指针,故我们需要提前设置一个哨兵节点 ans ,这可以在最后让我们比较容易地返回最终的链表。
实战演练:leetcode21. 合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
思路:
显然,我们需要维护一个 head 指针,我们需要做的是调整它的 next 指针。然后,我们重复以下过程 :如果 l1 当前节点的值小于等于 l2 ,我们就把 l1 当前的节点接在 head 节点的后面同时将 l1 指针往后移一位。否则,我们对 l2 做同样的操作,然后把 head 向后移一位。
注意,由于head会发生移动,这样我们将难以找到输出链表的头指针,故我们需要提前设置一个哨兵节点 ans ,这可以在最后让我们比较容易地返回合并后的链表。
在循环终止的时候, l1 和 l2 至多有一个是非空的。由于输入的两个链表都是有序的,所以不管哪个链表是非空的,它包含的所有元素都比前面已经合并链表中的所有元素都要大。这意味着我们只需要简单地将非空链表接在合并链表的后面,并返回合并链表即可。
题解:
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* ans=new ListNode(0);
ListNode* head=ans;
while(l1!=nullptr && l2!=nullptr){
if( l1->val < l2->val ){
head->next=l1;
l1=l1->next;
head=head->next;
}
else{
head->next=l2;
l2=l2->next;
head=head->next;
}
}
head->next= l1==nullptr ? l2 : l1 ;
return ans->next;
}
};
- 复杂度分析
时间复杂度:O(n + m),其中 n 和 m 分别为两个链表的长度。因为每次循环迭代中,l1 和 l2 只有一个元素会被放进合并链表中, 因此 while 循环的次数不会超过两个链表的长度之和。所有其他操作的时间复杂度都是常数级别的,因此总的时间复杂度为 O(n+m)。
空间复杂度:O(1)。我们只需要常数的空间存放若干变量。
♥♥♥有帮助的话,给个赞吧♥♥♥
注
题目来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/string-to-integer-atoi
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
博客著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。