21(调整数组顺序使所有奇数位于所有偶数之前)、22(链表中倒数第k个节点)、23(链表中环的入口节点)

题目21分析:(调整数组顺序使所有奇数位于所有偶数之前)
考虑时间复杂度问题,可设置首尾第一第二两个指针,当第一指针指向奇数,第二指针指向偶数,则交换指向的数据,
直至第二指针移动到第一指针之前。同时为了考虑算法的可扩展,将奇偶判断写为子函数的形式。
思路:
1.初始化第一指针和第二指针指向数组的首尾
2.轮询第一指针<第二指针
2.向后移动第一指针,直至指向偶数
3.向前移动第二指针,直至指向奇数

4.交换第一、二指针指向的数据

#include <iostream>

using namespace std;

bool odd_or_even(int num)
{
	if ((num & 0x1) == 0)//奇数的最后一位都是1,所以可利用位与判断数据的奇偶性,偶数==0,奇数==1
		return true;
	else
		return false;
}
void reorder_arr(int *arr, int length,bool (*func)(int num))//入口参数是函数名称(也是地址)
{
	if (arr == NULL||length<1)
	{
		cout << "数组为空。" << endl;
		return;
	}

	//1.初始化第一指针和第二指针指向数组的首尾
	int *first_ptr = arr;
	int *second_ptr = arr + length - 1;
	//2.轮询第一指针<第二指针
	while (first_ptr < second_ptr)
	{
		//2.向后移动第一指针,直至指向偶数
		while (first_ptr < second_ptr && !func(*first_ptr))//入口参数
			++first_ptr;
		//3.向前移动第二指针,直至指向奇数
		while (first_ptr < second_ptr&&func(*second_ptr))
			--second_ptr;
		if (first_ptr < second_ptr)
		{
			int temp = *first_ptr;
			*first_ptr = *second_ptr;
			*second_ptr = temp;
		}
	}
}

void main()
{
	int arr[] = { 1,2,3,4,5 };
	int length = sizeof(arr) / sizeof(arr[0]);
	reorder_arr(arr, length, odd_or_even);
	for (int i = 0; i < length; i++)
		cout << arr[i] << endl;
}

题目22分析:(链表中倒数第k个节点)
由于是单向链表,如果使用遍历链表两次的方式,时间复杂度较高,所以使用两个指针的方式。保持第一指针和第二指针的距离是k-1,则当第一指针到达尾节点时,第二指针指向的就是倒数第k个节点。
思路:
1.初始化第一指针指向头节点、第二指针==NULL
2.首先让第一指针走k-1步,然后让初始化第二指针指向头节点

3.同时向前遍历,直到第一指针到达尾节点

#include <iostream>

using namespace std;

struct LinkNode
{
	int data;
	LinkNode *next;
};
//创建链表
void create_link(LinkNode *head_ptr, int length)
{
	for (int i = length; i >= 1; --i)
	{
		LinkNode *new_node = new LinkNode;
		new_node->data = i;
		new_node->next = head_ptr->next;
		head_ptr->next = new_node;
	}
}
//打印链表内容
void print_link(LinkNode *head_ptr, int length)
{
	LinkNode *temp_node = head_ptr->next;
	while (temp_node!= NULL)
	{
		cout << temp_node->data << " ";
		temp_node = temp_node->next;
	}
	cout << endl;
}

LinkNode* print_tail_k_node(LinkNode *head_ptr, int k)
{
	if (head_ptr == NULL || k == 0)
		return NULL;
	//1.初始化第一指针指向头节点、第二指针==NULL
	LinkNode *first_ptr = head_ptr->next;
	LinkNode *second_ptr = NULL;

	//2.首先让第一指针走k-1步,然后让初始化第二指针指向头节点
	for (int i = 0; i < k - 1; i++)
	{
		if (first_ptr->next != NULL)//防御链表长度小于k的情况
			first_ptr = first_ptr->next;
		else
			return NULL;
	}
	second_ptr = head_ptr->next;

	//3.同时向前遍历,直到第一指针到达尾节点
	while (first_ptr->next != NULL)
	{
		first_ptr = first_ptr->next;
		second_ptr = second_ptr->next;
	}
	return second_ptr;
}

