每日算法练习

  大家好,今天给大家带来一些算法题,无他,只是想让大家认识一些题型,当以后遇到后会有头绪,能够使用优秀的算法。

题目一

  一颗二叉树有n个节点,求最多有多少种二叉树形状。

题目分析

  如果二叉树有0个节点,那么只有一种情况—空树;如果只有1个节点,那么只有一种情况—只有根节点;如果有两个节点,根节点占一个,我们先认为左侧节点有0个,那么右侧节点有一个,一种情况,当左侧节点有1个节点时,右侧无节点,也只有一种情况,两种情况相加共两种情况。这样我们就可以分析出解题思路:如果二叉树有n个节点,我们分别讨论二叉树左侧有0个,1个......n-1个节点时二叉树的数量,最后相加得到最终答案,每一次均为f(i)*f(n-i-1)。

代码分析

1.递归

int nodecount(int n){if(n==0||n==1){return 1;}int count=0;for(int left=0;left<=n-1;left++){//减去一个根节点 count=count+nodecount(left)*nodecount(n-left-1);	}return count;
}

2.动态规划 

int nodecount2(int n){//n为有多少结点 int dp[n+1];for(int i=0;i<n+1;i++){dp[i]=0;}dp[0]=dp[1]=1;for(int i=2;i<=n;i++){//总共结点数目 for(int left=0;left<=i-1;left++){//左侧结点数目 dp[i]=dp[i]+dp[left]*dp[i-left-1];}}return dp[n];
}

题目二 

  给你一个字符串仅有‘(’和‘)’构成,判断括号是否匹配,如果不匹配需要补充多少括号。

题目分析

  我想很多小伙伴拿到这道题目时,第一时间想到的是用栈解决。当然可以,不过有更简单的方法,只需要两个计数器count和ans即可。

  我们从左到右遍历整个字符串,当遇见左括号时count++,遇到右括号时count--。如果字符串需要右括号才能达到匹配目的时,那么最后count为一个大于0的数,count的数量就是需要的右括号数量。当遍历时发现count==-1时,说明字符串肯定不匹配,需要补充左括号,此时我们令count再次等于0,然后ans++。最终ans记录的就是需要补充左括号的数量。ans+count的值就是我们需要的补充的括号数量

代码分析

#include<iostream>
using namespace std;
void theminmatch(string str){int count=0,ans=0;for(int i=0;i<str.length();i++){if(str[i]=='('){count++;}else{count--;}if(count<0){ans++;count=0;}}//括号匹配if(!count&&!ans){cout<<"无需添加"<<endl;}if(count){cout<<"需要添加"<<count<<"个右括号"<<endl; }if(ans){cout<<"需要添加"<<ans<<"个左括号"<<endl;}
}
int main(){string str="(((())()()()())";theminmatch(str);
}

题目三 

 有两个集合,我们想进行操作:将一个集合的元素移动到另一个集合中,并且达到让这两个集合的平均值均增大。求最多操作次数。

题目分析

  首先,这两个集合应该不为空,否则无平均值这一概念。其次,当我们移动元素X到某集合时,若集合中包含X,那么该集合平均值不会发生变化(集合中相同元素当作一个元素),这是由集合性质决定的。

  集合A平均值为ave1,集合B平均值为ave2。那么该如何移动呢?我们分情况讨论。

  情况1:ave1=ave2:

  我们从A移动元素X到B,若X<ave1,那么移动后ave1变大,ave2变小,不符合情况。X>ave1,那么移动后ave1变小,ave2变大,不符合情况。如果X=ave1,那么移动后ave和ave2均不变,不满足情况。因此ave1=ave2时,移动次数为0.

  情况2:ave1<ave2(小移大):

  我们从A移动元素X到B,若X>ave1,移动后ave1减小,不符合情况。若X=ave1,移动后ave1不变,不符合情况。若X<ave1,移动后ave2变小,不符合情况。因此小集合向大集合移动时也不满足情况。

  情况3:ave1>ave2(大移小):

  我们从A移动元素X到B,若X>ave1,移动后ave1减小,不符合情况。若X<ave2,移动后ave2减小不符合情况。若X=ave1或X=ave2,移动后肯定存在某个集合平均值不变,不符合情况。当X界于ave2和ave1时,移动后两个元素集合平均值均增大,满足情况。

  此时我们知道何时才能移动,那么如果集合中有多个满足情况的元素呢?我们该优先移动小元素还是大元素呢?分析题目:移动次数最多!!肯定是优先移动小元素,因为移动小元素后ave1增长最大,ave2增加最小,二者差值最大,可能移动的次数最多。那如何保证我们先拿到小元素呢?对平均值大集合进行排序即可。

代码分析

#include<iostream>
#include<algorithm>
using namespace std;
int Sum(int *arr,int n){int sum=0;for(int i=0;i<n;i++){sum=sum+arr[i];}return sum;
}
int *copy(int *arr,int n){int *copy=new int[n];for(int i=0;i<n;i++){copy[i]=arr[i];}return copy;
}
bool notcontains(int *arr,int n,int x){for(int i=0;i<n;i++){if(arr[i]==x){return 0;}}return 1;
}
int main(){int arr1[4]={1,5,2,7};int arr2[5]={3,4,1,6,8};int *min,*max,length,ans=0,l,cnt1,cnt2;int sum1=Sum(arr1,4);int sum2=Sum(arr2,5);double average1=sum1*1.0/4;double average2=sum2*1.0/5;double minave,maxave;if(average1==average2){cout<<"0"<<endl;return 0;}if(average1>average2){max=copy(arr1,4);min=copy(arr2,5);sort(max,max+4);//对平均值大的数组进行排序 cnt1=length=4;cnt2=l=5;minave=average2;maxave=average1;}else{min=copy(arr1,4);max=copy(arr2,5);sort(max,max+5);cnt1=length=5;cnt2=l=4;maxave=average2;minave=average1;}//只能从大集合拿元素放到小集合才能满足两个集合平均值均变大      average1<x<average2  // 满足两个集合均不为空  移动到i集合时i集合不能有该元素 (集合两个相同元素相当于一个,平均值不变) for(int i=0;i<length;i++){if(max[i]>minave&&max[i]<maxave&&notcontains(min,l,max[i])&&cnt1!=1){//若有多个元素满足条件选小的//这样可以保证大数组平均值加的多 小数组平均值加的少 保证最大magic次数  //这也是为什么对大数组进行排序的原因 ans++;sum1=sum1-max[i];sum2=sum2+max[i];minave=(sum1*1.0)/(length-ans);//更新平均值 maxave=(sum2*1.0)/(l+ans);cnt1--;}}cout<<"最大挪动次数为"<<ans;
}

  有些小细节需要大家注意,算平均值时注意用double数据,思路比较简单,就是细节较多,大家多多注意。

题目四 

  给定一个字符串,只有左括号和右括号,字符串可能匹配也可能不匹配,求匹配的最长字串。

题目分析

  首先我们应该区分子串和子序列,子串是连续的,子序列可以不连续。

  我们这样考虑:dp【i】代表以i位置元素结尾所匹配的最大长度。当arr【i】为左括号时,dp【i】肯定为0。当arr【i】为右括号时,i前方dp【i-1】长度肯定已经匹配,此时我们需要看cur=i-dp【i-1】-1位置的元素,如果为右括号,那么dp【i】肯定为0。为什么呢?因为以cur位置元素结尾的最大匹配长度为0,如果不是0的话,那么dp【i-1】的值会变大,跟实际不符发生矛盾,因此cur位置为右括号时dp【i】=0。如果cur位置为左括号时,那么dp【i】长度至少为dp【i-1】+。此时我们需要看cur-1位置的dp值,最后dp【i】=dp【i】+dp【cur-1】

代码分析

#include<iostream>
using namespace std;
int getmax(string s,int n){int dp[n];//以i位置结尾的最大匹配串for(int i=0;i<n;i++){dp[i]=0;}dp[0]=0;int cur;for(int i=1;i<=n-1;i++){if(s[i]=='('){dp[i]=0;continue;//以左括号结尾肯定不匹配 }dp[i]=dp[i]+dp[i-1];//*****)此时状态 cur=i-dp[i-1]-1;//检查*前一位 if(cur<0){dp[i]=0;//如果没有肯定跟最后的右括号无法对应为0 continue;}if(s[cur]==')'){dp[i]=0;//如果*前一位为),那么肯定不会存在((####)*****)//因为如果cur有匹配的话 i-1位置匹配长度会更长矛盾  continue;}dp[i]=dp[i]+2;//如果cur为左括号(*****)在原来基础上加2(首尾) //最后加上cur-1位置的dp值只需一次,因为该处记录了此处为结尾的最大匹配值 if(cur-1<0){continue;}dp[i]=dp[i]+dp[cur-1];} int max=-1;for(int i=0;i<n;i++){cout<<dp[i]<<" ";if(max<dp[i]){max=dp[i];}}cout<<endl;return max;//返回最大值 
}
int main(){string str="(())(())";int max=getmax(str,str.length());cout<<max;
}

  大家注意是否有越界的可能,小细节不能忽略。

题目五 

  给定一个二维数组,保证其行列均按照从小到大的顺序,但整体无序。求二维数组中是否存在元素X。

题目分析

  很重要的一个条件就是行列有序!我们如果从数组右上角开始的话,比较当前位置元素和X大小关系,如果相等则返回。如果该元素小于X,那么行下标加一,列下标不变。如果该元素大于X,那么行下标不变,列下标减一。如果最后越界,说明不存在。没有越界说明存在。

  我们这样操作每次移动一行或一列,为O(m+n)的算法,而普通的遍历为O(m*n)。

代码分析

#include<iostream>
using namespace std;
int main(){int n,m;cin>>n>>m;int arr[n][m];//数组每一行和每一列均是从小到大有序,但整体不有序for(int i=0;i<n;i++){for(int j=0;j<m;j++){cin>>arr[i][j];}} //查找数组中是否存在元素Xint x;cout<<"输入想查找的元素"<<endl;cin>>x;int curx=0,cury=m-1,flag=0;while(arr[curx][cury]!=x){if(arr[curx][cury]>x){cury=cury-1;}else if(arr[curx][cury]<x){curx=curx+1;}if(curx<0||curx>n-1||cury<0||cury>m-1){flag=1;break;}}if(!flag){cout<<"元素所在位置为:"<<curx+1<<" "<<cury+1<<endl;} else{cout<<"不存在该元素"<<endl;}
} 

题目六 

  给定一个二维数组,元素只有0和1,且保证每一行:0在左侧,1在右侧(可以全0或全1)。求行中最多1的数量。

题目分析

  我们还是从右上角开始,一直向左走记录1的数量,当遇见0后向下走,对每一行均进行这种操作,最后count的值就是1的最大数量。

代码分析

#include<iostream>
using namespace std;
//数组只有0,1,且每一行1均在右侧,0均在左侧(可以全1或全0) 
//求行中最多1的数量 
int main(){int n,m;cin>>n>>m;int arr[n][m];for(int i=0;i<n;i++){for(int j=0;j<m;j++){cin>>arr[i][j];}}int curx=0,cury=m-1,count=0;while(curx<=n-1){while(cury>=0&&arr[curx][cury]==1){cury--;count++;}curx++;}cout<<count;
}

  要注意一直向左走时的越界问题。 

本次算法练习到此结束,希望大家多多点赞支持。

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

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

相关文章

Zabbix低权限SQL注入至RCE+权限绕过

Zabbix低权限SQL注入至RCE权限绕过&#xff0c;可惜没找到关于传webshell的好方法&#xff0c;如有大神告知&#xff0c;感激万分&#xff01; 本文中所有代码以及后续更新都会放在我的github仓库中&#xff1a; https://github.com/W01fh4cker/CVE-2024-22120-RCE 一、漏洞环…

[vulnhub]DC: 1

https://www.vulnhub.com/entry/dc-1,292/ 主机发现端口扫描 使用nmap扫描网段类存活主机 因为靶机是我最后添加的&#xff0c;所以靶机IP是156 nmap -sP 192.168.75.0/24 // Starting Nmap 7.93 ( https://nmap.org ) at 2024-09-28 12:48 CST Nmap scan rep…

jmeter脚本-请求体设置变量and请求体太长的处理

目录 1、查询接口 1.1 准备组织列表的TXT文件&#xff0c;如下&#xff1a; 1.2 添加 CSV数据文件设置 &#xff0c;如下&#xff1a; 1.3 接口请求体设置变量&#xff0c;如下&#xff1a; 2、创建接口 2.1 见1.1 2.2 见1.2 2.3 准备创建接口的请求体TXT文件&#xff…

SQL,力扣题目1549,每件商品的最新订单【窗口函数】

一、力扣链接 LeetCode_1549 二、题目描述 表: Customers ------------------------ | Column Name | Type | ------------------------ | customer_id | int | | name | varchar | ------------------------ customer_id 是该表主键. 该表包含消费者的…

卸载 Adobe Genuine Software Client

一、问题描述 使用破jie版Adobe Acrobat Pro DC软件后&#xff0c;会经常弹出以下窗口&#xff1a; 且上述探窗无法直接关掉。即使通过任务管理器将其临时关掉&#xff0c;可等过一段时间后&#xff0c;仍然会再次弹出&#xff0c;严重干扰工作进度。 二、问题解决 &#xff…

京东云雅典娜刷机步骤(需要拆机)

京东云雅典娜刷机步骤 必须拆机 必须拆机 必须拆机 刷机要用的文件 1.高通驱动文件&#xff08;USB刷机必备&#xff09;&#xff1a;https://pan.quark.cn/s/6405674f981b 2.进入临时uboot的程序&#xff1a;https://pan.quark.cn/s/ebc1d449cb89 3.uboot固件&#xff1a; ht…

电子商城购物平台的设计与开发+ssm(lw+演示+源码+运行)

摘 要 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;电子商城购物平台小程序被用户普遍使用&#xff0c;为方便…

基于 Spring Boot 和 Vue 的门票销售创新系统

作者介绍&#xff1a;✌️大厂全栈码农|毕设实战开发&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 &#x1f345;获取源码联系方式请查看文末&#x1f345; 推荐订阅精彩专栏 &#x1f447;&#x1f3fb; 避免错过下次更新 Springboot项目精选实战案例 更多项目…

【Python】Python自习课:第一个python程序

【Python】Python自习课&#xff1a;第一个python程序 示例

docker-compose安装rabbitmq 并开启延迟队列和管理面板插件(rabbitmq_delayed_message_exchange)

问题&#xff1a; 解决rabbitmq-plugins enable rabbitmq_delayed_message_exchange &#xff1a;plugins_not_found 我是在docker-compose环境部署的 services:rabbitmq:image: rabbitmq:4.0-managementrestart: alwayscontainer_name: rabbitmqports:- 5672:5672- 15672:156…

103 - Lecture 2 Table and Data Part 1

SQL - Tables and Data Part 1 Relational Database Management System(RDBMS) 关系型数据库管理系统&#xff08;RDBMS&#xff09;是基于关系模型的数据库系统&#xff0c;它支持多种关系操作。关系模型是一种数据存储和检索的模型&#xff0c;它使用表格来组织数据&#x…

PropTypes 和 TypeScript 在 React 中的比较

文章目录 引言PropTypes什么是 PropTypes&#xff1f;如何使用 PropTypes优点缺点 TypeScript什么是 TypeScript&#xff1f;如何使用 TypeScript优点缺点 选择建议总结 引言 在 React 开发中&#xff0c;组件的可复用性和可维护性至关重要。为了确保组件接收到正确的 props&a…

【自动化利器】12个评估大语言模型(LLM)质量的自动化框架

LLM评估是指在人工智能系统中评估和改进语言和语言模型的过程。在人工智能领域&#xff0c;特别是在自然语言处理&#xff08;NLP&#xff09;及相关领域&#xff0c;LLM评估具有至高无上的地位。通过评估语言生成和理解模型&#xff0c;LLM评估有助于细化人工智能驱动的语言相…

儿童安全座椅行业全面深入分析

儿童安全座椅就是一种专为不同体重&#xff08;或年龄段&#xff09;的儿童设计&#xff0c;将孩子束缚在安全座椅内&#xff0c;能有效提高儿童乘车安全的座椅。欧洲强制性执行标准ECE R44/03的定义是&#xff1a;能够固定到机动车辆上&#xff0c;带有ISOFIX接口、LATCH接口的…

Pytest-Bdd-Playwright 系列教程(6):在测试步骤函数中设置别名数据共享

Pytest-Bdd-Playwright 系列教程&#xff08;6&#xff09;&#xff1a;在测试步骤函数中设置别名&数据共享 前言一、步骤别名二、特性文件三、测试脚本四、运行测试五、小测验总结 前言 有的时候&#xff0c;为了提高可读性&#xff0c;我们需要使用不同的名称来声明相同的…

【笔记】变压器-热损耗-频响曲线推导 - 03 变压器参数-特性

参考《Mn-Zn开关电源用铁氧体磁心 PQ系列》&#xff0c;March 2014版 1.可能选择的型号和参数 PQ系列的这种铁氧体结构设计是TDK首创的。 优势是&#xff0c;相对E, EER磁芯&#xff0c;安装面积更小材质选择 PC47PC90PC95尺寸 PQ20/16 最小PQ50/50 最大 2.特性 2.1 温升与…

Unity性能优化 -- 性能分析工具

Stats窗口Profiler窗口Memory Profiler其他性能分析工具&#xff08;Physica Debugger 窗口&#xff0c;Import Activity 窗口&#xff0c;Code Coverage 窗口&#xff0c;Profile Analyzer 窗口&#xff0c;IMGUI Debugger 窗口&#xff09; Stats 统级数据窗口 game窗口 可…

一些swift问题

写得比较快&#xff0c;如果有问题请私信。 序列化和反序列化 反序列化的jsonString2只是给定的任意json字符串 private func p_testDecodeTable() {let arr ["recordID123456", "recordID2"]// 序列化[string] -> json datalet jsonData try? JSO…

VMware虚拟机Debian扩展磁盘

一、 版本 VMware&#xff1a;Workstation 17 Pro虚拟机&#xff1a;Debian11 二、 VMware虚拟机扩展 虚拟机关机状态快照或者备份&#xff1a;以免扩容失败导致文件丢失虚拟机——设置——硬盘——磁盘使用工具——扩展——扩展磁盘容量——设置为想要的大小 三、 虚拟机…