算法与设计分析--实验一

蛮力算法的设计与分析(暴力)

这次是某不知名学院开学课程的第一次实验,一共5道题,来自力扣

第一题.216组合总和*力扣题目链接

第一道题是经典的树型回溯

class Solution {
public:vector<vector<int>> combinationSum3(int k, int n) {}
};

首先我们要知道,力扣上都是核心代码模式,也就是说你只要实现其中的核心部分,一般是一个函数或者结构,不用你从新开始写头文件之类的,比如这里需要你实现的函数就是这个combinationSum3 (计数总和3)。

需要的返回值是一个二维动态数组(c++代码)

右上角可以选择代码模式,这里以C++为例

先看一遍题目描述:

找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。

说明:

所有数字都是正整数。

解集不能包含重复的组合。 

示例 1:

输入: k = 3, n = 7

输出: [[1,2,4]]

示例 2:

输入: k = 3, n = 9

输出: [[1,2,6], [1,3,5], [2,3,4]]

也就是说,我们输出的组合不能重复,顺序无关

这道题就是dfs组合计数的升级版

因为时间效率低,所以题目数据不会很大,数据大了就得换其他方法了

先看一遍递归实现排列型枚举的代码

#include<iostream>using namespace std;const int  N= 10;int path[N], n;bool st[N];void dfs(int u)
{if(u>n){for(int i = 1; i <=n; i++) cout<<path[i]<<' ';puts("");}else{for(int i = 1; i<=n;i++){if(st[i] == false){path[u] = i;st[i] = true;dfs(u+1);st[i] = false;}}}
}
int main(){cin>>n;dfs(1);return 0;
}

我们同理,先存储路径和答案

vector<vector<int>> result; // 存放结果集vector<int> path; // 符合条件的结果

确定终止条件

        if (path.size() == k) {if (sum == targetSum) result.push_back(path);return;}

在初学dfs(回溯)时,画一个回溯图会更好理解一点

电脑上画图还是太难了,找一个别人的图

我们可以发现,我们题目要求的K,就是树的深度

每一层都是1~9的选择, 但是我们要注意,因为答案不重复,比如3,6和6,3是属于一个答案

所以我们每一次选择数字都要从该数字的后面开始选择,比如选择了2,下一层选择的数字就是3~9

当然,我们还发现可以剪枝优化,

比如当SUM>我们的target的时候,我们就不用向下遍历了

还有就是当剩下可以选择的数字小于K了,我们也不用向下遍历了

代码+注释如下

class Solution {
private:vector<vector<int>> result; // 存放结果集vector<int> path; // 符合条件的结果void backtracking(int targetSum, int k, int sum, int startIndex) { //最后一个参数为开始选择的数字,防止出现重复组合if (sum > targetSum) { // 剪枝操作1return; // 如果path.size() == k 但sum != targetSum 直接返回}if (path.size() == k) { // 终止条件,可以返回了if (sum == targetSum) result.push_back(path);return;}for (int i = startIndex; i <= 9 - (k - path.size()) + 1; i++) { // 剪枝操作2sum += i; // 处理path.push_back(i); // 处理backtracking(targetSum, k, sum, i + 1); // 注意i+1调整startIndexsum -= i; // 回溯 还原现场path.pop_back(); // 回溯 还原现场}}public:vector<vector<int>> combinationSum3(int k, int n) {backtracking(n, k, 0, 1);return result;}
};

第二题.206反转链表力扣题目链接

这道题是基础中的基础了

题目描述:

反转一个单链表。

示例:

输入: 1->2->3->4->5->NULL

输出: 5->4->3->2->1->NULL

思路也很简单 就是遍历链表 遍历链表每一个节点的时候把该节点指向前一个节点

当然,为了原链表不被打乱,我们需要一个临时节点

代码+注释如下

