150.逆波兰表达式求值
题目链接:150. 逆波兰表达式求值 - 力扣(LeetCode)
题目描述:给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。
请你计算该表达式。返回一个表示表达式值的整数。
注意:
- 有效的算符为
'+'、'-'、'*'和'/'。 - 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
- 两个整数之间的除法总是 向零截断 。
- 表达式中不含除零运算。
- 输入是一个根据逆波兰表示法表示的算术表达式。
- 答案及所有中间计算结果可以用 32 位 整数表示。
示例 1:
输入:tokens = ["2","1","+","3","*"]
输出:9
解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
示例 2:
输入:tokens = ["4","13","5","/","+"]
输出:6
解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6
示例 3:
输入:tokens = ["10","6","9","3","+","-11","*","/","*","17","+","5","+"]
输出:22
解释:该算式转化为常见的中缀算术表达式为:
((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22
提示:
1 <= tokens.length <= 104tokens[i]是一个算符("+"、"-"、"*"或"/"),或是在范围[-200, 200]内的一个整数
逆波兰表达式:
逆波兰表达式是一种后缀表达式,所谓后缀就是指算符写在后面。
- 平常使用的算式则是一种中缀表达式,如
( 1 + 2 ) * ( 3 + 4 )。 - 该算式的逆波兰表达式写法为
( ( 1 2 + ) ( 3 4 + ) * )。
逆波兰表达式主要有以下两个优点:
- 去掉括号后表达式无歧义,上式即便写成
1 2 + 3 4 + *也可以依据次序计算出正确结果。 - 适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中
栈
遍历字符串数组,用栈存放操作数,当遇到符号时,从栈中弹出两个操作数,计算后放入栈中,直到遍历结束为止
#define MAX_LEN 10001
int Op(int a,int b,char op){
if(op=='+') return a+b;
if(op=='-') return a-b;
if(op=='*') return a*b;
return a/b;
}
int evalRPN(char** tokens, int tokensSize) {
int stack[MAX_LEN];
int top=0;
for(int i=0;i<tokensSize;i++){
if(top>1&(strcmp(tokens[i],"+") == 0 || strcmp(tokens[i],"-") == 0 || strcmp(tokens[i],"*") == 0 ||strcmp(tokens[i],"/") == 0)){
stack[top-2]=Op(stack[top-2],stack[top-1],tokens[i][0]);
top--;
}else{
stack[top++]=strtol(tokens[i],NULL,0);
}
}
return stack[top-1];
}
239.滑动窗口最大值
题目链接:239. 滑动窗口最大值 - 力扣(LeetCode)
题目描述:给你一个整数数组 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] <= 1041 <= k <= nums.length
解法一、暴力求解(部分用例会超时)
#define MAX_LEN 100000
int* maxSlidingWindow(int* nums, int numsSize, int k, int* returnSize) {
int *ans=(int*)malloc(sizeof(int)*MAX_LEN);
int cnt=0;
for(int i=k-1;i<numsSize;i++){
int max = -10001;
for(int j=i-k+1;j<=i;j++){
max = nums[j]>max?nums[j]:max;
}
ans[cnt++]=max;
}
*returnSize =cnt;
return ans;
}
解法二、单调队列
设置一个单调递减的双端队列,队头元素始终存放窗口内的最大值。
如何维护单调队列配合滑动窗口移动?
pop(value):如果窗口移除的元素value等于单调队列的出口元素,那么队列弹出元素,否则不用任何操作
push(value):如果push的元素value大于入口元素的数值,那么就将队列入口的元素弹出,直到push元素的数值小于等于队列入口元素的数值为止
这样队头元素始终是当前窗口的最大值。
为了方便判断队首元素与滑动窗口的位置关系,队列中保存的是对应元素的下标。
int* maxSlidingWindow(int* nums, int numsSize, int k, int* returnSize) {
int q[numsSize];
int left = 0, right = 0;
*returnSize = 0;
int *ans=(int*)malloc(sizeof(int)*(numsSize-k+1));
for (int i = 0; i < numsSize; ++i) {
//当前元素大于队首元素,队首元素出列直到当前元素小于等于队首元素为止
while (left < right && nums[i] > nums[q[right - 1]]) {
right--;
}
//将当前元素入队
q[right++] = i;
//队尾元素不在窗口中,永久弹出并移动窗口
if (q[left] <= i - k) {
left++;
}
//滑动窗口的元素达到了k个,才可以将其加入答案数组中
if(i>=k-1){
ans[(*returnSize)++] = nums[q[left]];
}
}
return ans;
}
347.前K个高频元素
题目链接:347. 前 K 个高频元素 - 力扣(LeetCode)
题目描述:给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:
输入: nums = [1], k = 1
输出: [1]
提示:
1 <= nums.length <= 105k的取值范围是[1, 数组中不相同的元素的个数]- 题目数据保证答案唯一,换句话说,数组中前
k个高频元素的集合是唯一的
hash表+qosrt排序
先将数组排序,然后用结构体统计每个元素的频次,再对结构体数组排序,取前k个
typedef struct{
int num;
int cnt;
}Table;
//初始数组排序
int cmp1(const void *a,const void *b){
return *(int*)a - *(int*)b;
}
//结构体数组排序
int cmp2(const void *a,const void *b){
Table *ta=(Table*)a;
Table *tb=(Table*)b;
return tb->cnt - ta->cnt;
}
int* topKFrequent(int* nums, int numsSize, int k, int* returnSize) {
qsort(nums,numsSize,sizeof(int),cmp1);
int *ans=(int*)malloc(sizeof(int)*k);
int cnt=0;
Table times[numsSize];
int idx=0;
times[idx].num=nums[0];
times[idx].cnt=1;
for(int i=1;i<numsSize;i++){
if(nums[i]==nums[i-1]){
times[idx].cnt++;
}else{
times[++idx].num=nums[i];
times[idx].cnt=1;
}
}
qsort(times,idx+1,sizeof(Table),cmp2);
for(int i=0;i<k;i++){
ans[cnt++]=times[i].num;
}
*returnSize = k;
return ans;
}
1240

被折叠的 条评论
为什么被折叠?



