文章目录
b_leetcode1——链表逆序a
题目:已知链表头节点指针head,将链表逆序。(不可申请额外空间)
ReverseLinkedList.h
#pragma once
#include<stdio.h>
//下面这个就叫做结构体的声明
struct ListNode
{
int val; //数据域
ListNode* next;
//下面这个是构造函数
ListNode(int a) : val(a), next(NULL) {}
};
ListNode* ReverseList(ListNode* h
ReverseLinkedList.cpp
#include "ReverseLinkedList.h"
ListNode* ReverseList(ListNode* head) {
ListNode* new_head = NULL;
while (head) {
ListNode *temp_node = head->next;
head->next = new_head;
new_head = head;
head = temp_node;
}
return new_head;
}
ReverseLinkedList_test.cpp
#define _CRT_SECURE_NO_WARNINGS
#include "ReverseLinkedList.h"
#include <iostream>
using namespace std;
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;
ListNode *head = &a;
while (head) {
cout << head->val << endl;
head = head->next;
}
cout << "after reverse" << endl;
head = ReverseList(&a);
while (head) {
cout << head->val << endl;
head = head->next;
}
system("pause");
return 0;
}
b_leetcode1——链表逆序b
题目:已知链表头节点指针head,将链表从位置m到n逆序(不申请额外空间)
reverse_Between.h
#pragma once
#include <stdio.h>
struct ListNode {
int val;
ListNode *next;
ListNode(int x) :val(x), next(NULL) {}
};
ListNode *reverseBetween(ListNode *head,int m,int n);
reverse_Between.cpp
#include "reverse_Between.h"
ListNode *reverseBetween(ListNode *head, int m, int n) {
int change_len = n - m + 1;
ListNode* result = head;
ListNode* pre_head = NULL;
ListNode* new_head = NULL;
while (head && --m)
{
pre_head = head;
head = head->next;
}
ListNode* tail_node = head;
while (head && change_len) {
ListNode* temp = head->next;
head->next = new_head;
new_head = head;
head = temp;
change_len--;
}
tail_node->next = head;
if (pre_head) {
pre_head->next = new_head;
}
else {
result = new_head;
}
return result;
}
reverse_Between_test.cpp
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include "reverse_Between.h"
using namespace std;
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;
ListNode * head = reverseBetween(&a, 2, 4);
while (head) {
cout << head->val << endl;
head = head->next;
}
system("pause");
return 0;
}
b_leetcode2——求两个链表的交点
题目:已知链表A的头节点指针headA,链表B的头节点指针headB,两个链表相交,求两链表交点对应的节点
- 如果两个链表没有交点,则返回NULL;
- 在求交点的过程中,不可以破坏链表的结构或者修改链表的数据域
- 可以确保传入的链表A与链表B没有任何环
- 实现算法尽可能使时间复杂度O(n),空间复杂度O(1)
思路1:
- 1、遍历链表A,将A中节点对应的指针(地址),插入set
- 2、遍历链表B,将B中节点对应的指针(地址),在set中查找,发现在set中的第一个节点地址,就是两个链表的交点。
思路2:
-
1、计算headA和headB的链表长度,然后计算较长的链表多出来的长度
-
2、将较长链表的指针移动到和较短链表指针对齐的位置
-
3、headA和jheadB同时移动,当两个指针指向同一个节点时,即找到了
下面时具体的代码
getintersectionnode.h
#pragma once
#include <set>
#include <stdio.h>
struct ListNode
{
int val;
ListNode* next;
ListNode(int x) : val(x), next(NULL) {}
};
int get_list_length(ListNode *head);
ListNode* forward_long(ListNode *head,int len);
ListNode* getintersectionnode1(ListNode *heada,ListNode* headb);
ListNode* getintersectionnode2(ListNode *heada, ListNode* headb);
思路一的解答方法
getintersectionnode1.cpp
#include "getintersectionnode.h"
ListNode *getintersectionnode1(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;
}
思路二的方法:
getintersectionnode2.cpp
#include "getintersectionnode.h"
#include <iostream>
int get_list_length(ListNode *head) {
int len = 0;
while (head) {
len++;
head = head->next;
}
return len;
}
ListNode* forward_long(ListNode *head, int len) {
while (head&&len) {
head = head->next;
len--;
}
return head;
}
ListNode* getintersectionnode2(ListNode *heada, ListNode* headb) {
int lena = get_list_length(heada);
int lenb = get_list_length(headb);
int change_len = 0;
if (lena > lenb) {
change_len = lena - lenb;
heada = forward_long(heada, change_len);
}
else
{
change_len = lenb - lena;
headb = forward_long(headb, change_len);
}
while (heada&&headb) {
if (heada == headb) {
return heada;
}
heada = heada->next;
headb = headb->next;
}
return NULL;
}
getintersectionnode_test.cpp
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include "getintersectionnode.h"
using namespace std;
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;
ListNode *result = getintersectionnode2(&a1, &b1);
cout << result->val << endl;
system("pause");
return 0;
}
b_leetcode3——链表求环
题目:已知链表中可能存在环,若有环返回环起始节点,否则返回NULL。
思路一:
- 1、遍历链表,将链表中节点对应的指针(地址),插入set
- 2、但是在插入之前,需要判断set中有没有这个指针(地址),第一个在set中发现的节点地址,即是链表环的起点。
思路二:
- 采用的是快慢指针赛跑的思路,首先快、慢指针位于同一起跑线上,快指针的速度是慢指针的两倍。(这里需要注意的是编程时候的细节:快指针和慢指针同时走一步,如果快指针不为空,就继续再走一步,如果为空,就不能走了。)这里的编程需要注意的是千万不要让快指针一次性走两步,不然可能会出错
- 如果没有相遇,返回空指针,如果相遇了,就把相遇位置处的地址记下来。
- 最后也是最关键的就是现在我们有了相遇位置和链表头节点处的指针,分别从这两个位置出发的话,到达链表的环的位置距离是一样的,这个时候我们就给这两个位置同样的速度向后遍历,如果他们的地址一样,那就是环的起始位置。具体的思路如下:
detect.h
#pragma once
#include <set>
struct ListNode
{
int val;
ListNode *next;
ListNode (int x) :val(x),next(NULL){}
};
ListNode* detectcycle1(ListNode* head);
ListNode* dete
deteccycle1.cpp
#include "detectcycle.h"
ListNode *detectcycle1(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;
}
detectcycle2.cpp
#include "detectcycle.h"
ListNode* detectcycle2(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) {
return NULL;
}
while (head) {
if (head == meet) {
return head;
}
head = head->next;
meet = meet->next;
}
return NULL;
}
detectcycle_test.cpp
#include "detectcycle.h"
using namespace std;
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;
ListNode *node = detectcycle2(&a);
cout << node->val << endl;
system("pause");
return 0;
}
b_leetcode4——链表划分
题目:已知链表头指针head与数值x,将所有小于x的节点放在大于或等于x的节点前,且保持这些节点的原来的相对位置。
思路:
- 1、建立两个临时的链表(less和more),对于这两个链表,分别保存其头指针和一个遍历的指针,也就是四个指针
- 如果head->val比x小,就把这个地址放到less头指针的后面,并且将这个遍历的指针移动到val上面
- 如果head->val比x大,就把这个地址放到more头指针的后面,后面的操作同样。
- 最后把两个临时链表拼接起来就可以了
partition.h
#pragma once
#include <stdio.h>
struct ListNode
{
int val;
ListNode* next;
ListNode(int x) :val(x), next(NULL) {}
};
ListNode *partition(ListNode* head,int x);
partition.cpp
#include "partition.h"
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;
}
partition_test.cpp
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include "partition.h"
using namespace std;
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;
ListNode *head = partition(&a, 3);
while (head) {
cout << head->val << endl;
head = head->next;
}
system("pause");
return 0;
}
b_leetcode5——排序链表的合并
题目:已知有两个已排序的链表头节点指针11与12,将这两个链表合并,合并后仍为有序的,返回合并后的头节点。
思路:
-
一、首先建立一个临时的链表结构,准备存放排序后的链表
-
二、然后建立两个指针,分别指向这两个链表的头部开始比较
-
三、比较这两个指针的val,把val比较小的那个指针存放到临时的链表的结构中去
-
四、将较小的指针向后移动一位,val较大的那个指针保持不动,这样循环