《程序员代码面试指南》it名企算法与数据结构题目最优解(第二版)刷题笔记8

本文介绍使用环形单链表解决约瑟夫问题的方法,并提供了一种高效判断链表是否为回文结构的算法。通过具体实例展示了链表操作的技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

由于之前看了牛客网的数据结构和算法的课程知道了左神,现在找到了这本书当作入门书做做吧,虽然书的题解都是java实现的,但好在用c++实现难度不大。

第二章 链表问题

第一题:环形单链表的约瑟夫问题
据说著名的犹太历史学家Josephus有过以下故事:在罗马人占领桥塔帕特后,39个犹太人与Josephus 及他的朋友躲到一个洞中,39个犹太人宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第一个人开始报数,报数到3的人就自杀,然后再有下一个人重新报1,报数到3的人再自杀。这样依次下去,直到剩下最后一个人时,那个人可以自由选择自己的命运。这就是著名的约瑟夫问题。现在请用单向环形链表描述该结构并呈现整个自杀过程。

输入:一个环形单向链表的头节点head 和报数的值m。

返回:最后生存下来的节点,且这个节点自己组成环形单向链表,其他节点都删掉。

之前已经反复说过,如果要删除一个节点,则要找到他之前的节点。首先遍历找到head之前的节点pre,然后按题意做下去即可,时间复杂度为O(n*m)。

 struct ListNode {
	int val;
	ListNode *next;
	ListNode(int x) : val(x), next(NULL) {}
	
 };
 ListNode* josephusKill(ListNode *head, int m) {
	 if (head == NULL || head->next == head || m < 1) {
		 return head;
	 }
	 ListNode* pre = head;
	 while (pre->next != head) {
		 pre = pre->next;
	 }
	 int count = 0;
	 while (head->next!=head) {
		 if (count != m-1) {
			 pre = head;
			 head = head->next;
			 ++count;
		 }
		 else {
			 pre->next = head->next;
			 head = head->next;
			 count = 0;
		 }
	 }
	 return head;
 }

题目二:判断一个链表是否为回文结构
回文用栈结构。
方法一:直接全放进栈中再进行出栈比对,额外空间复杂度为O(n);
方法二:对方法一进行了优化,虽然也是利用栈结构,但只压入一半的节点。

#include<stack>
using namespace std;
 struct ListNode {
	int val;
	ListNode *next;
	ListNode(int x) : val(x), next(NULL) {}
	
 };
 bool isPalindrome2(ListNode *head) {
     //关键在如下两步找到右区间的头结点
	 ListNode* right = head->next, *cur = head;
	 while (cur->next != NULL || cur->next->next != NULL) {
		 right = right->next;
		 cur = cur->next->next;
	 }
	 stack<int> stack;
	 while (cur->next != NULL) {
		 stack.push(cur->val);
		 cur = cur->next;
	 }
	 while (!stack.empty()) {
		 if (head->val != stack.top()) {
			 return false;
		 }
		 head = head->next;
		 stack.pop();
	 }
	 return true;
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值