class Solution {ListNode* reverse(ListNode* pre,ListNode* cur){//参数为 前节点 当前节点if(cur == NULL)return pre; //如果是空链表 直接返回 auto temp = cur->next; //临时节点指向当前节点的下一节点 为了遍历cur->next = pre;//当前节点指向前一节点return  reverse(cur,temp); //递归往后遍历}
public:ListNode* reverseList(ListNode* head) {return reverse(NULL,head);//传入头节点}
};

第三题:1160.拼写单词力扣题目链接

先看一遍题目描述

给你一份『词汇表』(字符串数组) words 和一张『字母表』(字符串) chars。

假如你可以用 chars 中的『字母』(字符)拼写出 words 中的某个『单词』(字符串),那么我们就认为你掌握了这个单词。

注意:每次拼写(指拼写词汇表中的一个单词)时,chars 中的每个字母都只能用一次。

返回词汇表 words 中你掌握的所有单词的 长度之和。

示例 1:

输入:words = ["cat","bt","hat","tree"], chars = "atach"

输出:6

解释:

可以形成字符串 "cat" 和 "hat",所以答案是 3 + 3 = 6。

示例 2:

输入:words = ["hello","world","leetcode"], chars = "welldonehoneyr"

输出:10

解释:

可以形成字符串 "hello" 和 "world",所以答案是 5 + 5 = 10。

提示:

1 <= words.length <= 1000

1 <= words[i].length, chars.length <= 100

所有字符串中都仅包含小写英文字母

class Solution {
public:int countCharacters(vector<string>& words, string chars) {}
};

题目传入的是一个字符串动态数组,一个目标字符串

这道题出在这样有点怪怪的,一开始用dfs没做出来

用类似哈希的做法就轻松搞定了

原理就是把chars里的每一个字母进行计数,当目标单词中每个字母计数不为0时,则证明能拼出这个单词

代码+注释如下:
 

class Solution {
public:int countCharacters(vector<string>& words, string chars) {int m[26]; // 计数,类哈希表,保存chars每个字母出现的次数memset(m, 0, sizeof(m)); //不是全局变量 得初始化for (char ch : chars) {m[ch-'a'] ++; //计数}int ret = 0;for (auto word : words) {int temp[26];memcpy(temp, m, sizeof(m));bool canSpell = true;for (char ch : word) {if (temp[ch-'a'] == 0) {canSpell = false;break;}temp[ch-'a'] --;}if (canSpell) {ret += word.size();}}return ret;}
};

第四题 
1475. 商品折扣后的最终价格

题目描述:

给你一个数组 prices ,其中 prices[i] 是商店里第 i 件商品的价格。

商店里正在进行促销活动,如果你要买第 i 件商品,那么你可以得到与 prices[j] 相等的折扣,其中 j 是满足 j > i 且 prices[j] <= prices[i] 的 最小下标 ,如果没有满足条件的 j ,你将没有任何折扣。

请你返回一个数组,数组中第 i 个元素是折扣后你购买商品 i 最终需要支付的价格。

示例 1:

输入:prices = [8,4,6,2,3]

输出:[4,2,4,2,3]

解释:

商品 0 的价格为 price[0]=8 ,你将得到 prices[1]=4 的折扣,所以最终价格为 8 - 4 = 4 。

商品 1 的价格为 price[1]=4 ,你将得到 prices[3]=2 的折扣,所以最终价格为 4 - 2 = 2 。

商品 2 的价格为 price[2]=6 ,你将得到 prices[3]=2 的折扣,所以最终价格为 6 - 2 = 4 。

商品 3 和 4 都没有折扣。

示例 2:

输入:prices = [1,2,3,4,5]

输出:[1,2,3,4,5]

解释:在这个例子中,所有商品都没有折扣。

示例 3:

输入:prices = [10,1,1,6]

输出:[9,0,1,6]

提示:

1 <= prices.length <= 500

1 <= prices[i] <= 10^3

简单题,我们可以完全按照题目意思写一个二重循环遍历就好

数据也不大,暴力就能过(废话,不能怎么叫暴力算法试验报告)

class Solution {
public:vector<int> finalPrices(vector<int>& prices) {vector<int> res;  //不改变原数组 开个数组存答案bool flag = true; //判断是否加入答案for(int i = 0; i < prices.size(); i ++ ){for(int j = 1; j < prices.size(); j ++ ){if(j > i && prices[j] <= prices[i]) // 题目给的条件照抄{res.push_back(prices[i] - prices[j]);flag = false;break;}}if(flag) res.push_back(prices[i]);elseflag = true; }return res;}
};

看了一下评论,这道题单调栈也能做,时间复杂度能优化到O(n)

class Solution {
public:vector<int> finalPrices(vector<int>& prices) {//维护一个价格单调递增的栈存储索引值//若当前价格小于栈顶所指价格,则栈顶索引值出栈,计算该索引处折扣后的价格,直到栈为空或当前价格大于栈顶所指价格//将当前索引入栈if(prices.empty()) return {};stack<int> s;int len=prices.size();vector<int> ans(len);s.push(0); //将第一个元素的索引入栈for(int i=1;i<len;++i){while(!s.empty()&&prices[i]<=prices[s.top()]){ans[s.top()]=prices[s.top()]-prices[i]; //计算折扣后的价格s.pop(); //出栈}s.push(i);}while(!s.empty()) //剩余的是没有折扣的{ans[s.top()]=prices[s.top()];s.pop();}return ans;}
};

第五题
1518. 换水问题

题目描述:

小区便利店正在促销,用 numExchange 个空酒瓶可以兑换一瓶新酒。你购入了 numBottles 瓶酒。

如果喝掉了酒瓶中的酒,那么酒瓶就会变成空的。

请你计算 最多 能喝到多少瓶酒。

输入:numBottles = 9, numExchange = 3

输出:13

解释:你可以用 3 个空酒瓶兑换 1 瓶酒。

所以最多能喝到 9 + 3 + 1 = 13 瓶酒。

输入:numBottles = 15, numExchange = 4

输出:19

解释:你可以用 4 个空酒瓶兑换 1 瓶酒。

所以最多能喝到 15 + 3 + 1 = 19 瓶酒。

示例 3:

输入:numBottles = 5, numExchange = 5

输出:6

示例 4:

输入:numBottles = 2, numExchange = 3

输出:2

