程序员代码面试指南题目解析(一)

news2024/12/27 11:35:06

        题目一:如何仅用递归函数和栈操作逆序一个栈

      题目要求:

    一个栈依次压入 1、2、3、4、5,那么从栈顶到栈底分别为5、4、3、2、1。将这个栈
转置后,从栈顶到栈底为 1、2、3、4、5,也就是实现栈中元素的逆序,但是只能用递归函数来实现,不能用其他数据结构。

      题目解析:

   根据题目要求,我们需要使用递归函数,依次将栈中的元素进行逆置出来。我们可以根据递归函数所可能产生的影响进行问题的解决。

   由于递归函数在递归的结束的时候可以进行返回,所以我们如果拿到一个数据并删除的话,在最后返回的时候会拿到最后一个数据。所进行的操作如下:

  如果想要将数组进行逆序仅仅拿到最后一个数据是完全不够的,我们还需要思考如何将一个数组进行逆序,这个思路其实很简单。我们可以再次使用一次递归操作,每次拿出最下面的数据,并保存,之后我们递归返回的时候就可以拿到最上面的数据了。我们将数据依次压入栈中就会得到一个逆序的栈。

    根据上述思路我们可以设计两个递归函数实现栈的逆序操作,实现代码如下:

#include<iostream>
#include<stack>
using namespace std;

int getAndRemoveLastElem(stack<int>& sk)
{
	int result = sk.top();
	sk.pop();
	if (sk.empty())
	{
		return result;
	}
	else
	{
		//继续进行递归删除操作
		int last = getAndRemoveLastElem(sk);
		sk.push(result);
		return last;
	}
}

//最后通过调用递归函数
void StackReverseStack(stack<int>& sk)
{
	if (sk.empty())
	{
		return;
	}
	int i = getAndRemoveLastElem(sk);
	StackReverseStack(sk);
	sk.push(i);
}

int main()
{
	stack<int> ret;
	ret.push(1);
	ret.push(2);
	ret.push(3);
	ret.push(4);
	ret.push(5);
	StackReverseStack(ret);
	//之后打印输出栈当中的内容检查逆序的状况
	while (!ret.empty())
	{
		cout << ret.top() << endl;
		ret.pop();
	}

	return 0;
}

        题目二:用栈来求解汉诺塔问题

      题目要求: 
   汉诺塔问题比较经典,这里修改一下游戏规则:现在限制不能从最左侧的塔直接移动
到最右侧,也不能从最右侧直接移动到最左侧,而是必须经过中间。求当塔有 N层的时候,需要最少移动多少步。

    题目解析:

    这道题我们可以将其认为是一个简单的模拟类的题目,首先我们来分析问题:

    题目当中要求我们所进行的移动的步数是最少的,因此不允许由连续的可逆的步骤存在。例如:上一步从左到中间进行移动,下一步就从中间到左进行移动。这样上一步移动的步骤就是完全没有效果的,不可能是最少的移动次数。

   其次,题目当中要求我们在移动的时候必须经过中间,因此我们可以判断,当两个柱子进行移动完成之后(其中一个柱子一定是中间的柱子)一定是中间的柱子和另外一个没有进行移动的柱子进行移动操作,无非就是从中间移动到目标位置,或者从目标位置移动到中间。我们只需要符合汉诺塔的规则即可,也就是小的数据必须在大的数据之上才可以进行移动。所进行的示例如下:

    我们可以设置两个变量用于作为记录两个变化的柱子的情况,之后排除中间的柱子,让另一根柱子跟中间柱子进行数据的移动即可。根据上述思路我们可以写出如下代码:

