记录LeetCode算法讲解经典版,涉及相关数据结构和算法的经典题目及相关题目解题思想和代码实现。
目录
一、预备知识
二、例题
例1-a、链表逆序(easy)
- 题目描述:
- 解题思路:
- 代码实现:
/**
* 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 *new_head=NULL;
ListNode *q;
while(head!=NULL){
q = head->next;
head->next=new_head;
new_head = head;
head=q;
}
return new_head;
}
};
例1-b、链表逆序2(medium)
- 题目描述:
- 解题思路:
- 代码实现:
/**
* 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) {
ListNode* result = head;
int number = n-m+1;
ListNode* pre_head = NULL;
//找到pre_head和head:head指向m位置,pre_head指向m前一个
while(head&&--m){
pre_head = head;
head=head->next;
}
//modify_list_tail指向反向链表的尾节点
ListNode* modify_list_tail = head;
//new_head指向反转链表的头节点;
ListNode* new_head = NULL;
while(head&&number){
ListNode* q = head->next;
head->next = new_head;
new_head=head;
head = q;
number--;
}
modify_list_tail->next = head;
if(pre_head){
pre_head->next = new_head;
}else{
/*m=1的情况,没有pre_head*/
result = new_head;
}
return result;
}
};
例2、链表求交点(easy)
- 题目描述:
- 解题思路:
- 代码实现:
方法一:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
#include<set>
using namespace std;
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
set<ListNode *> se;//用于保存headA各个节点地址的set
// 把headA为头节点的链表各个节点放入set
while(headA){
se.insert(headA);
headA = headA->next;
}
// 查找headB的各个头节点是否在set中
while(headB){
if(se.find(headB)!=se.end()){
return headB;
}
headB=headB->next;
}
return 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) {
int lenA = 0;
int lenB = 0;
ListNode* A = headA;
ListNode* B = headB;
while(A){
A = A->next;
lenA++;
}
while(B){
B = B->next;
lenB++;
}
if(lenB>=lenA){
int temp = lenB-lenA;
while(temp){
headB=headB->next;
temp--;
}
}else{
int temp = lenA-lenB;
while(temp){
headA=headA->next;
temp--;
}
}
while(headA&&headB){
if(headA!=headB){
headA=headA->next;
headB=headB->next;
}else{
return headA;
}
}
return NULL;
}
};
例3、链表求环(medium)
- 题目描述:
- 解题思路:
- 代码实现:
方法一:
#include<set>
using namespace std;
/**
- 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) {
set<ListNode *> que;
while(head){
que.insert(head);
head=head->next;
if(que.find(head)!=que.end()){
return head;
}
}
return NULL;
}
};
方法二:
/**
- 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 *slow = head;
ListNode *fast = head;
ListNode *meet = NULL;
while(fast){
fast = fast->next;
slow = slow->next;
if(fast){
fast = fast->next;
}
if(fast==slow){
meet = fast;
break;
}
}
if(fast==NULL){
return NULL;
}
while(head&&meet){
if(head==meet){
return head;
}
head=head->next;
meet=meet->next;
}
return NULL;
}
};
例4、链表划分(medium)
- 题目描述:
- 解题思路:
思路二:利用两个队列,把小于x的入small队列,大于等于x的入big队列,连接两个链表,更新每个节点的值,让其等于small队列和big队列中元素的值,其中small队列先入,big队列后入。 - 代码实现:
方法一:
#include<queue>
using namespace std;
/**
- 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) {
//创建一个小于x的链表头和大于等于x的链表头
ListNode small(0);
ListNode big(0);
ListNode *small_head_move = &small;
ListNode *big_head_move = &big;
ListNode *small_head = &small;
ListNode *big_head = &big;
while(head){
ListNode* q = head->next;
if(head->val<x){
small_head_move->next = head;
small_head_move =head;
}else{
big_head_move->next = head;
big_head_move = head;
}
head = q;
}
// 让big和small最后指向都为空
big_head_move->next = NULL;
big_head = big_head->next;
// 连接small和big
small_head_move->next = big_head;
// 移到头节点的下一个节点
small_head = small_head->next;
return small_head;
}
};
方法二:
#include<queue>
using namespace std;
/**
* 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) {
queue<int> small_que;
queue<int> big_que;
ListNode* start=head;
ListNode* result=head;
while(head){
if(head->val<x){
small_que.push(head->val);
}else{
big_que.push(head->val);
}
head = head->next;
}
while(start){
while(!small_que.empty()){
if(start==NULL){
break;
}
int top = small_que.front();
small_que.pop();
start->val=top;
start = start->next;
}
while(!big_que.empty()){
if(start==NULL){
break;
}
int top = big_que.front();
big_que.pop();
start->val=top;
start = start->next;
}
}
return result;
}
};
例5、复杂链表的复制(hard)
- 题目描述:
- 解题思路:
- 代码实现:
/*
// 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;
}
};
*/
#include<map>
#include<vector>
using namespace std;
class Solution {
public:
Node* copyRandomList(Node* head) {
map<Node*,int> loc_id;
vector<Node*> vec;
Node *start = head;
int i = 0;
while(start){
vec.push_back(new Node(start->val,NULL,NULL));
loc_id[start]=i;
i++;
start = start->next;
}
vec.push_back(0);
Node *result = head;
i = 0;
while(result){
vec[i]->next =vec[i+1];
if(result->random){
int id = loc_id[result->random];
vec[i]->random = vec[id];
}
result=result->next;
i++;
}
return vec[0];
}
};
例6-a、2个排序链表归并(easy)
- 题目描述:
- 解题思路:
- 代码实现:
/**
- 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 start(0);
ListNode *new_head = &start;
ListNode *result = &start;
while(l1&&l2){
if(l1->val<=l2->val){
new_head->next = l1;
new_head=l1;
l1=l1->next;
}else{
new_head->next = l2;
new_head=l2;
l2=l2->next;
}
}
if(l1==NULL){
new_head->next = l2;
}
if(l2==NULL){
new_head->next = l1;
}
return result->next;
}
};
例6-b、k个排序链表归并(hard)
- 题目描述:
- 解题思路:
- 代码实现:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
#include<vector>
#include<algorithm>
bool cmp(const ListNode *a,const ListNode *b){
return a->val < b->val;
}
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
vector<ListNode *> vec;
for( int i = 0;i<lists.size();i++){
while(lists[i]){
vec.push_back(lists[i]);
lists[i]=lists[i]->next;
}
}
if(vec.size()==0){
return NULL;
}
sort(vec.begin(),vec.end(),cmp);
for(int i = 1;i<vec.size();i++){
vec[i-1]->next = vec[i];
}
vec[vec.size()-1]->next=NULL;
return vec[0];
}
};