链表节点的获取
如何快速获取链表的结点个数K
链表的节点是结构体指针,密钥什么办法可以快速获取链表的结点个数。
所以只能从头到尾进行循环统计:
while(temp)
{
++i;
temp=temp->next;
}
如何快速获取链表的倒数第n结点
分析:
倒数第1个就是k-(1-1),倒数第二个就是 k-(2-1),倒数第三个就是k-(3-1)
方法:
1,先统计链表节点总数,再循环到第n个节点。
单项链表如何获取当前节点的前一个节点
头节点特殊问题
很多情况下需要对头节点进行判断和作特殊处理,麻烦,怎么办:
在头节点前面再增加一个哑节点(dummy node),让头节点不再是头节点。
merge two sorted lists
Refusing to use violence algorithm to deal all question from now no.
code:
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if (l1 == nullptr) {
return l2;
} else if (l2 == nullptr) {
return l1;
} else if (l1->val < l2->val) {//如果小于
l1->next = mergeTwoLists(l1->next, l2);//获取的是
return l1;
} else {//如果大于或者等于
l2->next = mergeTwoLists(l1, l2->next);
return l2;
}
}
};
递归算法实现。
} else if (l1->val < l2->val) {//如果小于
l1->next = mergeTwoLists(l1->next, l2);//小于的下一个和大的那个比较
return l1;
} else {//如果大于或者等于
l2->next = mergeTwoLists(l1, l2->next);
return l2;
}
函数总是返回小的那个
比较之后小的那个用于获取返回值
再把小的那个的后一个和大的那个进行比较
每一次的函数返回都是复合条件的结果,知道比较到结束条件。
递归的使用:
凡是形同数据进行循环的不要再暴力实现了,记得用递归。
迭代实现:
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* preHead = new ListNode(-1);
ListNode* prev = preHead;
while (l1 != nullptr && l2 != nullptr) {
if (l1->val < l2->val) {
prev->next = l1;
l1 = l1->next;
} else {
prev->next = l2;
l2 = l2->next;
}
prev = prev->next;
}
// 合并后 l1 和 l2 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可
prev->next = l1 == nullptr ? l2 : l1;
return preHead->next;
}
};
底层原理:
两两比较,获取小的,小的往后移,大的保留下次再比较。
总链表每一次获取之后都要移到最后一个节点。
链表节点获取的注意事项
获取节点之前要先判定本节点存不存在,比如获取值为NULL的节点的下一个节点,那就不存在了。
/**
* 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) {
/**
* 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* pre=head->next;不能在这里获取
//ListNode* tp=pre->next;
if(head==nullptr)//应该先判定再获取
return head;
else if(head->next==nullptr)
return head;
else{
ListNode* pre=head->next;
ListNode* tp=pre->next;
pre->next=head;
head->next=swapPairs(tp);
return pre;
}
}
};
if(head==nullptr)
return head;
else if(head->next==nullptr)
return head;
else{
ListNode* pre=head->next;
ListNode* tp=pre->next;
pre->next=head;
head->next=swapPairs(tp);
return pre;
}
}
};
迭代法实现节点的交换要保存下来第二个节点之后的链表。
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode dummyHead = new ListNode(0);
dummyHead.next = head;
ListNode temp = dummyHead;
while (temp.next != null && temp.next.next != null) {
ListNode node1 = temp.next;
ListNode node2 = temp.next.next;
temp.next = node2;
node1.next = node2.next;
node2.next = node1;
temp = node1;
}
return dummyHead.next;
}
}
1,亚节点的使用可以减轻思维压力,也方便使用,迭代中尽量使用。