目录
例一:LeetCode206
//已知链表头节点指针head,将链表逆序,不可申请额外空间
#include <stdio.h>
struct ListNode {
int val;
ListNode* next;
ListNode(int x) :val(x), next(NULL) {}
};
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* new_head = NULL;
while (head) {
ListNode* next = head->next;
head->next = new_head;
new_head = head;
head = next;
}
return new_head;
}
};
int main() {
ListNode a(1);
ListNode b(2);
ListNode c(3);
ListNode d(4);
ListNode e(5);
a.next = &b;
b.next = &c;
c.next = &d;
d.next = &e;
Solution solve;
ListNode* head = &a;
printf("Before reverse:\n");
while (head) {
printf("%d\n", head->val);
head = head->next;
}
head = solve.reverseList(&a);
printf("After reverse:\n");
while (head) {
printf("%d\n", head -> val);
head = head->next;
}
return 0;
}
例二:LeetCode92
//已知链表头节点指针head,将链表从位置m到n逆序,不能申请额外空间
#include <stdio.h>
struct ListNode {
int val;
ListNode* next;
ListNode(int x) :val(x), next(NULL) {};
};
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
int change_len = n - m + 1;//计算需要逆置的节点个数
ListNode* pre_head = NULL;//初始化开始逆置的节点的前驱
ListNode* result = head;//最终转化后的链表的头节点,非特殊情况即为head
while (head && --m) {//head向前移动m-1个位置
pre_head = head;
head = head->next;
}
ListNode* modify_list_tall = head;//将modify_list_tall指向当前的head,即逆置后的链表尾
ListNode* new_head = NULL;
while (head && change_len) {//逆置change_len个节点
ListNode* next = head->next;
head->next = new_head;
new_head = head;
head = next;
change_len--;
}
modify_list_tall->next = head;
if (pre_head) {
pre_head->next = new_head;
}
else {
result = new_head;//如果head不为空,说明不是从第一个节点开始逆置的m>1
}
return result;
}
};
int main() {
ListNode a(1);
ListNode b(2);
ListNode c(3);
ListNode d(4);
ListNode e(5);
a.next = &b;
b.next = &c;
c.next = &d;
d.next = &e;
Solution solve;
ListNode* head = solve.reverseBetween(&a, 2, 4);
while (head) {
printf("%d\n", head->val);
head = head->next;
}
return 0;
}
例三:LeetCode160
//已知链表A的头节点指针headA,链表B的头节点指针headB,两个链表相交,求两链表交点对应的节点。
#include <stdio.h>
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(NULL) {};
};
//时间nlogn 空间O(n)
// class Solution{
// public:
// ListNode* getIntersectionNode(ListNode* headA,ListNode* headB){
// std::set<ListNode*> node_set;
// while(headA){
// node_set.insert(headA);
// headA=headA->next;
// }
// while(headB){
// if(node_set.find(headB!=node_set.end())){
// return headB;
// }
// headB=headB->next;
// }
// return NULL
// }
// };
//
//时间O(n) 空间O(1)
int get_list_length(ListNode* head) {
int len = 0;
while (head) {
len++;
head = head->next;
}
return len;
}
ListNode* forward_long_list(int long_len, int short_len, ListNode* head) {
int delta = long_len - short_len;
while (head && delta) {
head = head->next;
delta--;
}
return head;
}
class Solution {
public:
ListNode* getIntersectionNode(ListNode* headA, ListNode* headB) {
int list_A_len = get_list_length(headA);
int list_B_len = get_list_length(headB);
if (list_A_len > list_B_len) {
headA = forward_long_list(list_A_len, list_B_len, headA);
}
else {
headB = forward_long_list(list_B_len, list_A_len, headB);
}
while (headA && headB) {
if (headA == headB) {
return headA;
}
headA = headA->next;
headB = headB->next;
}
return NULL;
}
};
int main() {
ListNode a1(1);
ListNode a2(2);
ListNode b1(3);
ListNode b2(4);
ListNode b3(5);
ListNode c1(6);
ListNode c2(7);
ListNode c3(8);
a1.next = &a2;
a2.next = &c1;
c1.next = &c2;
c2.next = &c3;
b1.next = &b2;
b2.next = &b3;
b3.next = &c1;
Solution solve;
ListNode* result = solve.getIntersectionNode(&a1, &b1);
printf("%d\n", result->val);
return 0;
}
例四:LeetCode141
//已知链表中可能存在环,若有环返回环起始节点,否则返回NULL
#include <stdio.h>
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(NULL) {}
};
// class Solution{
// public:
// ListNode* detectCycle (ListNode* head){
// std::set<ListNode*> node_set;
// while(head){
// if(node_set.find(head) != node_set.end()){
// return head;
// }
// node_set.insert(head);
// head = head->next;
// }
// return NULL;
// }
// };
//
class Solution {
public:
ListNode* detectCycle(ListNode* head) {
ListNode* fast = head;
ListNode* slow = head;
ListNode* meet = NULL;//相遇节点
while (fast) {
slow = slow->next;
fast = fast->next;
if (!fast) {
return NULL;
}
fast = fast->next;
if (fast == slow) {
meet = fast;
break;
}
}
if (meet == NULL) {
return NULL;
}
while (head && meet) {
if (meet == head) {
return head;
}
head = head->next;
meet = meet->next;
}
return NULL;
}
};
int main() {
ListNode a(1);
ListNode b(2);
ListNode c(3);
ListNode d(4);
ListNode e(5);
ListNode f(6);
ListNode g(7);
a.next = &b;
b.next = &c;
c.next = &d;
d.next = &e;
e.next = &f;
f.next = &g;
g.next = &c;
Solution solve;
ListNode* node = solve.detectCycle(&a);
if (node) {
printf("%d\n", node->val);
}
else {
printf("NULL\n");
}
return 0;
}
例五:LeetCode86
//已知链表的头指针head和数值X,将所有小于X的节点放在大于或等于X的节点前,且保持这些节点原来的相对位置。
#include <stdio.h>
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
ListNode* partition(ListNode* head, int x) {
ListNode less_head(0);
ListNode more_head(0);
ListNode* less_ptr = &less_head;
ListNode* more_ptr = &more_head;
while (head) {
if (head->val < x) {
less_ptr->next = head;
less_ptr = head;
}
else {
more_ptr->next = head;
more_ptr = head;
}
head = head->next;
}
less_ptr->next = more_head.next;
more_ptr->next = NULL;
return less_head.next;
}
};
int main() {
ListNode a(1);
ListNode b(4);
ListNode c(3);
ListNode d(2);
ListNode e(5);
ListNode f(2);
a.next = &b;
b.next = &c;
c.next = &d;
d.next = &e;
e.next = &f;
Solution solve;
ListNode* head = solve.partition(&a, 3);
while (head) {
printf("%d\n", head->val);
head = head->next;
}
return 0;
}
例六:LeetCode138
//已知一个复杂的链表,节点中有一个指向本链表任意某个节点的随机指针(也可以为空),求这个链表的深度拷贝。
//深度拷贝:
#include <stdio.h>
#include <map>
#include <vector>
struct Node {
int val;
Node* next, * random;
Node(int _x, Node *_next, Node *_random) : val(_x), next(_next), random(_random) {}
};
//map<key,val> name; 通过节点的地址,得知是第几个节点
//int main() {
// std::map<RandomListNode*, int> node_map;
// RandomListNode a(5);
// RandomListNode b(3);
// RandomListNode c(6);
//
// a.next = &b;
// b.next = &c;
// a.random = &c;
// b.random = &a;
// c.random = &c;
// node_map[&a] = 1;
// node_map[&b] = 2;
// node_map[&c] = 3;
// printf("a.random id = %d\n", node_map[a.random]);
// printf("b.random id = %d\n", node_map[b.random]);
// printf("c.random id = %d\n", node_map[c.random]);
// return 0;
//}
class Solution {
public:
Node* copyRandomList(Node* head) {
std::map<Node*, int> node_map;//利用map根据地址得到是第几个节点
std::vector<Node*> node_vec;//使用vector存储新链表的节点
Node* ptr = head;
int i = 0;
while (ptr) {
node_vec.push_back(new Node(ptr->val, NULL, NULL));
node_map[ptr] = i;
ptr = ptr->next;
i++;
}
node_vec.push_back(0);//为了让51行的操作到最后一个节点时任然一致
ptr = head;
i = 0;
while (ptr) {
node_vec[i]->next = node_vec[i + 1];
if (ptr->random) {
int id = node_map[ptr->random];
node_vec[i]->random = node_vec[id];
}
ptr = ptr->next;
i++;
}
return node_vec[0];
}
};
int main() {
Node a(1, NULL, NULL);
Node b(2, NULL, NULL);
Node c(3, NULL, NULL);
Node d(4, NULL, NULL);
Node e(5, NULL, NULL);
a.next = &b;
b.next = &c;
c.next = &d;
d.next = &e;
a.random = &c;
b.random = &d;
c.random = &c;
e.random = &d;
Solution solve;
Node* head = solve.copyRandomList(&a);
while (head) {
printf("label = %d ", head->val);
if (head->random) {
printf("rand = %d\n", head->random->val);
}
else {
printf("rand = NULL\n");
}
head = head->next;
}
return 0;
}
例七:LeetCode21
//已知两个已排序链表的头节点指针l1和l2,将这两个链表合并,合并后任然为有序的,并返回头节点。
#include <stdio.h>
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
ListNode* mergeTwoLists(ListNode* L1, ListNode* L2) {
ListNode temp_head(0);
ListNode* ptr = &temp_head;
while (L1 && L2) {
if (L1->val < L2->val) {
ptr->next = L1;
L1 = L1->next;
}
else {
ptr->next = L2;
L2 = L2->next;
}
ptr = ptr->next;
}
if (L1) {
ptr->next = L1;
}
if (L2) {
ptr->next = L2;
}
return temp_head.next;
}
};
int main() {
ListNode a(1);
ListNode b(4);
ListNode c(6);
ListNode d(0);
ListNode e(5);
ListNode f(7);
a.next = &b;
b.next = &c;
d.next = &e;
e.next = &f;
Solution solve;
ListNode* head = solve.mergeTwoLists(&a, &d);
while (head) {
printf("%d\n", head->val);
head = head->next;
}
return 0;
}
例八:LeetCode23
//已知k个已排序链表的头节点指针,将这k个链表合并,合并后仍然为有序,返回合并后的头节点。
#include <stdio.h>
#include <vector>
#include <algorithm>
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(NULL) {}
};
bool cmp(const ListNode* a, const ListNode* b) {
return a->val < b->val;
}
// int main() {
// ListNode a(3);
// ListNode b(2);
// ListNode c(5);
// ListNode d(0);
// std::vector<ListNode*> node_vec;
// node_vec.push_back(&a);
// node_vec.push_back(&b);
// node_vec.push_back(&c);
// node_vec.push_back(&d);
// std::sort(node_vec.begin(), node_vec.end(), cmp);
// for (int i = 0; i < node_vec.size(); i++) {
// printf("%d\n", node_vec[i]->val);
// }
// return 0;
// }
class Solution {
public:
// ListNode* mergeKLists(std::vector<ListNode*>& lists) {//把所有的节点都存储到vector中,排序后,在连接成链表。
// std::vector<ListNode*> node_vec;
// for(int i = 0; i < lists.size(); i++){
// ListNode *head = lists[i];
// while(head){
// node_vec.push_back(head);
// head = head->next;
// }
// }
// if(node_vec.size() == 0){
// return NULL;
// }
// std::sort(node_vec.begin(), node_vec.end(), cmp);
// for(int i = 1; i < node_vec.size(); i++){
// node_vec[i-1]->next = node_vec[i];
// }
// node_vec[node_vec.size()-1]->next = NULL;
// return node_vec[0];
// }
ListNode* mergeTwoLists(ListNode* L1, ListNode* L2) {
ListNode temp_head(0);
ListNode* ptr = &temp_head;
while (L1 && L2) {
if (L1->val < L2->val) {
ptr->next = L1;
L1 = L1->next;
}
else {
ptr->next = L2;
L2 = L2->next;
}
ptr = ptr->next;
}
if (L1) {
ptr->next = L1;
}
if (L2) {
ptr->next = L2;
}
return temp_head.next;
}
//分治法
ListNode* mergeKLists(std::vector<ListNode*>& lists) {//要加& ,调用时,直接将参数的地址传递给mergeKLists
if (lists.size() == 0) {
return NULL;
}
if (lists.size() == 1) {
return lists[0];
}
if (lists.size() == 2) {
return mergeTwoLists(lists[0], lists[1]);
}
int mid = lists.size() / 2;
std::vector<ListNode*> sub1_lists;
std::vector<ListNode*> sub2_lists;
for (int i = 0; i < mid; i++) {
sub1_lists.push_back(lists[i]);
}
for (int i = mid; i < lists.size(); i++) {
sub2_lists.push_back(lists[i]);
}
ListNode* l1 = mergeKLists(sub1_lists);
ListNode* l2 = mergeKLists(sub2_lists);
return mergeTwoLists(l1, l2);
}
};
int main() {
ListNode a(1);
ListNode b(4);
ListNode c(6);
ListNode d(0);
ListNode e(5);
ListNode f(7);
ListNode g(2);
ListNode h(3);
a.next = &b;
b.next = &c;
d.next = &e;
e.next = &f;
g.next = &h;
Solution solve;
std::vector<ListNode*> lists;
lists.push_back(&a);
lists.push_back(&d);
lists.push_back(&g);
ListNode* head = solve.mergeKLists(lists);
while (head) {
printf("%d\n", head->val);
head = head->next;
}
return 0;
}