#include<iostream>
#include<stack>
#include<vector>
#include<string>
using namespace std;
//使用栈进行解决汉诺塔问题
int stackSloveHanio(int data)
{
	stack<int> left;
	while (data)
	{
		left.push(data);
		data--;
	}
	stack<int> mid;
	stack<int> right;
	//经过第一次初始化之后进行统一的数据操作
	int from = 1;
	int to = 2;     //使用1,2,3表示左中右三个柱子
	int x = left.top();
	left.pop();
	mid.push(x);
	int count = 1;
	//之后检查三个柱子的情况得到最终想要的结果
	while (!left.empty() || !mid.empty())
	{
		//当左边跟中间的柱子都不为空的时候就继续循环查找新的初始情况
		//由判断可知,我们的from和to无论怎么移动一定与中间柱子有关,
		//因此我们只需要查找中间柱子跟另外一个没有用到的柱子的移动方向即可
		int tmp = from;
		if (from == 2)
		{
			tmp = to;
		}
		if (tmp == 1)  //下一次进行的操作就需要是从另外一个柱子跟中间柱子移动数据
		{
			//判断3柱子移动到中间,还是从中间移动到3柱子
			if (!right.empty()&&(mid.empty() || right.top() < mid.top()))
			{
				//从3移动到2
				mid.push(right.top());
				right.pop();
				from = 3;
				to = 2;
			}
			else
			{
				//从2移动到3
				right.push(mid.top());
				mid.pop();
				from = 2;
				to = 3;
			}
			count++;
		}
		if (tmp == 3)
		{
			//同理可得
			if (!left.empty()&&(mid.empty() || left.top() < mid.top()))
			{
				mid.push(left.top());
				left.pop();
				from = 1;
				to = 2;
			}
			else
			{
				left.push(mid.top());
				mid.pop();
				from = 2;
				to = 1;
			}
			count++;
		}
	}
	return count;
}
int main()
{
	cout<<stackSloveHanio(3);
	return 0;
}

        题目三:生成窗口最大值数组

      题目要求:
  有一个整型数组 arr 和一个大小为 w 的窗口从数组的最左边滑到最右边,窗口每次向
右边滑一个位置。
例如,数组为[4,3,5,4.3,3,6,7],窗口大小为 3 时:
[4 3 5] 4 3 3 6 7          窗口中最大值为 5
4 [3 5 4] 3 3 6 7          窗口中最大值为 5
4 3 [5 4 3] 3 6 7          窗口中最大值为 5
4 3 5 14 3 3] 6 7         窗口中最大值为 4
4 3 5 4 [3 3 6] 7          窗口中最大值为 6
4 3 5 4 3 [3 6 7]          窗口中最大值为 7
如果数组长度为 n,窗口大小为 w,则一共产生 n-w+1 个窗口的最大值。

请实现一个函数。
•输入:整型数组 arr,窗口大小为 w.
•输出:一个长度为 n-W+1 的数组 res,res[i]表示每一种窗口状态下的最大值。
以本题为例,结果应该返回{5,5,5,4,6,7}。

     题目解析:

   这道题目实际上想要让我们进行的操作也就是根据指定的窗口依次选出窗口内元素的最大值。拿到这道题目的时候我们首先会有一个思路:直接进行模拟不久行了嘛,每次有新的数据进入窗口的时候进行一次遍历,得到最大的值,加入到数组当中。但是我们来思考一下时间复杂度:每一次遍历窗口一遍,假设窗口的大小为M,数据总共N个,所以我们总的时间复杂度为O(MN)这并不是一个很好的算法,因此我们需要进行优化。

  书中有一个很奇妙的思想:试想一下,在我们的窗口当中有新加入的元素,当新加入的元素较大的时候前面较小的元素就不可能是最大的元素,我们可以直接前面较小的数据删除。当新加入的数据较小的时候,当前面较大的数据删除之后,那么这个暂时较小的数据就有可能是最大的了。所以我们需要将数据保存。

  借助双端队列进行优化我们的代码。我们可以进行一次数组遍历,当队列为空或者新数据小于队列尾部的数据的时候可以直接将数据的下标加入到队列的尾部,当新数据大于队列尾部的数据的时候,直接将队列尾部的数据进行弹出数据。知道队列当中的数据大于新数据或者队列为空为止。所要进行的操作如下:

    需要注意的是:由于为了方便我们判断数据的加入以及输出的边界条件,因此我们需要将数组的下标作为加入队列的元素。当我们的队头元素小于我们窗口最左侧元素的下标的时候就说明数据已经失效,需要将队头数据删除,获得下一个窗口当中最大的元素。根据上述思路我们可以编写出如下的代码:

#include<iostream>
#include<vector>
#include<queue>
using namespace std;

