力扣练习题(2024/4/21)

      贪心算法是一种在每一步选择中都做出最佳选择的算法方法。它以尽量减少当前问题的复杂性为目标,在每一步选择中尽可能取得最佳结果。尽管贪心算法不能保证总是获得最优解,但在许多情况下,它是解决问题的高效方法。

1分发饼干

如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为 摆动序列 。第一个差(如果存在的话)可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。

  • 例如, [1, 7, 4, 9, 2, 5] 是一个 摆动序列 ,因为差值 (6, -3, 5, -7, 3) 是正负交替出现的。

  • 相反,[1, 4, 7, 2, 5] 和 [1, 7, 4, 5, 5] 不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。

子序列 可以通过从原始序列中删除一些(也可以不删除)元素来获得,剩下的元素保持其原始顺序。

给你一个整数数组 nums ,返回 nums 中作为 摆动序列 的 最长子序列的长度 。

示例 1:

输入:nums = [1,7,4,9,2,5]
输出:6
解释:整个序列均为摆动序列,各元素之间的差值为 (6, -3, 5, -7, 3) 。

示例 2:

输入:nums = [1,17,5,10,13,15,10,5,16,8]
输出:7
解释:这个序列包含几个长度为 7 摆动序列。
其中一个是 [1, 17, 10, 13, 10, 16, 8] ,各元素之间的差值为 (16, -7, 3, -3, 6, -8) 。

示例 3:

输入:nums = [1,2,3,4,5,6,7,8,9]
输出:2

提示:

  • 1 <= nums.length <= 1000
  • 0 <= nums[i] <= 1000

思路:

为了满足更多的小孩,就不要造成饼干尺寸的浪费。

大尺寸的饼干既可以满足胃口大的孩子也可以满足胃口小的孩子,那么就应该优先满足胃口大的。

这里的局部最优就是大饼干喂给胃口大的,充分利用饼干尺寸喂饱一个,全局最优就是喂饱尽可能多的小孩

  1. 首先,对孩子的胃口数组和饼干数组进行排序,这样可以更容易地进行匹配。

  2. 接着,从胃口最大的孩子开始向前遍历,同时从饼干数组的最后一个位置向前匹配。这样做的原因是贪心地选择最大的孩子和最大的饼干进行匹配。

  3. 在遍历的过程中,如果当前的饼干满足当前孩子的胃口,则将结果计数加一,并将饼干的下标向前移动一位。

  4. 最终返回结果,即能满足的孩子数量。

代码:

class Solution {
public:int findContentChildren(vector<int>& g, vector<int>& s) {// 将孩子数组和饼干数组按照从小到大排序sort(g.begin(), g.end()); // 按照孩子的胃口排序sort(s.begin(), s.end()); // 按照饼干的大小排序int index = s.size() - 1; // 饼干数组的下标int result = 0; // 结果,能满足孩子的数量// 从胃口最大的孩子开始匹配饼干for (int i = g.size() - 1; i >= 0; i--) { // 遍历胃口// 如果还有饼干可用且当前饼干满足当前孩子的胃口if (index >= 0 && s[index] >= g[i]) { // 遍历饼干result++; // 满足一个孩子index--; // 使用了一个饼干,下标减一}}return result; // 返回满足孩子的数量}
};

2 摆动序列

如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为 摆动序列 。第一个差(如果存在的话)可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。

  • 例如, [1, 7, 4, 9, 2, 5] 是一个 摆动序列 ,因为差值 (6, -3, 5, -7, 3) 是正负交替出现的。

  • 相反,[1, 4, 7, 2, 5] 和 [1, 7, 4, 5, 5] 不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。

子序列 可以通过从原始序列中删除一些(也可以不删除)元素来获得,剩下的元素保持其原始顺序。

给你一个整数数组 nums ,返回 nums 中作为 摆动序列 的 最长子序列的长度 。

示例 1:

输入:nums = [1,7,4,9,2,5]
输出:6
解释:整个序列均为摆动序列,各元素之间的差值为 (6, -3, 5, -7, 3) 。

示例 2:

输入:nums = [1,17,5,10,13,15,10,5,16,8]
输出:7
解释:这个序列包含几个长度为 7 摆动序列。
其中一个是 [1, 17, 10, 13, 10, 16, 8] ,各元素之间的差值为 (16, -7, 3, -3, 6, -8) 。

示例 3:

输入:nums = [1,2,3,4,5,6,7,8,9]
输出:2

提示:

  • 1 <= nums.length <= 1000
  • 0 <= nums[i] <= 1000

思路:

解题关键点

关键在于识别何时一个数的加入可以形成摆动序列中的一个新的"峰"或"谷"。

分析步骤

  1. 初始化变量:

    • curDiff 记录当前差值(当前元素与下一个元素的差)。
    • preDiff 记录前一个差值,用于与当前差值比较。
    • result 初始化为1,至少有一个元素时,我们认为摆动序列至少为1。
  2. 遍历序列计算差值:

    • 对于数组中的每个元素(除最后一个),计算与下一个元素的差值 curDiff
    • 这个差值用来确定当前元素的位置是在上升趋势还是下降趋势。
  3. 判断摆动条件:

    • 当 preDiff <= 0 && curDiff > 0 时,说明之前是下降趋势或持平,现在转为上升,当前元素形成一个谷。
    • 当 preDiff >= 0 && curDiff < 0 时,说明之前是上升趋势或持平,现在转为下降,当前元素形成一个峰。
    • 只有在这两种情况下,result 才会增加,因为我们找到了一个摆动。
  4. 更新 preDiff

    • 只有在确定当前差值确实形成了一个新的摆动时,才更新 preDiff。这是为了确保不遗漏任何一个可能的摆动点。

特殊情况处理

  • 如果数组元素全相同或者整体趋势一致(只上升或只下降),摆动序列的长度将为1,因为没有真正的摆动发生。

代码:

class Solution {
public:int wiggleMaxLength(vector<int>& nums) {if (nums.size() <= 1) return nums.size(); // 如果数组长度小于等于1,直接返回数组长度int curDiff = 0; // 当前一对差值int preDiff = 0; // 前一对差值int result = 1;  // 记录峰值个数,序列默认序列最右边有一个峰值for (int i = 0; i < nums.size() - 1; i++) { // 遍历数组curDiff = nums[i + 1] - nums[i]; // 当前一对差值// 出现峰值if ((preDiff <= 0 && curDiff > 0) || (preDiff >= 0 && curDiff < 0)) {result++; // 峰值个数加一preDiff = curDiff; // 更新前一对差值}}return result; // 返回峰值个数}
};

3 最大子数组和

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

子数组

是数组中的一个连续部分。

示例 1:

输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。

示例 2:

输入:nums = [1]
输出:1

示例 3:

输入:nums = [5,4,-1,7,8]
输出:23

提示:

  • 1 <= nums.length <= 105
  • -104 <= nums[i] <= 104

贪心算法思路:

贪心算法是一种通过每一步的局部最优选择来达到全局最优解的算法。在解决最大子数组和问题时,贪心算法的思路是尝试寻找以每个元素结尾的所有子数组中和最大的那个子数组。具体来说,算法每次遍历数组中的一个元素,并更新两个变量:当前子数组的和 count 和最大子数组和 result。在遍历的过程中,如果当前子数组的和 count 大于 result,就更新 result 为 count,表示发现了一个更大的子数组和。如果 count 小于等于0,意味着当前子数组对最终结果没有正面贡献,因此将 count 重置为0,重新开始计算下一个子数组的和。

代码:

class Solution{
public:int maxSubArray(std::vector<int>& nums){int result = INT32_MIN; // 初始化结果为最小整数int count = 0; // 用于存储当前子数组的和for (int i = 0; i < nums.size(); i++){count += nums[i]; // 将当前元素添加到子数组和中if (count > result) { // 如果当前子数组的和大于之前记录的最大和result = count; // 更新最大和为当前子数组的和}if (count <= 0) {count = 0; // 如果当前子数组和小于等于0,说明对结果无贡献,将当前和重置为0}}return result; // 返回最大和}
};

4. 买卖股票的最佳时机 II

给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。

在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。

返回 你能获得的 最大 利润 。

示例 1:

输入:prices = [7,1,5,3,6,4]
输出:7
解释:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3 。总利润为 4 + 3 = 7 。

示例 2:

输入:prices = [1,2,3,4,5]
输出:4
解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。总利润为 4 。

示例 3:

输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 交易无法获得正利润,所以不参与交易可以获得最大利润,最大利润为 0 。

提示:

  • 1 <= prices.length <= 3 * 104
  • 0 <= prices[i] <= 104

贪心算法思路:

  1. 寻找价格上涨的区间:

    • 从第二天开始遍历价格数组,比较当前价格与前一天价格。
    • 如果当前价格高于前一天价格,则将当前价格区间标记为上涨区间的一部分。
    • 如果当前价格低于等于前一天价格,则结束上涨区间,将上涨区间的利润加入总利润中,并将下一个区间的起始点设为当前价格。
  2. 计算利润:

    • 对于每个上涨区间,利润等于区间终点的价格减去起始点的价格。
    • 如果某个上涨区间的利润为正,则将其加入总利润中。
  3. 累加利润:

    • 将每个上涨区间的利润累加起来,得到最大利润。

假如第 0 天买入,第 3 天卖出,那么利润为:prices[3] - prices[0]。

相当于(prices[3] - prices[2]) + (prices[2] - prices[1]) + (prices[1] - prices[0])。

此时就是把利润分解为每天为单位的维度,而不是从 0 天到第 3 天整体去考虑!

那么根据 prices 可以得到每天的利润序列:(prices[i] - prices[i - 1]).....(prices[1] - prices[0])。

如图:

股票价格71510364
每天利润-645-73-2
每天只收集正利润4+5+3=12

代码:

#include <vector>
#include <algorithm> // 用于使用 max 函数class Solution {
public:int maxProfit(std::vector<int>& prices) {int result = 0; // 初始化最大利润为0for (int i = 1; i < prices.size(); i++) {// 计算当前交易的利润,如果利润为负数,则取0,表示不进行交易result += std::max(prices[i] - prices[i - 1], 0);}return result; // 返回最大利润}
};

5 指定日期的产品价格

产品数据表: Products

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| product_id    | int     |
| new_price     | int     |
| change_date   | date    |
+---------------+---------+
(product_id, change_date) 是此表的主键(具有唯一值的列组合)。
这张表的每一行分别记录了 某产品 在某个日期 更改后 的新价格。

编写一个解决方案,找出在 2019-08-16 时全部产品的价格,假设所有产品在修改前的价格都是 10 。

以 任意顺序 返回结果表。

结果格式如下例所示。

示例 1:

输入:
Products 表:
+------------+-----------+-------------+
| product_id | new_price | change_date |
+------------+-----------+-------------+
| 1          | 20        | 2019-08-14  |
| 2          | 50        | 2019-08-14  |
| 1          | 30        | 2019-08-15  |
| 1          | 35        | 2019-08-16  |
| 2          | 65        | 2019-08-17  |
| 3          | 20        | 2019-08-18  |
+------------+-----------+-------------+
输出:
+------------+-------+
| product_id | price |
+------------+-------+
| 2          | 50    |
| 1          | 35    |
| 3          | 10    |
+------------+-------+

思路:

  1. 第一个部分:选择在2019年8月16日之后有价格变动的产品

    • 使用select语句选择产品ID和价格。价格设为10作为一个默认值。
    • 使用group by语句按产品ID进行分组。
    • 使用having子句筛选出变动日期在2019年8月16日之后的记录。
    • 结果是每个产品最早的价格变动记录,并将价格设为10。
  2. 第二个部分:选择在2019年8月16日之前最后一次价格变动的产品

