1.链表概念:
暂略。
2.栈的相关题目:
2.1 leetcode 237 —— Delete Node in a Linked List
注意:这个题没有给head~
/**
* 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) {
node->val = node->next->val;
node->next = node->next->next;
}
};
2.2 ***leetcode 206 —— Reverse Linked List
这个题虽然简单但是还蛮重要的~
1.迭代:
参考链接:http://www.pianshen.com/article/517476376/
/**
* 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* pre = NULL;
ListNode* nxt;
while(head != NULL)
{
nxt = head->next;
head->next = pre;
pre = head;
head = nxt;
}
return pre;
}
};
2.递归:
/**
* 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* res;
if(head == NULL || head->next == NULL)
{
return head;
}
res = reverseList(head->next);//保存最后一个节点 也是反转后的头节点
head->next->next = head;
head->next = NULL;
return res;
}
};
2.3 ***leetcode 21 —— Reverse Linked List
迭代:
/**
* 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* begin = NULL;
ListNode* pre;
if(!l1)
{
return l2;
}
if(!l2)
{
return l1;
}
while(l1 && l2)
{
if(l1->val <= l2->val)
{
if(!begin)
{
begin = l1;
}
else
{
pre->next = l1;
}
pre = l1;
l1 = l1->next;
}
else
{
if(!begin)
{
begin = l2;
}
else
{
pre->next = l2;
}
pre = l2;
l2 = l2->next;
}
}
pre->next = l1 ? l1 : l2;
return begin;
}
};
递归:
做递归题的时候需要思考子问题是什么
/**
* 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) {
//返回值永远是当前两个节点较小的那个
if(l1 == NULL)
{
return l2;
}
else if(l2 == NULL)
{
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;
}
}
}
};
2.4 ***leetcode 160 —— Intersection of Two Linked Lists
设A链长m,B链长n,相交点为长链中第k个。
容易想到的方法1:O(m+n+k)
思路:先计算两个链的长度,然后移动长链头结点到与短链相等处,然后开始判断两个链的当前节点是否相等
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if(headA == NULL || headB == NULL)
{
return NULL;
}
ListNode* A = headA;
ListNode* B = headB;
int lenA = 0;
int lenB = 0;
int i;
while(A)
{
A = A->next;
lenA++;
}
while(B)
{
B = B->next;
lenB++;
}
i = lenA > lenB ? lenA - lenB : lenB - lenA;
A = headA;
B = headB;
if(lenA > lenB)
{
for(;i>0;i--)
{
A = A->next;
}
}
else
{
for(;i>0;i--)
{
B = B->next;
}
}
while(A != NULL || B != NULL)
{
if(A == B)
{
return A;
}
else
{
A = A->next;
B = B->next;
}
}
return NULL;
}
};
代码简洁的方法2:O(m+n)
把AB两个链拼接在一起,A的头结点走链A+B,B的头结点走链B+A,走的过程中判断两个链当前节点是否相等,拼接链的结尾为NULL,若没有交点走到最后两个链的当前节点也会都等于NULL。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *A = headA;
ListNode *B = headB;
while(A != B)
{
A = A ? A->next : headB;
B = B ? B->next : headA;
}
return A;
}
};
2.5 ***leetcode 141 —— Linked List Cycle
快慢指针就可以解了~
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
ListNode* slow = head;
ListNode* fast = head;
while(slow && fast && fast->next && fast->next != slow)
{
slow = slow->next;
fast = fast->next->next;
}
if(!slow || !fast || !fast->next)
{
return false;
}
return true;
}
};
2.6 ***leetcode 234 —— Palindrome Linked List
注意链表可以是偶数长度也可以是奇数长度。
/**
* 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) {
if(!head || !head->next)
{
return true;
}
if(!head->next->next)
{
if(head->val == head->next->val)
{
return true;
}
return false;
}
ListNode* middle = NULL;
ListNode* begin = head;
while(begin && begin->next && begin->next->next)
{
if(begin->val == begin->next->next->val)
{
middle = begin->next->next;
begin->next = NULL;
break;
}
else if(begin->val == begin->next->val)
{
middle = begin->next;
begin->next = NULL;
break;
}
else
{
begin = begin->next;
}
}
if(!middle)
{
return false;
}
else
{
ListNode* pre = NULL;
ListNode* nxt;
while(middle)
{
nxt = middle->next;
middle->next = pre;
pre = middle;
middle = nxt;
}
while(head && pre)
{
if(head->val != pre->val)
{
return false;
}
else
{
head = head->next;
pre = pre->next;
}
}
if(!head && !pre)
{
return true;
}
}
return false;
}
};
2.7 ***leetcode 148 —— Sort List
这个题用的是归并排序,各个排序的复杂度对比见此链接:
但是用链表实现起来比较困难,我参考了下面的链接:(链接内容非常好!)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* sortList(ListNode* head) {
ListNode begin(0);
begin.next = head;
auto p = head;
int len = 0;
while(p)
{
len++;
p = p->next;
}
for(int step = 1;step < len;step <<= 1)
{
auto cur = begin.next;
auto tail = &begin;
while(cur)
{
auto left = cur;
auto right = cut(left,step);
cur = cut(right,step);
tail->next = merge(left, right);
while (tail->next)
{
tail = tail->next;
}
}
}
return begin.next;
}
ListNode* cut(ListNode* head,int n)
{
auto p = head;
while(--n && p)
{
p = p->next;
}
if(!p) return p;
auto nxt = p->next;
p->next = NULL;
return nxt;
}
ListNode* merge(ListNode* l1,ListNode* l2)
{
ListNode* begin = NULL;
ListNode* pre;
if(!l1)
{
return l2;
}
if(!l2)
{
return l1;
}
while(l1 && l2)
{
if(l1->val <= l2->val)
{
if(!begin)
{
begin = l1;
}
else
{
pre->next = l1;
}
pre = l1;
l1 = l1->next;
}
else
{
if(!begin)
{
begin = l2;
}
else
{
pre->next = l2;
}
pre = l2;
l2 = l2->next;
}
}
pre->next = l1 ? l1 : l2;
return begin;
}
};
2.8 ***leetcode 328 —— Odd Even Linked List
/**
* 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)
{
return NULL;
}
if(!head->next || !head->next->next)
{
return head;
}
ListNode evenBegin(0);
ListNode* odd = head;
ListNode* even = head->next;
evenBegin.next = even;
while(even && even->next)
{
odd->next = even->next;
odd = odd->next;
even->next = odd->next;
even = even->next;
}
odd->next = evenBegin.next;
return head;
}
};
2.9 ***leetcode 2 —— Add Two Numbers
链表后元素置0使两个链表长度相等
/**
* 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) {
ListNode dummyHead(0);
ListNode* curr = &dummyHead;
int carry = 0;
while(l1 || l2)
{
int a = l1? l1->val : 0;
int b = l2? l2->val : 0;
int sum = a + b + carry;
curr->next = new ListNode(sum % 10);
curr = curr->next;
carry = sum / 10;
l1 = l1 ? l1->next : l1;
l2 = l2 ? l2->next : l2;
}
if(carry)
{
curr->next = new ListNode(carry);
}
return dummyHead.next;
}
};
2.10 ***leetcode 19 —— Remove Nth Node From End of List
用快慢指针做
/**
* 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* fast = head;
ListNode* slow = head;
ListNode dummyHead(0);
dummyHead.next = head;
ListNode* pre = &dummyHead;
while(n--)
{
fast = fast->next;
}
while(fast)
{
fast = fast->next;
pre = slow;
slow = slow->next;
}
pre->next = slow->next;
return dummyHead.next;
}
};
2.11 ***leetcode 142 —— Linked List Cycle II
题解参考:https://leetcode-cn.com/problems/linked-list-cycle-ii/solution/huan-xing-lian-biao-ii-by-leetcode/
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode* fast = head;
ListNode* slow = head;
while(fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
if(fast == slow)
{
break;
}
}
if(!fast || !fast->next)
{
return NULL;
}
slow = head;
while(slow != fast)
{
fast = fast->next;
slow = slow->next;
}
return slow;
}
};
2.12 ***leetcode 138 —— Copy List with Random Pointer
这个问题的关键在于找拷贝后结点的random位置,比较笨的办法是,先不管random按照next建立深拷贝后的链表,然后再从第一个结点开始,遍历新链表,并将random赋值。这个方法的复杂度为O(n∧2)。
所以问题的核心就是想办法在O(n)时间内找到每个新节点random该指的位置。
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;
Node() {}
Node(int _val, Node* _next, Node* _random) {
val = _val;
next = _next;
random = _random;
}
};
*/
class Solution {
public:
Node* copyRandomList(Node* head) {
if(!head)
{
return NULL;
}
Node dummyHeadOld(0,NULL,NULL);
dummyHeadOld.next = head;
while(head)
{
Node* tmp = new Node(head->val,head->next,NULL);
head->next = tmp;
head = tmp->next;
}
Node dummyHeadNew(0,NULL,NULL);
dummyHeadNew.next = dummyHeadOld.next->next;
Node* p = dummyHeadNew.next;
head = dummyHeadOld.next;
while(head)
{
p->random = head->random ? head->random->next : NULL;
head = p->next;
if(head)
{
p = head->next;
}
}
head = dummyHeadOld.next;
p = dummyHeadNew.next;
while(head)
{
head->next = p->next;
head = head->next;
if(head)
{
p->next = head->next;
p = p->next;
}
}
return dummyHeadNew.next;
}
};
2.13 ***leetcode 61 —— Rotate List
注意k比链表长的情况
/**
* 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)
{
return NULL;
}
if(!k || !head->next)
{
return head;
}
ListNode dummyHead(0);
dummyHead.next = head;
ListNode* tail;
int len = 0;
int newK = 0;
while(head)
{
if(!head->next)
{
tail = head;
}
head = head->next;
len++;
}
newK = len - (k % len) + 1;
head = dummyHead.next;
for(int i = 1;i < newK -1;i++)
{
head = head->next;
}
tail->next = dummyHead.next;
dummyHead.next = head->next;
head->next = NULL;
return dummyHead.next;
}
};
2.14 ***leetcode 23 —— Merge k Sorted Lists
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
if(lists.size() < 1)
{
return NULL;
}
for(int step = 1;step < lists.size();step = step * 2)
{
int curr = 0;
while(curr < lists.size())
{
lists[curr] = (curr + step) < lists.size() ? merge(lists[curr],lists[curr+step]) : lists[curr];
curr += 2 * step;
}
}
return lists[0];
}
ListNode* merge(ListNode* l1,ListNode* l2)
{
ListNode* begin = NULL;
ListNode* pre;
if(!l1)
{
return l2;
}
if(!l2)
{
return l1;
}
while(l1 && l2)
{
if(l1->val <= l2->val)
{
if(!begin)
{
begin = l1;
}
else
{
pre->next = l1;
}
pre = l1;
l1 = l1->next;
}
else
{
if(!begin)
{
begin = l2;
}
else
{
pre->next = l2;
}
pre = l2;
l2 = l2->next;
}
}
pre->next = !l1 ? l2 : l1;
return begin;
}
};