 提示:

1 <= numBottles <= 100

2 <= numExchange <= 100

看着题目很复杂,实际上那是非常非常的简单,之前的题目瓶盖还能换酒,这个只有瓶子能换酒

大一的C语言基础题都比这难

不说了,直接上代码和注释,看完应该都能懂 也不用什么优化了,暴力算法已经超越100%了,这题基数小,暴力最快

class Solution {
public:int numWaterBottles(int numBottles, int numExchange) {int res = 0; //存答案int temp = numBottles;  // 存初始瓶数res += numBottles;while(temp >= numExchange) //如果剩下的瓶子换不了就结束{res += temp / numExchange;int temp2 = temp % numExchange; // 记得要加上上一轮换不了的余数temp /= numExchange;temp += temp2;}return res;}
};

总结:

新学期算法课的第一次试验,除了第一题有难度,其他基本是拿来凑数的

第一题是搜索和回溯,也是真正“暴力”算法的样子,其他的更多像一个模拟题,复述题目内容就好

半年了,学校蓝桥杯的报名费都还没报销,真是对自己学算法的同学极大的鼓励啊

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

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

相关文章

leetcode:58. 最后一个单词的长度

题目&#xff1a; 函数原型&#xff1a; int lengthOfLastWord(char * s) 解析&#xff1a; 求最后一个单词的长度&#xff0c;我们有两种思路 第一种思路&#xff1a; 逆向求&#xff0c;先设置一个字符串下标index&#xff0c;定位到最后一个单词的最后一个字符。再一个设置长…

MySQL——连接查询与子查询

一、连接查询 单表查询&#xff1a;在一张表当中查询数据&#xff0c;叫做单表查询。 连接查询&#xff0c;结合俩&#xff08;多&#xff09;张表&#xff0c;在俩张&#xff08;多&#xff09;表当中查询数据&#xff0c;在一张表当中查询一部分&#xff0c;在另一张表当中…

UE4/UE5 动画控制

工程下载​ ​​​​​​​​​​​​​https://mbd.pub/o/bread/ZJ2cm5pu 蓝图控制sequence播放/倒播动画&#xff1a; 设置开启鼠标指针&#xff0c;开启鼠标事件 在场景中进行过场动画制作 设置控制事件

MySQL的概述、版本、安装过程

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 作者会持续更新网络知识和python基础知识&#xff0c;期待你的关注 目录 一、MySQL的概述 二、MySQL的版本 三、MySQL的下载与安装 前言 本文将来谈谈MySQL的概述&#xff0c;MySQL的版本&#xff0c;以及它…

实相融、云启未来,智慧公厕让城市生活更美好

现代社会&#xff0c;随着科技的不断发展&#xff0c;人们对于城市生活的要求也在不断提升。在这个过程中&#xff0c;智慧公厕作为城市基础设施中的重要组成部分&#xff0c;正在发挥着越来越重要的作用。通过数字化、云管理、人工智能等未来的科技方式&#xff0c;智慧公厕为…

Android lint配置及使用

关于作者&#xff1a;CSDN内容合伙人、技术专家&#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 &#xff0c;擅长java后端、移动开发、商业变现、人工智能等&#xff0c;希望大家多多支持。 目录 一、导读二、概览三、将 lint 配置为不显示警告3.1 在 A…

OpenWrt系统开发笔记

openWrt英文官网&#xff1a; https://openwrt.org/ 中文官网&#xff1a; http://www.openwrt.org.cn/ 一、开发环境及编译 在github上有两个源码使用的比较多   一个是lede,地址为&#xff1a;https://github.com/coolsnowwolf/lede   另一个为OpenWrt的官方源码&#…

【美团3.18校招真题1】

大厂笔试真题网址&#xff1a;https://codefun2000.com/ 塔子哥刷题网站博客&#xff1a;https://blog.codefun2000.com/ 小美剪彩带 提交网址&#xff1a;https://codefun2000.com/p/P1088 题意&#xff1a;找出区间内不超过k种数字子数组的最大长度 使用双指针的方式&…

【JAVA】Object类与抽象类

作者主页&#xff1a;paper jie_的博客 本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 本文录入于《JAVASE语法系列》专栏&#xff0c;本专栏是针对于大学生&#xff0c;编程小白精心打造的。笔者用重金(时间和…

包管理工具--》发布一个自己的npm包

包管理工具系列文章目录 一、包管理工具--》npm的配置及使用&#xff08;一&#xff09; 二、包管理工具--》npm的配置及使用&#xff08;二&#xff09; 三、包管理工具--》发布一个自己的npm包 四、包管理工具--》yarn的配置及使用 五、包管理工具--》其他包管理器之cnpm…

【PTA】浙软2020年上机题目自测

个人学习记录&#xff0c;代码难免不尽人意。 在PTA买了浙软2020年的保研上机真题时光机做了做&#xff0c;20年的明显要比19年的难一些&#xff0c;我用了差不多2小时多一点做完了&#xff0c;最后得分90分&#xff0c;在当年排名26左右。下面是4道题和我的做法 7-1 Standard…

[MySQL]查看数据库大小

查看库大小 例如&#xff1a;查看当前MySQL中数据总量超过2GB的库&#xff1a; select table_schema as 数据库,table_rows as 记录数,data_size as 数据容量(GB),index_size as 索引容量(MB) from (selecttable_schema,sum(table_rows) as table_rows,sum(truncate(data_leng…