leetcode 单调栈

leetcode300. 最长递增子序列

1. 题目

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

示例 1:
输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。

示例 2:
输入:nums = [0,1,0,3,2,3]
输出:4

示例 3:
输入:nums = [7,7,7,7,7,7,7]
输出:1

提示:
1 <= nums.length <= 2500
-104 <= nums[i] <= 104。

2. 解答

int lengthOfLIS(int* nums, int numsSize) {
    if (numsSize == 0) {
        return 0;
    }

    int *stack = (int *)malloc(sizeof(int) * numsSize);
    memset(stack, 0, sizeof(int) * numsSize);
    int top = 0;
    stack[top++] = nums[0];
    for (int i = 1; i < numsSize; i++) {
        if (nums[i] > stack[top - 1]) {
            stack[top++] = nums[i];
        } else {
            for (int j = 0; j < top; j++) {
                if (nums[i] <= stack[j]) {
                    stack[j] = nums[i];
                    break;
                }
            }
        }
    }
    return top;
}

leetcode739. 每日温度

1. 题目

请根据每日气温列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用0来代替。
例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。

提示:
气温 列表长度的范围是 [1, 30000]。每个气温的值的均为华氏度,都是在 [30, 100] 范围内的整数。

2. 解答

int* dailyTemperatures(int* temperatures, int temperaturesSize, int* returnSize) {
    if (temperaturesSize == 0) {
        *returnSize = 0;
        return NULL;
    }

    int *res = (int *)malloc(sizeof(int) * temperaturesSize);
    int *stack = (int *)malloc(sizeof(int) * temperaturesSize);
    memset(res, 0, sizeof(int) * temperaturesSize);
    memset(stack, 0, sizeof(int) * temperaturesSize);

    int top = -1;
    for (int i = 0; i < temperaturesSize; i++) {
        while (top != -1 && temperatures[i] > temperatures[stack[top]]) {
            int index = stack[top];
            top--;
            res[index] = i - index;
        }
        stack[++top] = i;
    }
    *returnSize = temperaturesSize;
    return res;
}

leetcode503. 下一个更大元素II

1. 题目

给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。

示例 1:

输入: [1,2,1]
输出: [2,-1,2]
解释: 第一个 1 的下一个更大的数是 2;
数字 2 找不到下一个更大的数;
第二个 1 的下一个最大的数需要循环搜索,结果也是 2。
注意: 输入数组的长度不会超过 10000。

2. 解答

int* nextGreaterElements(int* nums, int numsSize, int* returnSize) {
    *returnSize = numsSize;
    if (numsSize == 0) {
        return NULL;
    }

    int *stack = (int *)malloc(sizeof(int) * (2 * numsSize - 1));
    memset(stack, 0, sizeof(int) * (2 * numsSize - 1));
    int *res = (int *)malloc(sizeof(int) * numsSize);
    memset(res, -1, sizeof(int) * numsSize);
    int top = 0;
    for (int i = 0; i < 2 * numsSize - 1; i++) {
        int index = i % numsSize;
        while (top > 0 && nums[stack[top - 1]] < nums[index]) {
            res[stack[top - 1]] = nums[index];
            top--;
        }
        stack[top++] = index;
    }
    return res;
}

leetcode962. 最大宽度坡

1. 题目

给定一个整数数组 A,坡是元组 (i, j),其中 i < j 且 A[i] <= A[j]。这样的坡的宽度为 j - i。
找出 A 中的坡的最大宽度,如果不存在,返回 0 。

示例 1:
输入:[6,0,8,2,1,5]
输出:4
解释:
最大宽度的坡为 (i, j) = (1, 5): A[1] = 0 且 A[5] = 5.

示例 2:
输入:[9,8,1,0,1,9,4,0,4,1]
输出:7
解释:
最大宽度的坡为 (i, j) = (2, 9): A[2] = 1 且 A[9] = 1.

提示:
2 <= A.length <= 50000
0 <= A[i] <= 50000

2. 解答