    • 使用子查询找到在2019年8月16日之前最后一次价格变动的产品及其最新价格。
    • 子查询中,先筛选出变动日期在2019年8月16日之前的记录,然后按产品ID分组,并选取每组中的最大变动日期。
    • 主查询中,根据子查询结果选择对应产品的最新价格。

通过以上两个部分的联合查询,可以得到在指定日期前后的产品价格变动情况,其中在指定日期之后没有变动的产品价格设为10,而在指定日期之前有变动的产品则显示最新价格。

代码:

-- 选择在2019年8月16日之后有价格变动的产品,并取每个产品最早的变动日期,价格设为10
select product_id,  -- 选择产品ID10 as price  -- 将价格设为10
from products  -- 选择产品表
group by product_id  -- 按产品ID分组
having min(change_date) > '2019-08-16'  -- 筛选出变动日期在2019年8月16日之后的记录union -- 选择在2019年8月16日之前最后一次价格变动的产品,并取最新价格
select product_id,  -- 选择产品IDnew_price as price  -- 取最新价格
from products  -- 选择产品表
where (product_id, change_date) in (-- 子查询:选择在2019年8月16日之前最后一次价格变动的产品select product_id,  -- 选择产品IDmax(change_date)  -- 取最大的变动日期from products  -- 选择产品表where change_date <= '2019-08-16'  -- 筛选出变动日期在2019年8月16日之前的记录group by product_id  -- 按产品ID分组)

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

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

相关文章

centos安装服务及设置自启动

centos安装redis及设置自启动 centos安装redis及设置自启动redis安装脚本redis启动脚本chkconfig设置开机自启动systemctl设置开机自启动nginx脚本mysql脚本mongodb脚本rabbitmq脚本java服务脚本删除日志定时任务 centos安装redis及设置自启动 redis安装脚本 进入 /opt/redis…

Python数据挖掘项目开发实战:利用神经网络破解验证码

注意&#xff1a;本文的下载教程&#xff0c;与以下文章的思路有相同点&#xff0c;也有不同点&#xff0c;最终目标只是让读者从多维度去熟练掌握本知识点。 下载教程&#xff1a;Python数据挖掘项目开发实战_用神经网络破解验证码_编程案例解析实例详解课程教程.pdf 使用Pyth…

【小浩算法cpp实现】删除链表的倒数第n个节点

目录 前言我的思路思路一思路二 我的代码 前言 今天继续学习算法&#xff0c;前几天觉得数组的题还是简单了&#xff0c;今天换个链表的&#xff0c;没想到也是考研期间学过的比较经典的链表算法&#xff0c;就当复习cpp啦&#xff01; 我的思路 首先我觉得大家应该已经懂了…

pdf在线免费转word网站推荐,纯免费、不注册

pdf在线免费转word网站推荐&#xff0c;纯免费、不注册 pdf在线免费转word文档 https://orcc.online/pdf 不限次数、免费不需要注册&#xff0c;上传之后过一段时间&#xff0c;右侧就会出现转换完成的word文档。 其他工具 时间戳转换 https://orcc.online/timestamp Base…

Nature Climate Change 高引文章 | 朴世龙院士团队等揭示全球变绿及其驱动因子

植被是生物圈的关键组成部分&#xff0c;对调节地球气候和提供生态系统服务具有重要作用。陆地植被生长对全球变化非常敏感。工业革命以来&#xff0c;大气二氧化碳浓度升高、气候变暖、氮沉降增加和土地利用变化等因子&#xff0c;通过复杂的生物物理化学过程&#xff0c;对陆…

Dubbo 集群容错常见方案

Failover Cluster&#xff1a; 失败自动切换&#xff0c;自动重试其它服务器&#xff08;默认&#xff09; Failfast Cluster&#xff1a; 快速失败&#xff0c;立即报错&#xff0c;只发起一次调用 Failsafe Cluster&#xff1a; 失败安全&#xff0c;出现异常时&#xff0c…

Android开发——Fragment

Demo fragment_blank.xml <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_pare…

韩顺平Java | C25 JDBC和连接池(中)

JDBCUtils工具类 JDBC操作中获取连接和释放资源操作可以封装到JDBCUtils工具类中。 工具类代码 完成mysql的连接和关闭资源 package com.hspedu.jdbc.utils; import java.io.FileInputStream; import java.io.IOException; import java.sql.*; import java.util.Properties…

数据结构--双向链表

在讲双向链表之前&#xff0c;我们先了解一下链表的分类&#xff1a; 链表的结构⾮常多样&#xff0c;主要分为带头与不带头、单向与双向、循环与不循环。三个种类可以任意搭配&#xff0c;所以总共可以形成八种链表&#xff0c;但是最常用的是单向不带头不循环链表和双向带头循…

如何从零开始创建React应用:简易指南

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

经典目标检测YOLOV1模型的训练及验证

1、前期准备 准备好目录结构、数据集和关于YOLOv1的基础认知 1.1 创建目录结构 自己创建项目目录结构&#xff0c;结构目录如下&#xff1a; network CNN Backbone 存放位置 weights 权重存放的位置 test_images 测试用的图…

Tomcat命令行窗口、IDEA中Tomcat控制台 中文乱码问题解决方案

Tomcat出现中文乱码问题 打开Tomcat文件夹下的conf/logging.properties文件&#xff0c;将下图位置中的编码由UTF-8全部替换成GBK 然后重启Tomcat服务器&#xff0c;问题解决 Intellij IDEA启动Tomcat服务器控制台出现中文乱码 解决方案非常简单&#xff0c;按照下图设置控制…

【MySQL】表的增删改查

目录 前言&#xff1a; 新增&#xff08;Create&#xff09;&#xff1a; 查询&#xff08;Retrieve&#xff09;&#xff1a; 别名&#xff1a; 去重&#xff1a;DISTINCT 排序&#xff1a;ORDER BY &#xff1a; 条件查询&#xff1a;WHERE &#xff1a; 分页查询&am…

c++实数排序

例&#xff1a;数的三次方跟 描述&#xff1a;给定一个浮点数n&#xff0c;求它的三次方根。 输入描述&#xff1a;一个浮点数 输出描述&#xff1a;问题的解 保留6位小数 #include<bits/stdc.h> using namespace std; double n,eps1e-8; bool check (double x){retu…

【新手入门必看】从零开始学指针

我使用VS CODEMSYS2的编译环境进行学习&#xff0c;想使用VS CODE进行C/C代码编写的小伙伴参考这篇文章进行环境配置VS Code 配置 C/C 编程运行环境&#xff08;保姆级教程&#xff09; 一、指针的引入 指针地址 #include <stdio.h>int main() {int a 10;printf(&quo…

Git的操作和使用

一、基本操作 1、创建git本地仓库 &#xff08;1&#xff09;创建目录&#xff1a;mkdir gitcode &#xff08;2&#xff09;进入目录&#xff1a;cd gitcode/ &#xff08;3&#xff09;查询目录内容&#xff1a;ls &#xff08;4&#xff09;在当前目录下创建git本地仓库…

java算法day3

移除链表元素设计链表翻转链表两两交换链表中的结点 移除链表元素 ps&#xff1a;有时候感觉到底要不要写特判&#xff0c;你想到了就写&#xff01;因为一般特判有一劳永逸的作用。 解法有两种&#xff0c;一种是不用虚拟头结点&#xff0c;另一种就是用虚拟头结点。 这里我…

QT中表格控件使用

一、QTableView表头设置样式 //控件样式 QString setcolor"QHeaderView{""border:0px solid #ffffff;""outline:0px;""background:#000000;""}""QHeaderView::section:horizontal:first{""border:1px solid…

React-基础语法学习

1、教程&#xff1a;井字棋游戏 本教程将引导你逐步实现一个简单的井字棋游戏&#xff0c;并且不需要你对 React 有任何了解。在此过程中你会学习到一些编写 React 程序的基本知识&#xff0c;完全理解它们可以让你对 React 有比较深入的理解。 1.1、教程分成以下几个部分&am…

3D感知生成对抗网络的高斯溅射解码器

Gaussian Splatting Decoder for 3D-aware Generative Adversarial Networks 3D感知生成对抗网络的高斯溅射解码器 Florian Barthel1, 2  Arian Beckmann1  Wieland Morgenstern1  Anna Hilsmann1  Peter Eisert1,2 Florian Barthel 1, 2 阿里安贝克曼Wieland晨星Anna Hils…