每日练习——leetcode1047和239
目录
1047. 删除字符串中的所有相邻重复项
题目描述
给出由小写字母组成的字符串 S
,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
示例:
输入:"abbaca" 输出:"ca" 解释: 例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。
提示:
1 <= S.length <= 20000
S
仅由小写英文字母组成。
解题思路
- 获取字符串长度并初始化栈:
- 首先,使用
strlen
函数获取输入字符串s
的长度,并存储在变量len
中。 - 接着,为栈分配足够的内存空间(
len + 1
),其中额外的1个位置是为了存放字符串的结束符\0
。 - 定义了一个变量
stackTop
来追踪栈顶的位置,初始时栈为空,所以stackTop
设为0。
- 首先,使用
- 遍历字符串并处理相邻重复字符:
- 使用一个for循环来遍历输入字符串
s
中的每个字符。 - 对于每个字符
s[i]
,检查它是否与当前栈顶元素stack[stackTop - 1]
相同。 - 如果相同,说明出现了相邻的重复字符,将栈顶指针
stackTop
减1,以移除栈顶的重复字符。 - 如果不同,或者栈为空(即
stackTop
为0),则将当前字符s[i]
压入栈中,并递增栈顶指针stackTop
。
- 使用一个for循环来遍历输入字符串
- 添加字符串结束符并返回结果:
- 遍历完整个字符串后,在栈中最后一个有效字符的位置(即
stack[stackTop - 1]
之后,即stack[stackTop]
)添加一个字符串结束符\0
,这样stack
就形成了一个合法的C字符串。 - 最后,返回栈的地址,即处理后的字符串。
- 遍历完整个字符串后,在栈中最后一个有效字符的位置(即
代码实现
char* removeDuplicates(char* s) {
int len = strlen(s);
char* stack =(char *)malloc(sizeof(char)*(len + 1));
int stackTop = 0;
for (int i = 0; i < len; i++) {
if (stackTop > 0 && stack[stackTop - 1] == s[i]) {
stackTop--;
} else {
stack[stackTop++] = s[i];
}
}
stack[stackTop] = '\0';
return stack;
}
239. 滑动窗口最大值
题目描述
给你一个整数数组 nums
,有一个大小为 k
的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k
个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
示例 1:
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3 输出:[3,3,5,5,6,7] 解释: 滑动窗口的位置 最大值 --------------- ----- [1 3 -1] -3 5 3 6 7 3 1 [3 -1 -3] 5 3 6 7 3 1 3 [-1 -3 5] 3 6 7 5 1 3 -1 [-3 5 3] 6 7 5 1 3 -1 -3 [5 3 6] 7 6 1 3 -1 -3 5 [3 6 7] 7
示例 2:
输入:nums = [1], k = 1 输出:[1]
提示:
1 <= nums.length <= 105
-104 <= nums[i] <= 104
1 <= k <= nums.length
解题思路
- 定义变量:
n
:数组nums
的长度。queue
:一个数组,用于模拟队列的操作,存储窗口内可能的最大值。front
和rear
:分别表示队列的队首和队尾索引。left
和right
:分别表示当前滑动窗口的左边界和右边界。
- 窗口右移:
- 遍历数组
nums
,从right = 0
开始,直到right
达到数组末尾。
- 遍历数组
- 维护队列的单调性:
- 在每次窗口右移时,检查队列的队尾元素是否小于新元素
nums[right]
。如果是,则不断从队尾弹出元素,直到队列为空或找到不小于nums[right]
的元素。 - 然后,将新元素
nums[right]
入队。
- 在每次窗口右移时,检查队列的队尾元素是否小于新元素
- 处理窗口大小大于
k
的情况:- 当窗口的大小(
right - left + 1
)大于k
时,说明窗口的左边界需要向右移动。 - 如果队列的队首元素(即当前窗口的最大值)与
nums[left]
相等,则将队首元素出队,因为该元素已经不在窗口内了。 - 否则,将
nums[left]
更新为队首元素,即当前窗口的最大值。 - 然后,左边界
left
向右移动一位。
- 当窗口的大小(
- 返回结果:
- 遍历完成后,滑动窗口已经遍历了整个数组
nums
。 nums
数组中的每个位置left
(即每个窗口的左边界)都存储了对应窗口的最大值。- 函数返回修改后的
nums
数组,并通过returnSize
返回窗口的个数,即n - k + 1
。
- 遍历完成后,滑动窗口已经遍历了整个数组
代码实现
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* maxSlidingWindow(int* nums, int numsSize, int k, int* returnSize) {
int n = numsSize; // n 为数组 nums 的长度
int queue[n]; // 队列,用于存储当前窗口内的元素索引
int front = 0, rear = -1; // 队首和队尾索引,分别指向队列的第一个和最后一个元素
int left = 0, right = 0; // 窗口的左边界和右边界索引
// 当右边界没有达到数组末尾时,继续移动窗口
while (right < n) {
// 如果队列不为空且当前元素大于队列尾部的元素,则将队列尾部的元素出队
// 这样可以保证队列是单调递减的,即队首元素是当前窗口的最大值
while (rear >= front && nums[right] > nums[queue[rear]]) {
rear--;
}
// 将当前元素的索引入队
queue[++rear] = right;
// 右边界向右移动一位
right++;
// 当窗口大小大于 k 时,左边界需要向右移动
if (left + k <= right) {
// 如果队列的队首元素(即当前窗口的最大值)对应的索引等于左边界的索引
// 则说明这个最大值已经不在窗口内了,将其从队列中出队
if (queue[front] == left) {
front++;
}
// 将当前窗口的最大值(即队列的队首元素对应的值)存入原数组对应的位置
nums[left] = nums[queue[front]];
// 左边界向右移动一位
left++;
}
}
// 设置返回数组的大小为窗口的个数,即 n - k + 1
*returnSize = n - k + 1;
// 返回修改后的原数组,它现在包含了每个窗口的最大值
return nums;
}
原文地址:https://blog.csdn.net/2401_83138160/article/details/137695702
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!