链表相关的笔记
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* pPre = NULL;
ListNode* pCur = head;
ListNode* pNext = NULL;
while(pCur){
pNext = pCur->next;
pCur->next = pPre;
pPre = pCur;
pCur = pNext;
}
return pPre;
}
};
/* 整体思路:
* 在反转链表的基础上,记录好左侧部分和右侧部分结点,然后和局部反转后的链表拼接起来即可
*/
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
if (head == NULL || m < 1 || n < m)
return NULL;
ListNode* dummyHead = new ListNode(-1);
dummyHead->next = head;
ListNode* pCur = dummyHead;
ListNode* pPre = NULL;
ListNode* pNext = NULL;
// 让pCur指向m结点的前一个结点,存储为left
for (int i = 1; i <= m - 1; ++i)
pCur = pCur->next;
ListNode* left = pCur;
// pCur指向m结点
pCur = pCur->next;
// 反转部分的尾结点存储为right
ListNode* right = pCur;
// 对m到n位置的数进行反转
// 反转后这部分头结点为pPre
// 尾结点需要事先存储为right
// pNext为n右侧部分的头结点
// right -> pNext
// pPre接上m左侧部分 left->pPre
// pNext接上n右侧部分
for (int i = m; i <= n; ++i){
pNext = pCur->next;
pCur->next = pPre;
pPre = pCur;
pCur = pNext;
}
// left -> reverse part head: pPre -> ... -> reverse part tail:right ->pNext
left->next = pPre;
right->next = pNext;
return dummyHead->next;
}
};
通过vector创建链表、打印链表、删除链表释放空间
ListNode* createLinkedList(vector<int> v){
if (v.empty())
return NULL;
ListNode* head = new ListNode(v[0]);
ListNode* pCur = head;
for (int i = 1; i < v.size(); ++i){
pCur->next = new ListNode(v[i]);
pCur = pCur->next;
}
return head;
}
void printLinkedList(ListNode* head){
while (head != NULL){
cout << head->val << " -> ";
head = head->next;
}
cout << "NULL" << endl;
}
void deleteLinkedList(ListNode* head){
ListNode* pCur = head;
while (pCur){
ListNode* delNode = pCur;
pCur = pCur->next;
delete delNode;
}
return;
}
/* 整体思路:
* 当前结点和下一个结点比较,相同则删除下一个结点,否则直接滑动一个结点
*/
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if(head == NULL)
return NULL;
ListNode* pCur = head;
while(pCur && pCur->next){
if(pCur->val == pCur->next->val){
ListNode* delNode = pCur->next;
pCur->next = pCur->next->next;
delete delNode;
}else
pCur = pCur->next;
}
return head;
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* partition(ListNode* head, int x) {
if (head == NULL)
return NULL;
ListNode* pCur = head;
ListNode* left = new ListNode(-1);
ListNode* right = new ListNode(-1);
ListNode* l = left;
ListNode* r = right;
while (pCur){
if (pCur->val < x){
l->next = pCur;
l = l->next;
//pCur_left = NULL;
}
else{
r->next = pCur;
r = r->next;
}
pCur = pCur->next;
}
// r的next指针必须置为0,因为它是right的最后一个结点
r->next = NULL;
l->next = right->next;
return left->next;
}
};
// 看看代码,画画图就懂了
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* oddEvenList(ListNode* head) {
if(head == NULL)
return NULL;
ListNode* first = head;
ListNode* second = head->next;
ListNode* temp = second;
while(second && second->next){
first->next = second->next;
first = first->next;
second->next = first->next;
second = second->next;
}
first->next = temp;
return head;
}
};
// 处理好进位即可,尤其是最后一位为1时,不要忘记单独处理
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
int jw = 0;
int sum = 0;
ListNode* head = new ListNode(0);
ListNode* pCur = head;
while(l1 || l2){
sum = (l1 ? l1->val : 0) + (l2 ? l2->val : 0) + jw;
jw = sum / 10;
pCur->next = new ListNode(sum % 10);
pCur = pCur->next;
l1 = (l1 ? l1->next : l1);
l2 = (l2 ? l2->next : l2);
}
if(jw)
pCur->next = new ListNode(1);
return head->next;
}
};
// 整体思路:用栈即可
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
stack<ListNode*> s1;
stack<ListNode*> s2;
stack<ListNode*> result;
while(l1){
s1.push(l1);
l1 = l1->next;
}
while(l2){
s2.push(l2);
l2 = l2->next;
}
int jw = 0;
while(!s1.empty() || !s2.empty()){
if(!s1.empty()){
l1 = s1.top();
s1.pop();
}else
l1 = NULL;
if(!s2.empty()){
l2 = s2.top();
s2.pop();
}else
l2 = NULL;
int sum = (l1 ? l1->val : 0) + (l2 ? l2->val : 0) + jw;
jw = sum / 10;
result.push(new ListNode(sum % 10));
}
// 注意最后的进位
if(jw)
result.push(new ListNode(1));
// 将结果依次出栈
ListNode* newHead = result.top();
result.pop();
ListNode* pCur = newHead;
while(!result.empty()){
pCur->next = result.top();
result.pop();
pCur = pCur->next;
}
return newHead;
}
};
设立链表的虚拟头结点dummyHead
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
if(head == NULL)
return NULL;
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* pCur = dummyHead;
while(pCur && pCur->next){
if(pCur->next->val == val){
ListNode* delNode = pCur->next;
pCur->next = pCur->next->next;
delete delNode;
}else
pCur = pCur->next;
}
return dummyHead->next;
}
};
// 用两个指针一前一后遍历
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if(head == NULL)
return NULL;
ListNode* newHead = new ListNode(0);
newHead->next = head;
ListNode* pCur = newHead;
ListNode* pre = head->next;
ListNode* behind = head;
while(pre != NULL){
if(pre->val != behind->val){
pCur->next = behind;
pCur = pCur->next;
pre = pre->next;
behind = behind->next;
}else{
while(pre && pre->val == behind->val){
// 直到pre为空 或者 不等于behind
pre = pre->next;
}
while(behind != pre){
ListNode* delNode = behind;
behind = behind->next;
delete delNode;
}
pCur->next = behind;
if(pre == NULL)
return newHead->next;
pre = pre->next;
}
}
return newHead->next;
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* newHead = new ListNode(0);
ListNode* pCur = newHead;
while(l1 || l2){
if(l1 == NULL){
pCur->next = l2;
break;
}
if(l2 == NULL){
pCur->next = l1;
break;
}
if(l1->val < l2->val){
pCur->next = l1;
l1 = l1->next;
pCur = pCur->next;
}else{
pCur->next = l2;
l2 = l2->next;
pCur = pCur->next;
}
}
return newHead->next;
}
};
// 实现分析好需要几个临时指针变量
// 画图分析一下指针变换顺序即可
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* dummyHead = new ListNode(0);
// 指向dummyHead的指针
ListNode* d_pCur = dummyHead;
dummyHead->next = head;
ListNode* pCur = head;
// 至少两个非空结点才swap
while (pCur && pCur->next) {
ListNode* temp = pCur->next;
ListNode* pNext = pCur->next;
pCur->next = pCur->next->next;
pNext->next = pCur;
d_pCur->next = temp;
d_pCur = d_pCur->next->next;
pCur = pCur->next;
}
return dummyHead->next;
}
};
// 链表排序,这段代码多体会一下
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *insertionSortList(ListNode *head) {
ListNode *sortedHead = new ListNode(-1);
while(head != NULL){
//保存head的下一个结点
ListNode *temp = head->next;
ListNode *cur = sortedHead;
while(cur->next != NULL && cur->next->val < head->val)
cur = cur->next;
//插入
head->next = cur->next;
cur->next = head;
//恢复head为head的下一个结点
head = temp;
}
return sortedHead->next;
}
};
// 将后一个结点的值赋值给当前结点
// 然后删除后一个结点即可
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
void deleteNode(ListNode* node) {
if(node == NULL)
return;
// 题目已经强调不是尾结点, 不需要考虑
// if(node->next == NULL)
// do something
node->val = node->next->val;
ListNode* delNode = node->next;
node->next = delNode->next;
delete delNode;
return;
}
};
双指针技术
// 两个指针一前一后扫描一遍即可,其中一个指针先行
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* pre = dummyHead;
ListNode* behind = dummyHead;
while(n--)
pre = pre->next;
while(pre->next){
pre = pre->next;
behind = behind->next;
}
// behind达到待删除结点的前驱
ListNode* delNode = behind->next;
behind->next = delNode->next;
delete delNode;
return dummyHead->next;
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* rotateRight(ListNode* head, int k) {
if (head == NULL)
return NULL;
// k 的大小可能大于链表的长度: 先计算链表长度,k = k % length
ListNode* pCur = head;
int length = 0;
while (pCur){
++length;
pCur = pCur->next;
}
k = k % length;
// k如果等于0,不需要旋转
if (k == 0)
return head;
// 原始链表:left_start ,..., left_end, right_start, ..., right_end
// 旋转结果:right_start, ..., right_end, left_start, ..., left_end
// 找到右半部分的前驱,也就是左半部分的最后一个结点left_end
// left_start就是head,不需要寻找了
ListNode* left_end = head;
for (int i = 1; i < length - k; ++i){
left_end = left_end->next;
}
// right_start是left_end的下一个结点
ListNode* right_start = left_end->next;
ListNode* right_end = right_start;
// right_end是尾结点
while (right_end->next != NULL)
right_end = right_end->next;
right_end->next = head;
left_end->next = NULL;
return right_start;
}
};
// 分三步:
// 1.找到中间结点
// 2.将右半侧反转
// 3.合并两个链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
void reorderList(ListNode* head) {
if(head == NULL || head->next == NULL)
return;
// 找到中间结点
ListNode* p1 = head;
ListNode* p2 = head->next;
while(p2 && p2->next){
p1 = p1->next;
p2 = p2->next->next;
}
ListNode* middleHead = p1->next;
p1->next = NULL;
// 反转middleHead开始的部分
ListNode* pPre = NULL;
ListNode* pCur = middleHead;
ListNode* pNext = NULL;
while(pCur){
pNext = pCur->next;
pCur->next = pPre;
pPre = pCur;
pCur = pNext;
}
middleHead = pPre;
// 合并
for (p1 = head, p2 = middleHead; p1; ) {
ListNode* temp = p1->next;
p1->next = p2;
p1 = p2;
p2 = temp;
}
}
};
// 思路:创建一个辅助栈,依次比较即可
// 此题还有空间更高效的算法:O(1)空间复杂度,O(n)时间复杂度
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool isPalindrome(ListNode* head) {
stack<ListNode*> s;
ListNode* pCur = head;
while(pCur){
s.push(pCur);
pCur = pCur->next;
}
pCur = head;
while(!s.empty()){
ListNode* temp = s.top();
s.pop();
if(temp->val != pCur->val)
return false;
pCur = pCur->next;
}
return true;
}
};