目录
1047. 删除字符串中的所有相邻重复项
题目描述
解题思路
代码实现
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 31 [3 -1 -3] 5 3 6 7 31 3 [-1 -3 5] 3 6 7 51 3 -1 [-3 5 3] 6 7 51 3 -1 -3 [5 3 6] 7 61 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;  
}