【C++】 —— 笔试刷题day_28

【C++】 —— 笔试刷题day_28

一、游游的重组偶数

题目解析

在这里插入图片描述
这道题,有q组数据,每一次输入一个正整数x,让我们将这个数进行重排,变成一个偶数,然后返回(如果x本身就是一个偶数那可以直接返回x);

如果不存在合法解,就是x通过重排后,无法变成一个偶数,就输出-1

算法思路

这道题,总体来说还是比较简单的;

对于正整数x,我们可以把它当作一个字符串进行输入;(如果按照整数输入,我们还要将这个数x的每一位变换成对应数组)

我们知道,如果一个数是偶数,那最低位一定是一个偶数,这样我们只需判断字符串的最后一位即可知道这个数是否是偶数;如果这个数是偶数,那就直接输出即可;如果最后一位不是偶数,那就从第一位开始向后找,找到一位是偶数,然后把它交换到最后一位;然后输出即可;如果遍历完这个字符串,还没找到一位是偶数的,那就表示这个数x通过重拍无法变成偶数,输出-1即可。

题目解析

#include<iostream>usingnamespace std; string func(){ string str; cin >> str;int n = str.size();if((str[n -1]-'0')%2==0)return str;for(int i =0; i < n -1; i++){if((str[i]-'0')%2==0){swap(str[i], str[n -1]);return str;}}return"-1";}intmain(){int q; cin >> q;while(q--){ cout <<func()<< endl;}return0;}

二、体操队形

题目解析

在这里插入图片描述
dd作为体操队长,现在要对体操队的n名同学(1 ~ n)进行排队;对于第i号队员,会有一个诉求a[i],表示i要排在a[i]的前面;如果a[i] == i,那就表示当前i号队员没有任何诉求,排在哪里都行。

现在dd想知道一共有多少种排队方案。

算法思路

初看这道题,可以说毫无头绪,根本无从下手;

我们要对n个队员排序;一部分队员还要求排在某个队员的前面,对于这个要求,我们很容易就可以解决了:

我们从左到右依次排队即可,排第i个队员时,只需判断它的诉求a[i]有没有排过就OK了。

那对于第i个位置,我们怎们知道某一个队员,能否在这个位置呢?

这就非常简单了,我们只需要记录一下每一个队员是否已经排过队了即可;

我们只需遍历每一个队员,看这一个队员是否能够放到该位置即可;

而我们一个队员不能放到该位置,有两种情况:一是这个队员已经排过了,我们接着遍历下一个队员即可;另一种则是,当前队员的诉求a[i]已经排过了,也就是该队员的诉求[i]在该队员i的前面;那此时无论我们怎们排,那肯定是不满足条件的;那我们就无需向后进行排了。

看到这里,相信大致思路以及能够理清楚了,我们先来绘制一下这道题的一个决策树:

在这里插入图片描述

代码实现

#include<iostream>usingnamespace std;int arr[11];//每一个队员的诉求bool vis[11];//记录每一个队员是否被排过int ret =0;//最终结果int n;voidbfs(int pos){if(pos == n +1){//表示找到一种排序方案 ret++;return;}for(int i =1;i<=n;i++){if(vis[i]==true)//i队员已经被排过continue;if(vis[arr[i]]==true)//i队员的诉求已经排过,也就是arr[i] 在 i的前面了,无论怎么排都不满足条件return; vis[i]=true;//当前位置被排过bfs(pos +1);//排下一个位置 vis[i]=false;//修改,回溯}}intmain(){ cin>>n;for(int i =1;i<=n;i++){ cin>>arr[i];}bfs(1);//从第一个位置开始填 cout<<ret<<endl;return0;}

三、二叉树中的最大路径和

题目解析

在这里插入图片描述
这道题还是比较难理解的,我们来看:

题目给定一个二叉树,让我们求出最大路径和;

路径:我们可以从二叉树中的任意节点出发,通过父 -> 子或者子 -> 父,到达任意节点的序列。同一个节点在一个二叉树路径中最多只能出现一次,简单来说就是同一个节点只能经过一次;一个路径至少包含一个节点,而且不一定要包含跟节点。

就如示例中给的1 , 2 , 3,最优路径就是2 -> 1 -> 3或者3 -> 1 -> 2