//编写一个函数,用于查找生成窗口最大值的数组
vector<int> createMaxWindow(vector<int> ret, int windows)
{
	//我们需要借助一个栈进行解决这个问题
	deque<int> dq;
	vector<int> finEnd;
	int count = windows;
	//进行数据的遍历操作,将我们数组当中的内容的下标依次放到栈当中,如果之后进入的数据大于之前的数据
	//就直接进行入栈操作,否则需要先执行出栈操作,等到满足小于之前的元素的时候就可以执行入栈操作了
	for (int i=0;i<ret.size();i++)
	{
		while (!dq.empty()&&ret[i]>ret[dq.front()])
		{
			dq.pop_back();
		}
		dq.push_back(i);
		//之前向栈当中插入的元素还不满,不能直接进行记录最大值
		if ( count== 1)
		{
			//进行检查并返回最大值,检查栈顶的最大值是否过期
			while (i - windows >= dq.front())
			{
				dq.pop_front();    //删除过期的最大值
			}
			//找到不过期的数据直接进行记录队头元素
			finEnd.push_back(ret[dq.front()]);
		}
		else
		{
			count--;
		}
	}
	return finEnd;
}

int main()
{
	//进行测试最大生成窗口代码
	vector<int> ret({ 1,2,3,4,5,6,7,8,9 });
	vector<int> tmp=createMaxWindow(ret, 5);
	for (auto e : tmp)
	{
		cout << e << " ";
	}
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1664804.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JUC下的BlockingQueue详解

BlockingQueue是Java并发包(java.util.concurrent)中提供的一个接口&#xff0c;它扩展了Queue接口&#xff0c;增加了阻塞功能。这意味着当队列满时尝试入队操作&#xff0c;或者队列空时尝试出队操作&#xff0c;线程会进入等待状态&#xff0c;直到队列状态允许操作继续。这…

【Python系列】Python中列表属性提取

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

AI菜鸟向前飞 — 大模型基础知识篇

前言 主要介绍最最基础的知识&#xff0c;在这个基础上有现在比较流行的GPT、Llama、Gemini**等一系列大模型的出现&#xff0c;打好基础才能更理解上面是如何运作以及实现的过程。 PS&#xff1a;本篇科普不会介绍梯度下降算法&#xff08;偏导数&#xff09;等复杂的过程&a…

巨坑啊! before-upload返回false 会执行on-remove

通过对on-remove对应参数的打印&#xff0c;发现回调中的file参数有个status&#xff0c;若是是在before-upload中就被过滤了&#xff0c;就是ready&#xff0c;若是已经上传成功了去点击删除&#xff0c;status是success&#xff0c;就他了。 onRemove(file,fileList){if(file…

redis的双写一致性

双写一致性问题 1.先删除缓存或者先修改数据库都可能出现脏数据。 2.删除两次缓存&#xff0c;可以在一定程度上降低脏数据的出现。 3.延时是因为数据库一般采用主从分离&#xff0c;读写分离。延迟一会是让主节点把数据同步到从节点。 1.读写锁保证数据的强一致性 因为一般放…

Redis——缓存雪崩、缓存穿透、缓存击穿

在项目中&#xff0c;通常会使用数据库比如 MySQL 存储应用数据&#xff0c;但是当数据太多之后&#xff0c;比如多了几十万条或上百万条的商品信息&#xff0c;这个时候查询商品数据的速度会很慢&#xff0c;影响用户体验。此时一般我们会选择将部分商品信息缓存起来&#xff…

【Rollup】用rollup从0到1开发一个js插件并发布到npm

Rollup 是一个 JavaScript 模块打包器&#xff0c;专注于打包 ES6 模块将其编译回多种模块化格式&#xff0c;尤其适合打包库和框架&#xff0c;因为它可以生成更小、更高效的代码&#xff0c;并且特别适合将代码打包成可在浏览器中使用的库。 从0到1开发js插件 1.创建文件夹…

2.前端路由的配置和使用

一&#xff0c;路由的作用 路由的作用就是将页面文件跟URL地址形成对应匹配 二&#xff0c;如何安装路由 这里我们采用pnpm的方式在项目中执行 pnpm install vue-routernext --save三&#xff0c;路由如何使用 首先创建一个我们需要访问的页面文件&#xff0c;这里我先创建…

机器学习:葡萄酒品质预测

说明&#xff0c;此项目是我的期末大作业&#xff0c;包括了对数据集探索&#xff0c;预处理以及分类的各个详细过程与描述&#xff0c;代码简单&#xff0c;主要是一个分类项目的流程&#xff0c;并没有对模型进行深度研究&#xff0c;因此我写在这里。 目录 一、问题介绍 …

ETL工具kettle(PDI)入门教程,Job

先新建两个Transform&#xff0c;MysqlToMysql.ktr和CsvToExcel.ktrURL&#xff1a;ETL工具kettle入门教程&#xff0c;transform&#xff0c;Mysql-&#xff1e;Mysql&#xff0c;Csv-&#xff1e;Excel-CSDN博客 主对象树&#xff0c;作业上右击&#xff0c;点击新建 核心对…

Unity引擎是什么?有哪些优点

大家好&#xff0c;我是咕噜土豆&#xff0c;很高兴又和大家见面了。今天我们一起来了解一下Unity引擎和它有哪些优点。 首先带大家了解什么是Unity引擎 Unity引擎是一款由Unity Technologies开发的跨平台游戏开发引擎&#xff0c;广泛用于创建2D和3D游戏以及其他交互式内容&…

uniapp管理后台编写,基于uniadmin和vue3实现uniapp小程序的管理后台

一&#xff0c;创建uniAdmin项目 打开开发者工具Hbuilder,然后点击左上角的文件&#xff0c;点新建&#xff0c;点项目。如下图。 选择uniadmin&#xff0c;编写项目名&#xff0c;然后使用vue3 记得选用阿里云服务器&#xff0c;因为最便宜 点击创建&#xff0c;等待项目创…

AI跟踪报道第41期-新加坡内哥谈技术-本周AI新闻:本周Al新闻: 准备好了吗?事情即将変得瘋狂

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

在Spring Boot应用安装SSL证书

目录 前提条件 步骤一&#xff1a;下载SSL证书 步骤二&#xff1a;在Spring Boot安装SSL证书 步骤三&#xff1a;验证SSL证书是否安装成功 前提条件 已通过数字证书管理服务控制台签发证书SSL证书绑定的域名已完成DNS解析&#xff0c;即您的域名与主机IP地址相互映射已在W…

ASP.NET学生信息管理系统

摘 要 本文介绍了在ASP.net环境下采用“自上而下地总体规划&#xff0c;自下而上地应用开发”的策略开发一个管理信息系统的过程。通过分析某一学校学生管理的不足&#xff0c;创建了一套行之有效的计算机管理学生的方案。文章介绍了学生管理信息系统的系统分析部分&#xff0c…

【C++ | 函数】默认参数、哑元参数、函数重载、内联函数

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; ⏰发布时间⏰&#xff1a;2024-05-04 1…

Linux —— 信号(4)

Linux —— 信号&#xff08;4&#xff09; 信号的处理用户态和内核态 信号的捕捉sigaction sa_mask字段volatileSIGCHLD信号 我们今天接着来看信号&#xff1a; 信号的处理 信号的处理简单一句话就是在内核态处理的。 用户态和内核态 用户态和内核态是操作系统和计组中的概…

MySQL系列之索引

&#x1f339;作者主页&#xff1a;青花锁 &#x1f339;简介&#xff1a;Java领域优质创作者&#x1f3c6;、Java微服务架构公号作者&#x1f604; &#x1f339;简历模板、学习资料、面试题库、技术互助 &#x1f339;文末获取联系方式 &#x1f4dd; 往期热门专栏回顾 专栏…

【声呐仿真】学习记录2-运行ROV(带camera、sonar、dvl等传感器)例程

【声呐仿真】学习记录2-运行ROV&#xff08;带camera、sonar、dvl等传感器&#xff09;例程 前言第一阶段-学习Gazebo第二阶段-学习URDF、xacro第三阶段-寻找例程跑一个rexrov示例程序1.uuvsimulator quick_start2.能键盘控制的示例程序&#xff08;失败&#xff09;3.能键盘控…

[初阶数据结构】单链表

前言 &#x1f4da;作者简介&#xff1a;爱编程的小马&#xff0c;正在学习C/C&#xff0c;Linux及MySQL。 &#x1f4da;本文收录于初阶数据结构系列&#xff0c;本专栏主要是针对时间、空间复杂度&#xff0c;顺序表和链表、栈和队列、二叉树以及各类排序算法&#xff0c;持…