void main()
{
	LinkNode *head_ptr = new LinkNode;
	head_ptr->data = 0;
	head_ptr->next = NULL;
	create_link(head_ptr, 6);
	print_link(head_ptr, 6);

	LinkNode *tail_k_node = print_tail_k_node(head_ptr, 3);
	cout << tail_k_node->data << endl;
}

题目23分析:(链表中环的入口节点)
首先需两个快慢指针判断是否有环,如果有环则获得相遇节点,此节点一定在环内;然后获得环中节点的数量n;最终使用两个
指针,从头节点开始,第一节点先走n步,然后同时开始移动,直至相遇。
思路:
1.初始化快慢指针,慢指针走一步,快指针走两步,直至相遇返回指针指向节点,否则当慢指针为空时,
则无环,返回NULL
2.获得相遇节点,从此节点开始遍历,直至再次相遇,获得节点数量n
3.初始化第一二指针,移动第一指针n步
4.同时移动第一、二指针,直至相遇

#include <iostream>

using namespace std;
struct LinkNode
{
	int data;
	LinkNode *next;
};
//创建有环链表
void create_link(LinkNode *head_ptr, int length, int start, int end)
{
	for (int i = length; i >= 1; --i)
	{
		LinkNode *new_node = new LinkNode;
		new_node->data = i;
		new_node->next = head_ptr->next;
		head_ptr->next = new_node;
	}
	LinkNode *entry_node=NULL;
	LinkNode *node = head_ptr->next;
	for (int i = 1; i <= length; ++i)
	{
		if (i == end)
			entry_node = node;
		if (i == start)
			node->next = entry_node;
		if(i!=length)
			node = node->next;
	}
}
//打印链表内容
void print_link(LinkNode *head_ptr, int length, int start, int end)
{
	LinkNode *temp_node = head_ptr->next;
	int num = 1;
	while (temp_node != NULL&& num<=10)
	{
		cout << temp_node->data << " ";
		temp_node = temp_node->next;
		++num;
	}
	cout << endl;
}
LinkNode *get_meet_node(LinkNode *head_ptr)
{
	//if (head_ptr->next = NULL)
	//	return NULL;

	//1.初始化快慢指针
	LinkNode *slow_node = head_ptr->next;
	if (slow_node == NULL)
		return NULL;

	LinkNode *fast_node = slow_node->next;
	//有环则不会为空
	while (fast_node != NULL&&slow_node != NULL)
	{
		//直至相遇返回指针指向节点
		if (fast_node == slow_node)
			return fast_node;

		//慢指针走一步,快指针走两步
		slow_node = slow_node->next;
		fast_node = fast_node->next;
		if(fast_node!=NULL)
			fast_node = fast_node->next;
	}
	return NULL;//无环则为空
}
LinkNode *get_entry_node(LinkNode *head_ptr)
{
	//2.获得相遇节点,从此节点开始遍历,直至再次相遇,获得节点数量n
	LinkNode *meet_node = get_meet_node(head_ptr);
	cout << "相遇节点:" << meet_node->data << endl;
	if (meet_node == NULL)//无环
		return NULL;

	int num = 1;
	LinkNode *node = meet_node;
	while (meet_node != node->next)
	{
		node = node->next;
		++num;
	}
	cout << "环中节点数量:" << num << endl;

	//3.初始化第一二指针,移动第一指针n步
	LinkNode *first_node = head_ptr->next;
	LinkNode *second_node = head_ptr->next;
	for (int i = 0; i < num; i++)
		first_node = first_node->next;

	//4.同时移动第一、二指针,直至相遇
	while (first_node != second_node)
	{
		first_node = first_node->next;
		second_node = second_node->next;
	}

	return first_node;
}
void main()
{
	LinkNode *head_ptr = new LinkNode;
	head_ptr->next = NULL;
	create_link(head_ptr, 6, 6, 3);
	print_link(head_ptr, 6, 6, 3);

	LinkNode *entry_node = get_entry_node(head_ptr);
	cout << "环的入口节点是:" << entry_node->data << endl;
}

猜你喜欢

转载自blog.csdn.net/attitude_yu/article/details/80621361
今日推荐