单链表反转https://www.nowcoder.com/practice/75e878df47f24fdc9dc3e400ec6058ca?tpId=295&tqId=23286&ru=/exam/oj&qru=/ta/format-top101/question-ranking&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3D%25E7%25AE%2597%25E6%25B3%2595%25E7%25AF%2587%26topicId%3D295
//思路一:利用栈的后进先出的特点
//此题可以先让所有结点入栈,再出栈的时候进行链接
//空间复杂度 O(N) 时间复杂度O(N)
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
stack sL;
while (pHead)
{
sL.push(pHead);
pHead = pHead->next;
}
if (sL.empty())
return nullptr;
ListNode* first = sL.top();
ListNode* next = first;
while (1)
{
sL.pop();
if (sL.empty())
break;
ListNode* temp = sL.top();
next->next = temp;
next = next->next;
}
next->next = nullptr;
return first;
}
};
//思路二:双指针
//记录第一个节点和下一个节点,改变其指向
//空间复杂度 O(1) 时间复杂度O(N)
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
ListNode* newHead = nullptr;
while (pHead)
{
ListNode* tmp = pHead->next;
pHead->next = newHead;
newHead = pHead;
pHead = tmp;
}
return newHead;
}
};
n到m链表反转https://www.nowcoder.com/practice/b58434e200a648c589ca2063f1faf58c?tpId=295&tqId=654&ru=/exam/oj&qru=/ta/format-top101/question-ranking&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3D%25E7%25AE%2597%25E6%25B3%2595%25E7%25AF%2587%26topicId%3D295
//思路一:四指针
// 记录需要反转区间的前一个prev及需要反转的下一个left
// 记录需要反转区间的最后一个right及下一个cur
// 时间复杂度: O(N) 空间复杂度O(1)
class Solution {
public:
void reverseList(ListNode* head){
ListNode* phead = nullptr;
ListNode* cur = head;
while (cur)
{
ListNode* tmp = cur->next;
cur->next = phead;
phead = cur;
cur = tmp;
}
}
ListNode* reverseBetween(ListNode* head, int m, int n) {
ListNode* phead = new ListNode;
phead->val = -1;
phead->next = head;
ListNode* prev = phead;
for (int i = 0; i < m - 1; i++)
{
prev = prev->next;
}
ListNode* left = prev->next;
ListNode* right = prev;
for (int i = 0; i < n - m + 1; i++)
{
right = right->next;
}
ListNode* cur = right->next;
right->next = nullptr;
prev->next = nullptr;
reverseList(left);
prev->next = right;
left->next = cur;
return phead->next;
// write code here
}
};
//思路二:双指针
//直接改变各指针指向
//时间复杂度: O(N) 空间复杂度O(1)
class Solution
{
public:
ListNode* reverseBetween(ListNode* head, int m, int n)
{
ListNode* phead = new ListNode;
phead->val = -1;
phead->next = head;
ListNode* prev = phead;
for (int i = 1; i <= m - 1; i++)
{
prev = prev->next;
}
ListNode* cur = prev->next;
for (int i = 1; i <= n - m; i++)
{
ListNode* CurNext = cur->next;
cur->next = CurNext->next;
CurNext->next = prev->next;
prev->next = CurNext;
}
return phead->next;
}
};
k个节点反转https://www.nowcoder.com/practice/b49c3dc907814e9bbfa8437c251b028e?tpId=295&tqId=722&ru=/exam/oj&qru=/ta/format-top101/question-ranking&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3D%25E7%25AE%2597%25E6%25B3%2595%25E7%25AF%2587%26topicId%3D295
//思路和上面翻转(n.m)链表思路同
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
int n = 0;
ListNode* num_head = head;
while (num_head)
{
num_head = num_head->next;
++n;
}
n /= k; //需要翻转次数
ListNode* phead = new ListNode(-1);
phead->next = head;
ListNode* prev = phead;
ListNode* cur = prev->next;
while (n--)
{
for (int i = 1; i < k; i++)
{
ListNode* cur_next = cur->next; //将需要翻转的往前链接
cur->next = cur_next->next;
cur_next->next = prev->next;
prev->next = cur_next;
}
prev = cur;
cur = cur->next;
}
return phead->next;
// write code here
}
};
合并有序链表https://www.nowcoder.com/practice/d8b6b4358f774294a89de2a6ac4d9337?tpId=295&tqId=23267&ru=/exam/oj&qru=/ta/format-top101/question-ranking&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3D%25E7%25AE%2597%25E6%25B3%2595%25E7%25AF%2587%26topicId%3D295
//思路:双指针
//每次比较节点值大小,依次链接到新的链表
//时间复杂度O(N) 空间复杂度O(1)
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
ListNode*p1=pHead1;
ListNode*p2=pHead2;
ListNode*npHead=new ListNode(-1);
ListNode*cur=npHead;
while(p1)
{
if(p1->valval || p2==nullptr)
{
cur->next=p1;
p1=p1->next;
cur=cur->next;
}
else if(p1->val>=p2->val || p1==nullptr)
{
cur->next=p2;
p2=p2->next;
cur=cur->next;
}
}
if(p2) cur->next=p2; //p2不为nullpt直接链接剩下的
return npHead->next;
}
};
合并K个有序链表
//思路一:
//复用上题合并两个有序链表
//第一次将lists[0]和lists[1]结合成一个大链表,再将大链表与后面链表依次合并
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
ListNode* p1 = pHead1;
ListNode* p2 = pHead2;
ListNode* npHead = new ListNode(-1);
ListNode* cur = npHead;
while (p1) {
if (p1->val < p2->val || p2 == nullptr) {
cur->next = p1;
p1 = p1->next;
cur = cur->next;
} else if (p1->val >= p2->val || p1 == nullptr) {
cur->next = p2;
p2 = p2->next;
cur = cur->next;
}
}
if (p2) cur->next = p2;
return npHead->next;
}
ListNode* mergeKLists(vector& lists) {
if(!lists.size()) return nullptr;
int m = 1;
ListNode* p1=lists[0];
while(m
//思路二:
//先将需要排序在vector进行存储,sort后再重建链表
//时间复杂度O(N*logN) 空间复杂度O(N)
class Solution {
public:
ListNode* mergeKLists(vector& lists) {
vector vi;
for (int i = 0; i < lists.size(); i++)
{
ListNode* phead = lists[i];
while (phead)
{
vi.push_back(phead->val);
phead = phead->next;
}
}
sort(vi.begin(), vi.end(), [](int a, int b) {return a < b; });
ListNode* head = new ListNode(-1);
ListNode* cur = head;
for (int i = 0; i < vi.size(); i++)
{
ListNode* newNode = new ListNode(vi[i]);
cur->next = newNode;
cur = newNode;
}
return head->next;
}
};
判断链表是否有环https://www.nowcoder.com/practice/650474f313294468a4ded3ce0f7898b9?tpId=295&tqId=605&ru=/exam/oj&qru=/ta/format-top101/question-ranking&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3D%25E7%25AE%2597%25E6%25B3%2595%25E7%25AF%2587%26topicId%3D295
//思路:快慢指针
//快指针比慢指针每次多走一步
//如果有环快指针则会追上慢指针,无环则先到nullptr
//时间复杂度O(N) 空间复杂度O(1)
class Solution {
public:
bool hasCycle(ListNode *head) {
ListNode*slow=head,*fast=head;
while(fast && fast->next) //快指针先到尾--这里可以判断head为nullptr和节点只有一个的情况
{
slow=slow->next;
fast=(fast->next)->next;
if(fast==slow)
return true;
}
return false;
}
};
环的入口https://www.nowcoder.com/practice/253d2c59ec3e4bc68da16833f79a38e4?tpId=295&tqId=23449&ru=/exam/oj&qru=/ta/format-top101/question-ranking&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3D%25E7%25AE%2597%25E6%25B3%2595%25E7%25AF%2587%26topicId%3D295
//思路一:同上采用快慢指针
//只要有环,必定相交两次,即第二次为入口
//时间复杂度O(N) 空间复杂度O(1)
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead) {
ListNode*slow=pHead,*fast=pHead;
while(fast && fast->next)
{
slow=slow->next;
fast=(fast->next)->next;
if(slow == fast) break;
}
if(fast == nullptr || fast->next == nullptr) return nullptr;
fast = pHead;
while(fast != slow)
{
fast=fast->next;
slow=slow->next;
}
return fast;
}
};
//思路:哈希表
//相同的结点会在哈希表出现两次,判断第一个出现两次的即可
//时间复杂度 O(N) 空间复杂度 O(N)
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead) {
unordered_map um_count;
while (pHead)
{
++um_count[pHead];
if (um_count[pHead] == 2)
return pHead;
pHead = pHead->next;
}
return nullptr;
}
};
删除倒数第n个节点https://www.nowcoder.com/practice/f95dcdafbde44b22a6d741baf71653f6?tpId=295&tqId=727&ru=/exam/oj&qru=/ta/format-top101/question-ranking&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3D%25E7%25AE%2597%25E6%25B3%2595%25E7%25AF%2587%26topicId%3D295
//思路:双指针
//先找到需要删除节点的前一个,再链接下一个的下一个
//时间复杂度 O(N) 空间复杂度 O(1)
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* phead = new ListNode(-1);
phead->next = head;
ListNode* slow = phead, * fast = head; //让slow指向要删除的前一个
while (--n && fast->next) fast = fast->next;
while (fast->next)
{
slow = slow->next;
fast = fast->next;
}
slow->next = (slow->next)->next;
return phead->next;
}
};
链表相交https://www.nowcoder.com/practice/6ab1d9a29e88450685099d45c9e31e46?tpId=295&tqId=23257&ru=/exam/oj&qru=/ta/format-top101/question-ranking&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3D%25E7%25AE%2597%25E6%25B3%2595%25E7%25AF%2587%26topicId%3D295
//思路:双指针
//两个指针所走路径同,速度同,所以必定相交
//时间复杂度O(n+m) 空间复杂度O(1)
class Solution {
public:
ListNode* FindFirstCommonNode(ListNode* pHead1, ListNode* pHead2) {
ListNode* p1 = pHead1, * p2 = pHead2;
while (p1 != p2)
{
p1 = (p1 == nullptr) ? pHead2 : p1->next; //走完第一条链,走第二条
p2 = (p2 == nullptr) ? pHead1 : p2->next; //走完第二条链,走第一条
}
return p1;
}
};
链表相加https://www.nowcoder.com/practice/c56f6c70fb3f4849bc56e33ff2a50b6b?tpId=295&tqId=1008772&ru=/exam/oj&qru=/ta/format-top101/question-ranking&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3D%25E7%25AE%2597%25E6%25B3%2595%25E7%25AF%2587%26topicId%3D295
思路:反转相加
复用前面反转链表代码
时间复杂度O(N) 空间复杂度O(1)
class Solution {
public:
ListNode* Reverse(ListNode* head)
{
ListNode* phead = nullptr;
ListNode* cur = head;
while (cur)
{
ListNode* next = cur->next;
cur->next = phead;
phead = cur;
cur = next;
}
return phead;
}
ListNode* addInList(ListNode* head1, ListNode* head2) {
head1 = Reverse(head1);
head2 = Reverse(head2);
ListNode* phead = new ListNode(-1);
int scale = 0;
while (head1 || head2 || scale)
{
int val = scale;
if (head1)
{
val += head1->val;
head1 = head1->next;
}
if (head2)
{
val += head2->val;
head2 = head2->next;
}
scale = val / 10;
ListNode* cur = new ListNode(val % 10);
ListNode* next = phead->next;
phead->next = cur;
cur->next = next;
}
return phead->next;
}
};
链表排序(升序)https://www.nowcoder.com/practice/f23604257af94d939848729b1a5cda08?tpId=295&tqId=1008897&ru=/exam/oj&qru=/ta/format-top101/question-ranking&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3D%25E7%25AE%2597%25E6%25B3%2595%25E7%25AF%2587%26topicId%3D295
//思路:参考希尔排序
//时间复杂度O(N*logN) 空间复杂度O(logN)因为递归最坏为树形结构,即为logN
class Solution {
public:
ListNode* sortDouble(ListNode* head1, ListNode* head2)
{
if (head1 == nullptr)
return head2;
if (head2 == nullptr)
return head1;
ListNode* phead = new ListNode(-1);
ListNode* cur = phead;
while (head1 && head2)
{
if (head1->val < head2->val)
{
cur->next = head1;
head1 = head1->next;
}
else
{
cur->next = head2;
head2 = head2->next;
}
cur = cur->next;
}
if (head1)
cur->next = head1;
if (head2)
cur->next = head2;
return phead->next;
}
ListNode* sortInList(ListNode* head) {
//走到只剩一个元素或为nullptr时,必定有序
if (head == nullptr || head->next == nullptr)
return head;
ListNode* slow = head;
ListNode* mid = head->next;
ListNode* fast = head->next->next;
while (fast && fast->next)
{
slow = slow->next;
mid = mid->next;
fast = fast->next->next; //right走两步,先到终点
}
slow->next = nullptr; //中间断开
//右边指针到达末尾时,中间指针指向链表中间
return sortDouble(sortInList(head), sortInList(mid));
//再以头为head1和中间断开结点为head2继续分治
}
};
链表回文https://www.nowcoder.com/practice/3fed228444e740c8be66232ce8b87c2f?tpId=295&tqId=1008769&ru=/exam/oj&qru=/ta/format-top101/question-ranking&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3D%25E7%25AE%2597%25E6%25B3%2595%25E7%25AF%2587%26topicId%3D295
//思路:快慢指针,逆序比较
//时间复杂度O(N) 空间复杂度O(1)
class Solution {
public:
/**
*
* @param head ListNode类 the head
* @return bool布尔型
*/
ListNode* Reverse(ListNode* head) {
ListNode* phead = nullptr;
ListNode* cur = head;
while (cur) {
ListNode* next = cur->next;
cur->next = phead;
phead = cur;
cur = next;
}
return phead;
}
bool isPail(ListNode* head) {
ListNode* mid = new ListNode(-1);
ListNode* fast = head;
ListNode* slow = head;
mid->next = slow;
while (fast && fast->next) {
mid = mid->next;
slow = slow->next;
fast = fast->next->next;
}
mid->next = nullptr;
head=Reverse(head);
if(head->val != slow->val) //节点个数为单数情况,则往后退一个再比较
slow=slow->next;
while (head && slow) {
if(head->val != slow->val)
return false;
head = head->next;
slow = slow->next;
}
return true;
}
};
链表的奇偶重排https://www.nowcoder.com/practice/02bf49ea45cd486daa031614f9bd6fc3?tpId=295&tqId=1073463&ru=/exam/oj&qru=/ta/format-top101/question-ranking&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3D%25E7%25AE%2597%25E6%25B3%2595%25E7%25AF%2587%26topicId%3D295
//思路:借助辅助数组
//时间复杂度O(N) 空间复杂度O(1)
class Solution {
public:
ListNode* oddEvenList(ListNode* head) {
vector vL;
while (head)
{
vL.push_back(head->val);
head = head->next;
}
ListNode* phead = new ListNode(-1);
ListNode* cur = phead;
for (int i = 0; i < vL.size(); i += 2)
{
cur->next = new ListNode(vL[i]);
cur = cur->next;
}
for (int i = 1; i < vL.size(); i += 2)
{
cur->next = new ListNode(vL[i]);
cur = cur->next;
}
return phead->next;
}
};
//存储方式2:
class Solution {
public:
ListNode* oddEvenList(ListNode* head) {
vector vL;
while (head)
{
vL.push_back(head);
head = head->next;
}
ListNode* phead = new ListNode(-1);
ListNode* cur = phead;
for (int i = 0; i < vL.size(); i += 2)
{
cur->next = vL[i];
cur = cur->next;
}
for (int i = 1; i < vL.size(); i += 2)
{
cur->next = vL[i];
cur = cur->next;
}
cur->next=nullptr; //这一步很重要!!!存储节点会把节点后面的所有节点都记录
return phead->next;
}
};
删除链表重复数https://www.nowcoder.com/practice/c087914fae584da886a0091e877f2c79?tpId=295&tqId=664&ru=/exam/oj&qru=/ta/format-top101/question-ranking&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3D%25E7%25AE%2597%25E6%25B3%2595%25E7%25AF%2587%26topicId%3D295
//思路:双指针
//时间复杂度O(N) 空间复杂度O(1)
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if (head == nullptr)
return nullptr;
ListNode* phead = new ListNode(-1);
phead->next = head;
ListNode* slow = phead;
ListNode* fast = head;
while (fast)
{
if (slow->val == fast->val)
{
fast = fast->next;
continue;
}
else
{
slow->next = fast;
slow = fast;
fast = fast->next;
}
}
slow->next=nullptr;
return phead->next;
}
};
删除链表相同项https://www.nowcoder.com/practice/71cef9f8b5564579bf7ed93fbe0b2024?tpId=295&tqId=663&ru=/exam/oj&qru=/ta/format-top101/question-ranking&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3D%25E7%25AE%2597%25E6%25B3%2595%25E7%25AF%2587%26topicId%3D295
//时间复杂度O(N) 空间复杂度O(1)
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if (head == nullptr)
return nullptr;
ListNode*phead=new ListNode(-1);
phead->next=head;
ListNode*cur=phead;
while(cur->next && cur->next->next)
{
if(cur->next->val == cur->next->next->val)
{
int tmp = cur->next->val;
while(cur->next && cur->next->val == tmp)
cur->next = cur->next->next;
}
else {
cur=cur->next;
}
}
return phead->next;
}
};