1每日温度
给定一个整数数组 temperatures
,表示每天的温度,返回一个数组 answer
,其中 answer[i]
是指对于第 i
天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0
来代替。
示例 1:
输入: temperatures
= [73,74,75,71,69,72,76,73]
输出: [1,1,4,2,1,1,0,0]
示例 2:
输入: temperatures = [30,40,50,60] 输出: [1,1,1,0]
示例 3:
输入: temperatures = [30,60,90] 输出: [1,1,0]
提示:
1 <= temperatures.length <= 105
30 <= temperatures[i] <= 100
思路:
1暴力解法的思路是使用两层循环来遍历每个温度,并在内层循环中查找下一个更高温度的位置。具体来说,外层循环遍历每个温度,内层循环从当前温度的下一个温度开始遍历,直到找到一个比当前温度高的温度位置,然后计算这两个位置的距离,并将结果存储起来。
- 对于每个温度
temperatures[i]
,都需要找到下一个比它高的温度的位置。 - 使用两层循环,外层循环遍历每个温度
temperatures[i]
,内层循环从i + 1
开始遍历到数组末尾,寻找第一个比temperatures[i]
高的温度。 - 如果找到了比
temperatures[i]
高的温度,就计算这两个位置的距离,即j - i
,其中j
是内层循环找到的更高温度的位置。 - 将计算得到的距离存储到结果数组中。
代码:
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
int n = temperatures.size();
vector<int> ans(n), next(101, INT_MAX); // 存储结果数组和温度下一次出现位置的数组,初始值设为INT_MAX
for (int i = n - 1; i >= 0; --i) { // 从后往前遍历温度数组
int warmerIndex = INT_MAX; // 初始化温度升高的位置为INT_MAX
for (int t = temperatures[i] + 1; t <= 100; ++t) { // 从当前温度的下一个温度开始循环
warmerIndex = min(warmerIndex, next[t]); // 找到下一个更高温度的位置
}
if (warmerIndex != INT_MAX) { // 如果找到了更高温度的位置
ans[i] = warmerIndex - i; // 计算与下一个更高温度的位置的距离
}
next[temperatures[i]] = i; // 更新当前温度下一次出现的位置
}
return ans; // 返回结果数组
}
};
2单调栈的思路
单调栈的思路是利用栈的特性,在遍历数组时,维护一个单调递减(或递增)的栈。对于每个元素,如果栈为空或者当前元素小于等于栈顶元素,则将当前元素的索引入栈;如果当前元素大于栈顶元素,则说明找到了栈顶元素的下一个更大(或更小)的元素,此时可以进行相应的操作,如计算距离并更新结果数组。通过这样的方式,可以在一次遍历中解决问题,时间复杂度为O(n)
这道题使用单调栈的思路可以很好地解决。具体来说,我们可以遍历每个温度,维护一个单调递减的栈,栈中存储的是温度的索引。当遍历到一个温度时,如果栈为空,或者当前温度小于等于栈顶温度对应的温度,那么将当前温度的索引入栈;如果当前温度大于栈顶温度对应的温度,说明找到了栈顶温度的下一个更高温度,此时可以计算距离并更新结果数组。通过维护这样一个单调递减的栈,在一次遍历中就可以解决该问题.
代码:
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& T) {
// 递增栈,存储温度的索引
stack<int> st;
// 用于存储结果的数组,初始化为0
vector<int> result(T.size(), 0);
// 遍历每个温度
for (int i = 0; i < T.size(); ++i) {
// 如果当前栈为空或者当前温度小于等于栈顶温度
if (st.empty() || T[i] <= T[st.top()]) {
st.push(i); // 将当前温度的索引入栈
} else { // 当前温度大于栈顶温度
// 循环处理栈中温度小于当前温度的情况
while (!st.empty() && T[i] > T[st.top()]) {
// 计算当前温度与栈顶温度的距离,并更新结果数组
result[st.top()] = i - st.top();
st.pop(); // 弹出栈顶元素
}
st.push(i); // 将当前温度的索引入栈
}
}
return result;
}
};
2目标和
给你一个非负整数数组 nums
和一个整数 target
。
向数组中的每个整数前添加 '+'
或 '-'
,然后串联起所有整数,可以构造一个 表达式 :
- 例如,
nums = [2, 1]
,可以在2
之前添加'+'
,在1
之前添加'-'
,然后串联起来得到表达式"+2-1"
。
返回可以通过上述方法构造的、运算结果等于 target
的不同 表达式 的数目。
示例 1:
输入:nums = [1,1,1,1,1], target = 3 输出:5 解释:一共有 5 种方法让最终目标和为 3 。 -1 + 1 + 1 + 1 + 1 = 3 +1 - 1 + 1 + 1 + 1 = 3 +1 + 1 - 1 + 1 + 1 = 3 +1 + 1 + 1 - 1 + 1 = 3 +1 + 1 + 1 + 1 - 1 = 3
示例 2:
输入:nums = [1], target = 1 输出:1
动态规划思路:
假设加法的总和为x,那么减法对应的总和就是sum - x。
所以我们要求的是 x - (sum - x) = target
x = (target + sum) / 2
此时问题就转化为,装满容量为x的背包,有几种方法。
这里的x,就是bagSize,也就是我们后面要求的背包容量。
动态规划五部曲:
- 确定dp数组以及下标的含义
dp[j] 表示:填满j(包括j)这么大容积的包,有dp[j]种方法
2 确定递推公式
有哪些来源可以推出dp[j]呢?
只要搞到nums[i],凑成dp[j]就有dp[j - nums[i]] 种方法。
例如:dp[j],j 为5,
- 已经有一个1(nums[i]) 的话,有 dp[4]种方法 凑成 容量为5的背包。
- 已经有一个2(nums[i]) 的话,有 dp[3]种方法 凑成 容量为5的背包。
- 已经有一个3(nums[i]) 的话,有 dp[2]中方法 凑成 容量为5的背包
- 已经有一个4(nums[i]) 的话,有 dp[1]中方法 凑成 容量为5的背包
- 已经有一个5 (nums[i])的话,有 dp[0]中方法 凑成 容量为5的背包
那么凑整dp[5]有多少方法呢,也就是把 所有的 dp[j - nums[i]] 累加起来。
所以求组合类问题的公式,都是类似这种:
dp[j] += dp[j - nums[i]]
3 dp数组如何初始化
从递推公式可以看出,在初始化的时候dp[0] 一定要初始化为1,因为dp[0]是在公式中一切递推结果的起源,如果dp[0]是0的话,递推结果将都是0。
如果数组[0] ,target = 0,那么 bagSize = (target + sum) / 2 = 0。 dp[0]也应该是1, 也就是说给数组里的元素 0 前面无论放加法还是减法,都是 1 种方法。
所以本题我们应该初始化 dp[0] 为 1。
4 确定遍历顺序
nums放在外循环,target在内循环,且内循环倒序。
5 举例推导dp数组
输入:nums: [1, 1, 1, 1, 1], S: 3
bagSize = (S + sum) / 2 = (3 + 5) / 2 = 4
代码:
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int S) {
int sum = 0;
for (int i = 0; i < nums.size(); i++) sum += nums[i];
if (abs(S) > sum) return 0; // 当目标和的绝对值大于数组总和时,没有方案
if ((S + sum) % 2 == 1) return 0; // 当目标和与数组总和的差为奇数时,没有方案
int bagSize = (S + sum) / 2; // 目标和与数组总和之差的一半为背包容量
vector<int> dp(bagSize + 1, 0); // 动态规划数组,表示在当前容量下的方案数
dp[0] = 1; // 初始化容量为0时有一种方案
for (int i = 0; i < nums.size(); i++) { // 遍历数组中的每个数
for (int j = bagSize; j >= nums[i]; j--) { // 从大到小更新当前容量下的方案数
dp[j] += dp[j - nums[i]]; // 更新方案数,当前容量的方案数等于当前容量减去当前数的方案数之和
}
}
return dp[bagSize]; // 返回目标容量下的方案数
}
};
3 有趣的电影
表:cinema
+----------------+----------+ | Column Name | Type | +----------------+----------+ | id | int | | movie | varchar | | description | varchar | | rating | float | +----------------+----------+ id 是该表的主键(具有唯一值的列)。 每行包含有关电影名称、类型和评级的信息。 评级为 [0,10] 范围内的小数点后 2 位浮点数。
编写解决方案,找出所有影片描述为 非 boring
(不无聊) 的并且 id 为奇数 的影片。
返回结果按 rating
降序排列。
结果格式如下示例。
示例 1:
输入: +---------+-----------+--------------+-----------+ | id | movie | description | rating | +---------+-----------+--------------+-----------+ | 1 | War | great 3D | 8.9 | | 2 | Science | fiction | 8.5 | | 3 | irish | boring | 6.2 | | 4 | Ice song | Fantacy | 8.6 | | 5 | House card| Interesting| 9.1 | +---------+-----------+--------------+-----------+ 输出: +---------+-----------+--------------+-----------+ | id | movie | description | rating | +---------+-----------+--------------+-----------+ | 5 | House card| Interesting| 9.1 | | 1 | War | great 3D | 8.9 | +---------+-----------+--------------+-----------+ 解释: 我们有三部电影,它们的 id 是奇数:1、3 和 5。id = 3 的电影是 boring 的,所以我们不把它包括在答案中。
思路:我们可以使用 mod(id,2)=1
来确定奇数 id,然后添加 description != 'boring'
来解决问题。
MOD()
函数是用来计算两个数相除后的余数。在 SQL 中,MOD()
函数通常使用以下语法:
MOD(dividend, divisor)
其中,dividend
是被除数,divisor
是除数。该函数返回 dividend
除以 divisor
后的余数。
例如,MOD(10, 3)
将返回 1,因为 10 除以 3 后余数为 1。
代码:
select id,movie,description,rating
from cinema
where description != 'boring' and mod(id,2) = 1
order by rating desc;
4 换座位
表: Seat
+-------------+---------+
| Column Name | Type |
+-------------+---------+
| id | int |
| student | varchar |
+-------------+---------+
id
是该表的主键(唯一值)列。
该表的每一行都表示学生的姓名和 ID。
id 是一个连续的增量。
编写解决方案来交换每两个连续的学生的座位号。如果学生的数量是奇数,则最后一个学生的id不交换。
按 id
升序 返回结果表。
查询结果格式如下所示。
示例 1:
输入: Seat 表: +----+---------+ | id | student | +----+---------+ | 1 | Abbot | | 2 | Doris | | 3 | Emerson | | 4 | Green | | 5 | Jeames | +----+---------+ 输出: +----+---------+ | id | student | +----+---------+ | 1 | Doris | | 2 | Abbot | | 3 | Green | | 4 | Emerson | | 5 | Jeames | +----+---------+ 解释: 请注意,如果学生人数为奇数,则不需要更换最后一名学生的座位
思路:case 语句检查每一行:
a. 如果 ID 是奇数且等于表中的最大 ID(这意味着它是最后一个学生并且学生总数是奇数),则保持 ID 不变。
b. 如果 ID 是奇数(并且不是奇数总学生的最后一个学生),则将 ID 增加 1。
c. 如果 ID 是偶数,则将 ID 减少 1。
d. order by 子句确保结果按修改后的 id 升序排列。
代码:
select
#如果id为奇数且为最大id,则保持不变
case when id % 2 = 1 and id = (select max(id) from seat) then id
#如果id为奇数,则加1
when id % 2 = 1 then id + 1
#如果id为偶数,则减1
else id - 1
end as id,
student
#从seat表中按id顺序检索学生信息
from seat
order by id;
5变更性别
Salary
表:
+-------------+----------+ | Column Name | Type | +-------------+----------+ | id | int | | name | varchar | | sex | ENUM | | salary | int | +-------------+----------+ id 是这个表的主键(具有唯一值的列)。 sex 这一列的值是 ENUM 类型,只能从 ('m', 'f') 中取。 本表包含公司雇员的信息。
请你编写一个解决方案来交换所有的 'f'
和 'm'
(即,将所有 'f'
变为 'm'
,反之亦然),仅使用 单个 update 语句 ,且不产生中间临时表。
注意,你必须仅使用一条 update 语句,且 不能 使用 select 语句。
结果如下例所示。
示例 1:
输入: Salary 表: +----+------+-----+--------+ | id | name | sex | salary | +----+------+-----+--------+ | 1 | A | m | 2500 | | 2 | B | f | 1500 | | 3 | C | m | 5500 | | 4 | D | f | 500 | +----+------+-----+--------+ 输出: +----+------+-----+--------+ | id | name | sex | salary | +----+------+-----+--------+ | 1 | A | f | 2500 | | 2 | B | m | 1500 | | 3 | C | f | 5500 | | 4 | D | m | 500 | +----+------+-----+--------+ 解释: (1, A) 和 (3, C) 从 'm' 变为 'f' 。 (2, B) 和 (4, D) 从 'f' 变为 'm' 。
思路:
具体思路就是利用 SQL 的 case when 语句进行条件判断和更新操作。首先,我们使用 case when条件来判断每条记录中的性别字段。如果性别为 ‘m’,则将其更新为 ‘f’;如果性别为其他值(假设只有 ‘m’ 和 ‘f’ 两种可能性),则将其更新为 ‘m’。这样就完成了性别的更新操作。
代码:
update salary
set sex = (case sex
when 'm' then 'f' #如果性别为男性,则改为女性
else 'm' #否则改为男性
end);