b_leetcode——链表

b_leetcode1——链表逆序a

题目:已知链表头节点指针head,将链表逆序。(不可申请额外空间)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8LlWIlvZ-1617370012448)(C:\Users\wl\AppData\Roaming\Typora\typora-user-images\image-20210220220245819.png)]

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逆序(不申请额外空间)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4vXWL8Ll-1617370012450)(C:\Users\wl\AppData\Roaming\Typora\typora-user-images\image-20210223101359859.png)]

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,两个链表相交,求两链表交点对应的节点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nYyQzs2Z-1617370012452)(C:\Users\wl\AppData\Roaming\Typora\typora-user-images\image-20210223103213217.png)]

  • 如果两个链表没有交点,则返回NULL;
  • 在求交点的过程中,不可以破坏链表的结构或者修改链表的数据域
  • 可以确保传入的链表A与链表B没有任何环
  • 实现算法尽可能使时间复杂度O(n),空间复杂度O(1)

思路1

  • 1、遍历链表A,将A中节点对应的指针(地址),插入set
  • 2、遍历链表B,将B中节点对应的指针(地址),在set中查找,发现在set中的第一个节点地址,就是两个链表的交点。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7gOZYBBM-1617370012454)(C:\Users\wl\AppData\Roaming\Typora\typora-user-images\image-20210223155004295.png)]

思路2:

  • 1、计算headA和headB的链表长度,然后计算较长的链表多出来的长度

  • 2、将较长链表的指针移动到和较短链表指针对齐的位置

  • 3、headA和jheadB同时移动,当两个指针指向同一个节点时,即找到了
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U2shhFku-1617370012456)(C:\Users\wl\AppData\Roaming\Typora\typora-user-images\image-20210223171219570.png)]

下面时具体的代码

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。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5apk5pbL-1617370012459)(C:\Users\wl\AppData\Roaming\Typora\typora-user-images\image-20210223195227697.png)]

思路一:

  • 1、遍历链表,将链表中节点对应的指针(地址),插入set
  • 2、但是在插入之前,需要判断set中有没有这个指针(地址),第一个在set中发现的节点地址,即是链表环的起点。

思路二:

  • 采用的是快慢指针赛跑的思路,首先快、慢指针位于同一起跑线上,快指针的速度是慢指针的两倍。(这里需要注意的是编程时候的细节:快指针和慢指针同时走一步,如果快指针不为空,就继续再走一步,如果为空,就不能走了。)这里的编程需要注意的是千万不要让快指针一次性走两步,不然可能会出错
  • 如果没有相遇,返回空指针,如果相遇了,就把相遇位置处的地址记下来。
  • 最后也是最关键的就是现在我们有了相遇位置链表头节点处的指针,分别从这两个位置出发的话,到达链表的环的位置距离是一样的,这个时候我们就给这两个位置同样的速度向后遍历,如果他们的地址一样,那就是环的起始位置。具体的思路如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2EhopQMi-1617370012460)(C:\Users\wl\AppData\Roaming\Typora\typora-user-images\image-20210224102926080.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zQP79MkT-1617370012461)(C:\Users\wl\AppData\Roaming\Typora\typora-user-images\image-20210224102959684.png)]

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的节点前,且保持这些节点的原来的相对位置。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jqmmkwvt-1617370012462)(C:\Users\wl\AppData\Roaming\Typora\typora-user-images\image-20210224104816199.png)]

思路:

  • 1、建立两个临时的链表(less和more),对于这两个链表,分别保存其头指针和一个遍历的指针,也就是四个指针
  • 如果head->val比x小,就把这个地址放到less头指针的后面,并且将这个遍历的指针移动到val上面
  • 如果head->val比x大,就把这个地址放到more头指针的后面,后面的操作同样。
  • 最后把两个临时链表拼接起来就可以了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NpargGIL-1617370012463)(C:\Users\wl\AppData\Roaming\Typora\typora-user-images\image-20210224110605202.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p9NI5x1x-1617370012464)(C:\Users\wl\AppData\Roaming\Typora\typora-user-images\image-20210224110650464.png)]

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,将这两个链表合并,合并后仍为有序的,返回合并后的头节点。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hlsiAF1G-1617370012464)(C:\Users\wl\AppData\Roaming\Typora\typora-user-images\image-20210224163513705.png)]

思路:

  • 一、首先建立一个临时的链表结构,准备存放排序后的链表

  • 二、然后建立两个指针,分别指向这两个链表的头部开始比较

  • 三、比较这两个指针的val,把val比较小的那个指针存放到临时的链表的结构中去

  • 四、将较小的指针向后移动一位,val较大的那个指针保持不动,这样循环

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5AeAJVkv-1617370012465)(C:\Users\wl\AppData\Roaming\Typora\typora-user-images\image-20210224165627009.png)]

猜你喜欢

转载自blog.csdn.net/qq_32651847/article/details/115408133
今日推荐