#define max(a,b) a > b ? a : b
/*解题思路:1.创建一个单调递增栈用于维护,存放数组的索引
2.当数组当前值小于当前栈索引的数组值时,将数组当前值的索引存入栈中
3.倒序检查数组,当栈不空且数组值大于或等于栈顶索引对应的数组值时,更新最大坡度
栈顶出栈;
当索引小于最大坡度时 就没有检查的必要了,结束循环
*/
int maxWidthRamp(int* A, int ASize) {
    int *stack = (int *)malloc(sizeof(int) * (ASize + 1));
    int res = 0;
    int top = 0;
    stack[top++] = 0;
    for (int i = 1; i < ASize; i++) {
        if (A[i] < A[stack[top - 1]]) {
            stack[top++] = i;
        }
    }
    for (int i = ASize - 1; i >= 0; i--) {
        while (top > 0 && A[i] >= A[stack[top - 1]]) {
            res = max(res, (i - stack[top - 1]));
            top--;
        }
        if (top == -1) {
            break;
        }
    }
    return res;
}

剑指offer63. 股票的最大利润

1. 题目

假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少?

示例 1:
输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。

示例 2:
输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

限制:
0 <= 数组长度 <= 10^5

2. 解答

方法一:

#define MAX(a, b) (((a) > (b)) ? (a) : (b))

int maxProfit(int* prices, int pricesSize) {
    int *stack = (int *)malloc(sizeof(int) * pricesSize);
    memset(stack, 0, sizeof(int) * pricesSize);
    int top = -1;
    int res = 0;
    int temp = 0;
    if (pricesSize <= 1) {
        return 0;
    }

    for (int i = 0; i < pricesSize; i++) {
        while (top != -1 && prices[stack[top]] > prices[i]) {
            top--;
        }
        temp = prices[i] - prices[stack[0]];
        res = MAX(res, temp);
        stack[++top] = i;
    }
    return res;
}

方法二:

int maxProfit(int* prices, int pricesSize) {
    if (pricesSize <= 1) {
        return 0;
    }
    int maxprof = 0;
    int min = prices[0];
    for (int i = 0; i < pricesSize; i++) {
        if (prices[i] > min) {
            maxprof = MAX(prices[i] - min, maxprof);
        } else if (prices[i] < min) {
            min = prices[i];
        }     
    }
    return maxprof;
}

leetcode 678. 有效的括号字符串

1. 题目

给定一个只包含三种字符的字符串:( ,) 和 *,写一个函数来检验这个字符串是否为有效字符串。有效字符串具有如下规则:

任何左括号 ( 必须有相应的右括号 )。
任何右括号 ) 必须有相应的左括号 ( 。
左括号 ( 必须在对应的右括号之前 )。

  • 可以被视为单个右括号 ) ,或单个左括号 ( ,或一个空字符串。
    一个空字符串也被视为有效字符串。

示例 1:
输入: “()”
输出: True

示例 2:
输入: “(*)”
输出: True

示例 3:
输入: “(*))”
输出: True

注意:
字符串大小将在 [1,100] 范围内。

2. 解答

#define MAXSIZE 100000

bool isValidStar(int *stack, int *star, int stackLen, int starLen)
{
    if (stack[stackLen - 1] > star[starLen - 1]) {
        return false;
    }
    while (starLen > 0 && stackLen > 0) {
        if (stack[stackLen - 1] < star[starLen - 1]) {
            stackLen--;
        }
        starLen--;
    }
    return stackLen == 0;
}

bool checkValidString(char * s) {
    int len = strlen(s);
    if (len == 0) {
        return true;
    }

    int stack[MAXSIZE];
    int star[MAXSIZE];
    int stackLen = 0;
    int starLen = 0;

    for (int i = 0; s[i] != '\0'; i++) {
        if (s[i] == '(') {
            stack[stackLen++] = i;
        } else if (s[i] == ')') {
            stackLen--;
            if (stackLen < 0) {
                if (starLen > 0) {
                    starLen--;
                    stackLen++;
                } else {
                    return false;
                }   
            } 
        } else {
            star[starLen++] = i;
        }
    }
    if (!stackLen) {
        return true;
    }
    if (stackLen > starLen) {
        return false;
    }

    return isValidStar(stack, star, stackLen, starLen);
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值