持续更新中!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
以下代码中只是应付面试时手撕代码时:输入需要自己创造输入,链表结构体也需要自己创造
leetcode中只需要class Solution部分:
部分来源:代码随想录 ,LeetCode 热题 100 - 学习计划 - 力扣(LeetCode)全球极客挚爱的技术成长平台
链表理论:
链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域,一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。
链表的入口节点称为链表的头结点也就是head。
分为单链表,双链表,循环链表:
双链表:
双链表:每一个节点有两个指针域,一个指向下一个节点,一个指向上一个节点。
既可以向前查询也可以向后查询。
循环链表:
循环链表:就是链表首尾相连。
链表是通过指针域的指针链接在内存中各个节点。
所以链表中的节点在内存中不是连续分布的 ,而是散乱分布在内存中的某地址上,分配机制取决于操作系统的内存管理。
移除链表元素:
以下只是应付面试时手撕代码时:输入需要自己创造输入,链表结构体也需要自己创造
leetcode中只需要class Solution部分:
#include<iostream>
struct ListNode
{
int val;
ListNode* next;
ListNode():val(0),next(nullptr){};
ListNode(int val):val(val),next(nullptr){};
ListNode(int val, ListNode* next):val(val), next(next){};
};
class Solution
{
public:
ListNode* removeElements(ListNode*head,int val){
if(head==nullptr) return head;
ListNode* dummy_node = new ListNode(0);
dummy_node->next = head;
ListNode* cur_node = dummy_node;
while(cur_node->next!=nullptr)
{
if(cur_node->next->val == val)
{
ListNode* tmp = cur_node->next;
cur_node->next = cur_node->next->next;
delete tmp;
}else{
cur_node = cur_node->next;
}
}
head = dummy_node->next;
delete dummy_node;
return head;
}
};
int main()
{
ListNode* head = new ListNode(1);
head->next = new ListNode(2);
head->next->next = new ListNode(6);
head->next->next->next = new ListNode(3);
head->next->next->next->next = new ListNode(4);
head->next->next->next->next->next = new ListNode(5);
head->next->next->next->next->next->next = new ListNode(6);
Solution s;
// ListNode* ListNode;
ListNode* cur_head = s.removeElements(head,6);
while(cur_head!=nullptr)
{
std::cout<<cur_head->val;
cur_head = cur_head->next;
}
return 0;
}
反转链表:
#include<iostream>
struct ListNode
{
int val;
ListNode* next;
ListNode():val(0),next(nullptr){};
ListNode(int val):val(val),next(nullptr){};
ListNode(int val, ListNode* next):val(val), next(next){};
};
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* prev = nullptr;
ListNode* cur_node = head;
ListNode* temp;
while(cur_node != nullptr)
{
temp = cur_node->next;
cur_node->next = prev;
//更新pre和cur
prev = cur_node;
cur_node = temp;
}
return prev;
}
};
int main()
{
ListNode* head = new ListNode(1);
head->next = new ListNode(2);
head->next->next = new ListNode(6);
head->next->next->next = new ListNode(3);
head->next->next->next->next = new ListNode(4);
head->next->next->next->next->next = new ListNode(5);
head->next->next->next->next->next->next = new ListNode(6);
Solution s;
// ListNode* ListNode;
ListNode* cur_head = s.reverseList(head);
while(cur_head!=nullptr)
{
std::cout<<cur_head->val;
cur_head = cur_head->next;
}
return 0;
}
两两交换链表:
#include<iostream>
struct ListNode
{
int val;
ListNode* next;
ListNode():val(0),next(nullptr){};
ListNode(int val):val(val),next(nullptr){};
ListNode(int val, ListNode* next):val(val), next(next){};
};
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* dummynode = new ListNode(0);
dummynode->next = head;
ListNode* cur = dummynode;
while(cur->next != nullptr && cur->next->next!=nullptr) { //顺序不能返
ListNode* temp1 = cur->next;
ListNode* temp2 = cur->next->next->next;
cur->next = cur->next->next;
cur->next->next = temp1;
cur->next->next->next = temp2;
cur = cur->next->next; //移动两位下一轮
}
ListNode* result = dummynode->next;
delete dummynode;
return result;
}
};
int main()
{
ListNode* head = new ListNode(1);
head->next = new ListNode(2);
head->next->next = new ListNode(6);
head->next->next->next = new ListNode(3);
head->next->next->next->next = new ListNode(4);
head->next->next->next->next->next = new ListNode(5);
head->next->next->next->next->next->next = new ListNode(6);
Solution s;
// ListNode* ListNode;
ListNode* cur_head = s.swapPairs(head);
while(cur_head!=nullptr)
{
std::cout<<cur_head->val;
cur_head = cur_head->next;
}
return 0;
}
删除链表的倒数第N个节点:
#include<iostream>
struct ListNode
{
int val;
ListNode* next;
ListNode():val(0),next(nullptr){};
ListNode(int val):val(val),next(nullptr){};
ListNode(int val, ListNode* next):val(val), next(next){};
};
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummy = new ListNode(0);
dummy->next = head;
ListNode* fast = dummy;
ListNode* slow = dummy;
while(n-- && fast!=nullptr)
{
fast = fast->next;
}
fast = fast->next; //同时移动slow指针和fast时 保持在删除节点的上个位置
while(fast!=nullptr)
{
fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next;
return dummy->next;
}
};
int main()
{
ListNode* head = new ListNode(1);
head->next = new ListNode(2);
head->next->next = new ListNode(6);
head->next->next->next = new ListNode(3);
head->next->next->next->next = new ListNode(4);
head->next->next->next->next->next = new ListNode(5);
head->next->next->next->next->next->next = new ListNode(6);
Solution s;
// ListNode* ListNode;
ListNode* cur_head = s.removeNthFromEnd(head,1);
while(cur_head!=nullptr)
{
std::cout<<cur_head->val;
cur_head = cur_head->next;
}
return 0;
}
相交链表:
- 通过双指针遍历,分别走完两条链表的总长度,使得指针在相交点处相遇。
- 如果没有相交,最终
p
和q
会同时到nullptr
,返回nullptr
。 - 时间复杂度 O(m + n),空间复杂度 O(1),是寻找相交节点的最优解法之一。
#include<iostream>
struct ListNode
{
int val;
ListNode* next;
ListNode():val(0),next(nullptr){};
ListNode(int val):val(val),next(nullptr){};
ListNode(int val, ListNode* next):val(val), next(next){};
};
//移动的距离相等时
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* p = headA;
ListNode* q = headB;
// 若A,B无交点,返回nullptr
//有交点返回 他们走的距离
while(p!=q)
{
p = p ? p->next : headB;
q = q? q->next : headA;
}
return p;
}
};
int main()
{
ListNode* head = new ListNode(1);
head->next = new ListNode(2);
head->next->next = new ListNode(6);
head->next->next->next = new ListNode(3);
head->next->next->next->next = new ListNode(4);
head->next->next->next->next->next = new ListNode(5);
head->next->next->next->next->next->next = new ListNode(6);
//错误 这里 head 和 headB 各自独立,它们的 ListNode 互不影响,没有真正共享的节点
//
// ListNode* headB = new ListNode(2);
// headB->next = new ListNode(6);
// headB->next->next = new ListNode(3);
// headB->next->next->next = new ListNode(4);
// headB->next->next->next->next = new ListNode(5);
// headB->next->next->next->next->next = new ListNode(6);
//赋值情形一
ListNode* headB = new ListNode(3);
headB->next = new ListNode(6);
//以下才开始相交
headB->next->next = head->next->next->next;
headB->next->next->next = head->next->next->next->next;
headB->next->next->next->next = head->next->next->next->next->next;
headB->next->next->next->next->next = head->next->next->next->next->next->next;
//直接赋值相交点--赋值情形二
// ListNode* headB = head->next;
Solution s;
// ListNode* ListNode;
ListNode* cur_head = s.getIntersectionNode(head,headB);
while(cur_head!=nullptr)
{
std::cout<<cur_head->val<<" ";
cur_head = cur_head->next;
}
return 0;
}
环形链表:
利用双指针:快指针与慢指针
while(fast != NULL && fast->next != NULL)
:这部分检查快指针和慢指针是否会碰撞,如果快指针或者快指针的下一个指针为NULL
,则说明链表无环,直接返回NULL
。ListNode* meet = head; while(meet != slow)
:找到环的入口节点。slow
和meet
从链表头部同时出发,每次向前走一步,直到它们相遇,即为环的入口节点。
#include<iostream>
struct ListNode
{
int val;
ListNode* next;
ListNode():val(0),next(nullptr){};
ListNode(int val):val(val),next(nullptr){};
ListNode(int val, ListNode* next):val(val), next(next){};
};
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode* fast = head;
ListNode* slow = head;
while(fast!=NULL && fast->next!=NULL)
{
slow = slow->next;
fast = fast->next->next;
if(slow==fast)
{
//找到入口点
ListNode* meet = head;
while(meet!=slow)
{
meet = meet->next;
slow = slow->next;
}
return meet;
}
}
return NULL;
}
};
int main()
{
ListNode* head = new ListNode(1);
head->next = new ListNode(2);
head->next->next = new ListNode(6);
head->next->next->next = new ListNode(3);
head->next->next->next->next = new ListNode(4);
head->next->next->next->next->next = new ListNode(5);
head->next->next->next->next->next->next = head->next->next;
// ListNode* headB = new ListNode(2);
// headB->next = new ListNode(6);
// headB->next->next = new ListNode(3);
// headB->next->next->next = new ListNode(4);
// headB->next->next->next->next = new ListNode(5);
// headB->next->next->next->next->next = new ListNode(6);
Solution s;
// ListNode* ListNode;
ListNode* cur_head = s.detectCycle(head);
// while(cur_head!=nullptr)
// {
// std::cout<<cur_head->val;
// cur_head = cur_head->next;
// }
if(cur_head!=NULL)
{
std::cout<<cur_head->val;
}
return 0;
}
回文链表:
#include<iostream>
struct ListNode
{
int val;
ListNode* next;
ListNode():val(0),next(nullptr){};
ListNode(int val):val(val),next(nullptr){};
ListNode(int val, ListNode* next):val(val), next(next){};
};
//时间复杂度O(n)和空间复杂度O(1)
class Solution {
public:
bool isPalindrome(ListNode* head) {
ListNode* slow = head;
ListNode* fast = head->next;
while(fast!=NULL && fast->next!=NULL)
{
fast = fast->next->next;
slow = slow->next;
}
//当队列为偶数时此时slow已经在链表的分割点中间位置
//奇数时 slow在中间位置 判断左右两边的链表是否相等
ListNode* second_head = slow->next; //第二个列表的头节点
slow->next = nullptr; //断开断开的左半部分
ListNode* pre = nullptr;
while(second_head!=NULL)
{
ListNode* temp = second_head->next;
second_head->next = pre;
pre = second_head;
second_head = temp;
}
slow = head;
//此时pre是second链表中的头节点
while(pre) //只要pre不为空
{
if(pre->val ==slow->val )
{
slow = slow->next;
pre = pre->next;
}
else{
return false; // 不是回文
}
}
return true; // 回文
}
// //封装reverslist
// ListNode* reversList(ListNode* head)
// {
// ListNode* pre = nullptr;
// ListNode* cur = head;
// while(cur!=nullptr)
// {
// ListNode* temp = cur->next;
// cur->next = pre;
// pre = cur;
// cur = temp;
// }
// return pre;
// }
};
int main()
{
ListNode* head = new ListNode(1);
head->next = new ListNode(2);
head->next->next = new ListNode(6);
head->next->next->next = new ListNode(3);
head->next->next->next->next = new ListNode(6);
head->next->next->next->next->next = new ListNode(2);
head->next->next->next->next->next->next = new ListNode(1);
// ListNode* headB = new ListNode(2);
// headB->next = new ListNode(6);
// headB->next->next = new ListNode(3);
// headB->next->next->next = new ListNode(4);
// headB->next->next->next->next = new ListNode(5);
// headB->next->next->next->next->next = new ListNode(6);
Solution s;
// ListNode* ListNode;
// ListNode* cur_head = s.detectCycle(head)
// while(cur_head!=nullptr)
// {
// std::cout<<cur_head->val;
// cur_head = cur_head->next;
// }
bool flag = s.isPalindrome(head);
std::cout<<flag<<std::endl;
return 0;
}
合并两个有序链表:
思想:pre的思想 删除链表的节点类似
#include<iostream>
struct ListNode
{
int val;
ListNode* next;
ListNode():val(0),next(nullptr){};
ListNode(int val):val(val),next(nullptr){};
ListNode(int val, ListNode* next):val(val), next(next){};
};
class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
if(list1==NULL || list2==NULL)
{
if(list1 == NULL) return list2;
if(list2 == NULL) return list1;
}
ListNode* head = (list1->val <= list2->val) ? list1 : list2;
ListNode* pre = head;
ListNode* cur1 = pre->next;
ListNode* cur2 = (pre==list1) ? list2 :list1; //如果当前的pre和当前的head相同 cur2指向下一个节点
while(cur1!=NULL && cur2!=NULL)
{
if(cur1->val <= cur2->val)
{
pre->next = cur1;
cur1 = cur1->next;
}
else
{
pre->next = cur2;
cur2 = cur2->next;
}
pre = pre->next;
}
pre->next = cur1==NULL? cur2 : cur1;
return head;
// if(list1->val <= list2->val)
// {
// ListNode*head = list1;
// }
}
};
int main()
{
ListNode* head = new ListNode(1);
head->next = new ListNode(2);
head->next->next = new ListNode(4);
head->next->next->next = new ListNode(6);
head->next->next->next->next = new ListNode(7);
head->next->next->next->next->next = new ListNode(9);
head->next->next->next->next->next->next = new ListNode(9);
ListNode* headB = new ListNode(2);
headB->next = new ListNode(3);
headB->next->next = new ListNode(5);
headB->next->next->next = new ListNode(6);
headB->next->next->next->next = new ListNode(7);
headB->next->next->next->next->next = new ListNode(8);
Solution s;
// ListNode* ListNode;
ListNode* cur_head = s.mergeTwoLists(head,headB);
while(cur_head!=nullptr)
{
std::cout<<cur_head->val;
cur_head = cur_head->next;
}
return 0;
// bool flag = s.isPalindrome(head)
// std::cout<<flag<<std::endl;
// return flag;
}
两数相加:
注意:两个列表长度不同的时候,用val1 ,val2模拟0值 进行计算,进位也同样如此
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
int res ;
int carry=0;
ListNode* dummy = new ListNode(); //虚拟头节点至关重要
ListNode* cur = dummy;
while(l1!=NULL || l2!=NULL || carry)
{
int val1 = 0,val2=0;
if(l1)
{
val1 = l1->val;
l1 = l1->next;
}
if(l2)
{
val2 = l2->val;
l2 = l2->next;
}
res = val1 + val2 + carry;
cur->next = new ListNode(res%10); //取余数
carry = res/10; //取除数
cur = cur->next;
}
return dummy->next;
}
};