算法思路

OK啊,初看这道题,如果题目读的似懂非懂的,那可以说一点思路没有(博主第一次看到这道题就是这样的)

仔细思考一下,这道题不就是一个递归/dfs问题吗;

这里分享一下博主做题时的思路:

对于题目描述,我们要找的路径,它可以是从一个节点先一直向上走,然后在某一个节点,开始再走向子节点;当然也可以是从一个节点一直向上走,不再向下走向子节点。

所以对于二叉树的每一个节点我们可以求一下,在这一个节点为转折点时的最大路径和;

我们要求某一个节点为转折点的最大路径和,那我们就要知道左子树单路径的最大路径和和右子树单路径的最大路径和;我们就只能通过递归的返回值来获得,所以我们返回值就表示从一个节点向下走到nullptr的单路径的最大路径和。

所以在遍历到某一个节点时,要做的就是:求以这个节点为转折点时的最大路径和;然后返回从这个节点向下走到nullptr的单路径的最大路径和。

如果左子树和右子树的最大单路径和是<0的,我们可以不向下走(因为我们要求的是最大路径和);

这样我们只需要考虑最大路径和的第一种情况,就是先向上走,但某一个节点再向下走;对于第二种情况,不就是我们返回值的情况吗。

但是上述中存在一个问题,也是博主在写这道题时没有注意到的一个问题:

这里博主直接判断的是左子树和右子树的最大单路径和都>0时,才计算左右子树最大单路径的和;博主没有考虑到如果左子树和右子树的最大单路径和一个<0,一个小于>0时的情况;

因为博主的疏忽,这也导致博主的思路有一个漏洞:如果考虑我们以某一个节点为转折点的情况,那最大路径和是第二章情况时,我们求出来的就是错误的答案;就比如10 , 5 , -9,正确结果是15而我们求出来的就是10

因为5 -> 10这一种情况在函数最后的返回值当中,而这里没有考虑这一个返回值。(但是这里,是可以通过这道题目的,可以是这道题没有这种情况的测试用例)。

无论如何,博主感觉自己的思路还是存在漏洞的,要在最后考虑一个递归函数的返回值。

OK啊,现在来看这道题的思路:

其实上述就是这道题的大致思路了,哈哈!

我们要求二叉树中的最大路径和,我们要采用递归,bfs;(递归肯定是后序遍历)

那遍历到一个节点时,我们要求什么?

在博主的思路中,求的是以这个节点为转折点的路径和的最大值;

但是如果左子树和右子树某个子树中的最大单路径和<0时,那此时的最大路径和就不是上述中的第一种情况了,而是第二种情况;那我们就漏掉了一直情况。

所以这里我们在遍历到一个节点时,要求的是在该子树中,经过该节点的路径的最大路径和。

那要求经过该节点的最大路径和,我们就要知道左子树和右子树的最大单路径的和

所以我们的返回值就表示该子树中的最大单路径的和,当然要经过当前节点。

OK我们知道了要求什么,和返回值是什么,现在来看如何去求:

经过该节点的最大路径和,那当左右子树最大单路径和可能是小于0的,而<0时,我们肯定不会向下走的,所以我们可以对左右子树的最大单路径和与0求一个最大值;

也就是说当左右子树的最大单路径和是<0时,我们求经过该节点的最大路径和时,左leftright子树最大单路径和是=0的;我们当前节点就表示一个路径。

**返回值:**因为我们这里的leftright都是>=0的,我们直接返回当前节点的值val + max(left,right)即可。

这样最后,我们就无需再对递归函数的返回值就行判断,直接返回结果即可。

代码实现

博主自己的思路:

classSolution{public:int ret =-1000*100000;intfunc(TreeNode* root){if(root ==nullptr)return0;int left =func(root->left);int right =func(root->right);//求if(left >=0&& right >=0) ret =max(ret, left + right + root->val);else ret =max(ret,root->val);returnmax(left,right)+ root->val;}intmaxPathSum(TreeNode* root){returnmax(ret,func(root));}};

优化后的思路代码:

classSolution{public:int ret =-1010;intbfs(TreeNode* root){if(root ==nullptr)return0;int left =max(bfs(root->left),0);int right =max(bfs(root->right),0); ret =max(ret, root->val + left + right);return root->val +max(left, right);}intmaxPathSum(TreeNode* root){// write code herebfs(root);return ret;}};

到这里,本篇文章内容就结束了,感谢各位支持

Read more

【C++初阶】C++入门相关知识(2):输入输出 & 缺省参数 & 函数重载

【C++初阶】C++入门相关知识(2):输入输出 & 缺省参数 & 函数重载

🎈主页传送门:良木生香 🔥个人专栏:《C语言》 《数据结构-初阶》 《程序设计》《鼠鼠的C++学习之路》 🌟人为善,福随未至,祸已远行;人为恶,祸虽未至,福已远离 上期回顾:在上一篇文章中,我们对C++进行了初步的认识,学习了C++的发展历史,第一个C++程序以及命名空间,我们知道,C++的出现就是为了改进和完善C语言的不足,使得程序更加高效,程序员编写起来更加方便快捷,那么本篇文章我们继续往下认识C++的入门相关知识 目录 一、C++的输入&输出 1.1、核心载体:头文件 1.2、核心的IO对象:cin与cout 1.2.1、std::cin 标准输入流 1.

By Ne0inhk
飞算 JavaAI:让 Java 开发效率翻倍的秘密武器 #飞算JavaAl炫技赛 #Java开发

飞算 JavaAI:让 Java 开发效率翻倍的秘密武器 #飞算JavaAl炫技赛 #Java开发

前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 * 飞算 JavaAI:让 Java 开发效率翻倍的秘密武器 #飞算JavaAl炫技赛 #Java开发 * 一、引言 * 二、Java 开发现状与挑战剖析 * 2.1 Java 语言的辉煌历史 * 2.2 传统 Java 开发的那些 “坑” * 2.2.1 开发周期:比蜗牛爬还慢 * 2.2.2 人力成本:高得离谱 * 2.2.3 代码质量:参差不齐 * 2.2.

By Ne0inhk
环境搭建 | [入门级]VSCode(Cursor|Trae|Qoder)搭建Java(Springboot3)企业开发环境全流程

环境搭建 | [入门级]VSCode(Cursor|Trae|Qoder)搭建Java(Springboot3)企业开发环境全流程

VSCode搭建Java企业开发环境全流程 在企业级Java开发(如Springboot)中,IDE的选择至关重要。VSCode凭借其轻量、高效、插件生态丰富的特点,逐渐成为许多开发者的首选。本文将详细介绍如何在VSCode中搭建完整的Java企业开发环境,涵盖从基础软件安装到项目调试运行的全流程,适合刚接触VSCode或想迁移Java开发环境的小伙伴。 当前热门的AI IDE(如Cursor、Trae、Qoder)均基于VSCode开发,因此本教程对这类IDE同样适用。 一、准备工作:安装必要软件 在搭建VSCode Java开发环境前,需先安装两个核心工具:JDK和VSCode。 1.1 安装JDK Java开发依赖JDK(Java Development Kit),企业开发建议选择LTS(长期支持)版本,如JDK 11或JDK 17。 1. 安装JDK:运行安装包,按提示完成安装,建议记住安装路径(如Windows下的C:\Program Files\Eclipse Adoptium\jdk-17.

By Ne0inhk
Java 多态

Java 多态

文章目录 * 多态 * 向上转型和向下转型 * 向上转型和重写 * 重写和重载的区别 * 动态绑定和静态绑定 * 用代码来解释什么是多态 * 向下转型 * 多态的优点 * 总结 多态 1. 什么是多态?为什么要使用多态? 简单来说是多种形态,具体来说是去完成某个事情,当不同对象去完成同一件事表现出来的不同结果/状态 打个比方就是同一个人对待不同人表现出来的形态是不同的 2. 多态实现的三个条件: 向上转型和向下转型 向上转型和重写 1. 将子类对象给父类类型的引用 父类类型 对象名 = new 子类类型() 直接赋值的 classAnimal{publicString name;publicint age;publicAnimal(String name,int age){this.name = name;this.age = age;}// 父类中的this是当前对象的引用publicvoideat(){System.out.println(

By Ne0inhk