List
链表结构
如无特殊说明,链表结构如下:
// 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) {
}
}
链表模板1
链表的创建,打印,销毁。
#include <iostream>
#include <vector>
using namespace std;
struct ListNode {
int val;
ListNode* next;
ListNode():val(0),next(nullptr) {
}
ListNode(int v):val(v),next(nullptr) {
}
ListNode(int v, ListNode* p):val(0),next(p) {
}
};
ListNode* createList(const vector<int>& nums)
{
ListNode dummy(0);
ListNode* node = &dummy;
for (const int& n: nums)
{
node->next = new ListNode(n);
node = node->next;
}
return dummy.next;
}
void printList(ListNode* head)
{
while (head)
{
cout << head->val << " ";
head = head->next;
}
cout << endl;
}
void destroyList(ListNode* head)
{
while (head)
{
ListNode* delNode = head;
head = head->next;
delete delNode;
}
}
int main(int argc, char* argv[])
{
vector<vector<int>> nums{
{
}, {
1}, {
1,2,3,4,5,6}};
for (auto& n: nums)
{
cout << "---------------" << endl;
ListNode* head = createList(n);
printList(head);
// ... do something here
printList(head);
destroyList(head);
}
return 0;
}
链表模板2
输入是字符串如:“1->2->3->4”,根据字符串创建链表。
#include <iostream>
#include <vector>
using namespace std;
struct ListNode {
int val;
ListNode* next;
ListNode():val(0),next(nullptr) {
}
ListNode(int v):val(v),next(nullptr) {
}
ListNode(int v, ListNode* p):val(0),next(p) {
}
};
ListNode* createList(const vector<int>& nums)
{
ListNode dummy(0);
ListNode* node = &dummy;
for (const int& n: nums)
{
node->next = new ListNode(n);
node = node->next;
}
return dummy.next;
}
void printList(ListNode* head)
{
while (head)
{
cout << head->val;
head = head->next;
if (head) // 注意这里的链表打印!!
cout << "->";
}
cout << endl;
}
void destroyList(ListNode* head)
{
while (head)
{
ListNode* delNode = head;
head = head->next;
delete delNode;
}
}
// 函数参数是字符串!!
ListNode* createList(string& str)
{
if (str == "")
return nullptr;
ListNode dummy(0);
ListNode* node = &dummy;
int i = 0;
int n = str.size();
int num = 0;
while (i < n)
{
if (str[i] >= '0' && str[i] <= '9')
{
num = num * 10 + (str[i] - '0');
}
else if(str[i] == '-')
{
node->next = new ListNode(num);
node = node->next;
num = 0;
}
i++;
}
node->next = new ListNode(num);
return dummy.next;
}
int main(int argc, char* argv[])
{
string str1;
cin >> str1; // 1->2->3
string str2;
cin >> str2; // 0->1->4->5
ListNode* head1 = createList(str1);
ListNode* head2 = createList(str2);
// do something ...
destroyList(head1);
destroyList(head2);
return 0;
}
19. 删除链表的倒数第 N 个结点
问题描述:
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
要求只能使用一趟扫描。
其中:
链表中结点的数目为 sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz
比如:
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
解析:
- 该题可以用快慢指针来实现一趟扫描找出被删除节点。只要让两个节点指针相差(n-1)个节点,然后让快的节点指针指向链表的最后一个节点,那么慢的节点指针自然指向要删除的那个节点。
- 注意被删除节点为头节点的情况,也就是n == sz的情况,需要设置哨兵节点。
- 让两个快慢两个指针的差距为n,可以减少一个prevNode的变量。
代码实现:
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode dummy(0);
dummy.next = head;
ListNode* slow = &dummy;
ListNode* fast = slow;
for (int i = 0; i < n; i++)
fast = fast->next;
while (fast->next)
{
slow = slow->next;
fast = fast->next;
}
ListNode* temp = slow->next->next;
delete slow->next;
slow->next = temp;
return dummy.next;
}
};
21. 合并两个有序链表
问题描述:
将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例1:
输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
解析:
- 总体思路是:每次比较链表l1和链表l2的值,那个小,就将该节点合入新链表中,然后继续拿小节点的next节点和之前大节点进行比较,直到其中一个链表为空。
- 定义一个虚拟节点,取值为INT_MIN,确保在排序之后,始终是第一个节点,那这样的话,虚拟节点的next节点就是真正的新链表指针。
代码实现:
class Solution {
public:
ListNode* mergeTwoLists(</