leetcode-------栈相关的简单4题---------------(16)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/baidu_36697353/article/details/88050782

首先,我们将栈相关的,难度为简单的4道题,一起做了,然后汇总成博客的形式。一起练一波,过完简单的题目之后,然后我们再去过中等的题目。

232.用栈实现队列

使用栈实现队列的下列操作:

  • push(x) -- 将一个元素放入队列的尾部。
  • pop() -- 从队列首部移除元素。
  • peek() -- 返回队列首部的元素。
  • empty() -- 返回队列是否为空。

示例:

MyQueue queue = new MyQueue();

queue.push(1);
queue.push(2);  
queue.peek();  // 返回 1
queue.pop();   // 返回 1
queue.empty(); // 返回 false

说明:

  • 你只能使用标准的栈操作 -- 也就是只有 push to toppeek/pop from topsize, 和 is empty 操作是合法的。
  • 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
  • 假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)。
class MyQueue(object):

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.list = []

        

    def push(self, x):
        """
        Push element x to the back of queue.
        :type x: int
        :rtype: None
        """
        self.list.append(x)
        

    def pop(self):
        """
        Removes the element from in front of queue and returns that element.
        :rtype: int
        """
        return self.list.pop(0)
       

    def peek(self):
        """
        Get the front element.
        :rtype: int
        """
        return self.list[0]

    def empty(self):
        """
        Returns whether the queue is empty.
        :rtype: bool
        """
        return not self.list

        


# Your MyQueue object will be instantiated and called as such:
# obj = MyQueue()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.peek()
# param_4 = obj.empty()

496. 下一个更大元素 I

给定两个没有重复元素的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。找到 nums1 中每个元素在 nums2 中的下一个比其大的值。

nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 大的元素。如果不存在,对应位置输出-1。

示例 1:

输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: [-1,3,-1]
解释:
    对于num1中的数字4,你无法在第二个数组中找到下一个更大的数字,因此输出 -1。
    对于num1中的数字1,第二个数组中数字1右边的下一个较大数字是 3。
    对于num1中的数字2,第二个数组中没有下一个更大的数字,因此输出 -1。

示例 2:

输入: nums1 = [2,4], nums2 = [1,2,3,4].
输出: [3,-1]
解释:
    对于num1中的数字2,第二个数组中的下一个较大数字是3。
    对于num1中的数字4,第二个数组中没有下一个更大的数字,因此输出 -1。

注意:

  1. nums1nums2中所有元素是唯一的。
  2. nums1nums2 的数组大小都不超过1000。

这道题,读了一会题,感觉好绕。我理解的就是,数组1中的元素,在数组2中,然后其右边的这个数是否比它大。如果是,然后比它大的那个数,如果不是,返回-1.

class Solution(object):
    def nextGreaterElement(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        """
        re = []
        for i in range(len(nums1)):
            next_ = nums2.index(nums1[i])
            if next_ < len(nums2)-1:
                next_ +=1
            if nums2[next_] > nums1[i] :
                re.append(nums2[next_])
            else:
                re.append(-1)
        return re
    

提交后,发现有一个用例没有通过。

解答错误

输入

[1,3,5,2,4]
[6,5,4,3,2,1,7]

输出

[7,-1,-1,-1,-1]

预期结果

[7,7,7,7,7]

这个用例,说明,不是右边一个,是指只有nums2右边有比它大的数,那么就返回这个数,否则才返回-1.所以需要重新修改代码。

class Solution(object):
    def nextGreaterElement(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        [4,1,2]
        [1,3,4,2]
        """
        re = []
        for i in range(len(nums1)):
            next_ = nums2.index(nums1[i])
            if next_ < len(nums2)-1:
                for j in range(next_+1,len(nums2)):
                    if nums2[j]> nums1[i]:
                        re.append(nums2[j])
                        break
                else:
                    re.append(-1)
            else:
                re.append(-1)

        return re

成功

显示详情 

执行用时: 116 ms, 在Next Greater Element I的Python提交中击败了16.23% 的用户

内存消耗: 10.9 MB, 在Next Greater Element I的Python提交中击败了0.00% 的用户

进行下一个挑战:

感觉耗时太高了。然后看了别人的算法优化了一下:

class Solution(object):
    def nextGreaterElement(self,nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        """
        for i in range(len(nums1)):
            position = nums2.index(nums1[i])
            for j in range(position + 1, len(nums2)):
                if nums2[j] > nums1[i]:
                    nums1[i] = nums2[j]
                    break
            if nums1[i] == nums2[position]:
                nums1[i] = -1
        return nums1

成功

显示详情 

执行用时: 108 ms, 在Next Greater Element I的Python提交中击败了17.39% 的用户

内存消耗: 11.1 MB, 在Next Greater Element I的Python提交中击败了0.00% 的用户

感觉差不多呢,然后看了一种新方法,用单调栈

def nextGreaterElement(nums1, nums2):
    stack = []  # 单调栈
    dic = {}  # 字典

    # 利用单调栈,将num2中所有值的对应更大元素存入dic
    for i in nums2:
        while stack and i > stack[-1]:  # 此处用while而不是if
            dic[stack.pop()] = i
        stack.append(i)

    # 遍历num1,根据dic中的记录改写num1
    for j in range(len(nums1)):
        nums1[j] = dic.get(nums1[j], -1)

    return nums1

成功

显示详情 

执行用时: 56 ms, 在Next Greater Element I的Python提交中击败了66.38% 的用户

内存消耗: 11 MB, 在Next Greater Element I的Python提交中击败了0.00% 的用户

进行下一个挑战:

682. 棒球比赛 

你现在是棒球比赛记录员。
给定一个字符串列表,每个字符串可以是以下四种类型之一:
1.整数(一轮的得分):直接表示您在本轮中获得的积分数。
2. "+"(一轮的得分):表示本轮获得的得分是前两轮有效 回合得分的总和。
3. "D"(一轮的得分):表示本轮获得的得分是前一轮有效 回合得分的两倍。
4. "C"(一个操作,这不是一个回合的分数):表示您获得的最后一个有效 回合的分数是无效的,应该被移除。

每一轮的操作都是永久性的,可能会对前一轮和后一轮产生影响。
你需要返回你在所有回合中得分的总和。

示例 1:

输入: ["5","2","C","D","+"]
输出: 30
解释: 
第1轮:你可以得到5分。总和是:5。
第2轮:你可以得到2分。总和是:7。
操作1:第2轮的数据无效。总和是:5。
第3轮:你可以得到10分(第2轮的数据已被删除)。总数是:15。
第4轮:你可以得到5 + 10 = 15分。总数是:30。

示例 2:

输入: ["5","-2","4","C","D","9","+","+"]
输出: 27
解释: 
第1轮:你可以得到5分。总和是:5。
第2轮:你可以得到-2分。总数是:3。
第3轮:你可以得到4分。总和是:7。
操作1:第3轮的数据无效。总数是:3。
第4轮:你可以得到-4分(第三轮的数据已被删除)。总和是:-1。
第5轮:你可以得到9分。总数是:8。
第6轮:你可以得到-4 + 9 = 5分。总数是13。
第7轮:你可以得到9 + 5 = 14分。总数是27。

注意:

  • 输入列表的大小将介于1和1000之间。
  • 列表中的每个整数都将介于-30000和30000之间。

如果定义一个变量sum=0来求和的话,会非常麻烦,这道题栈的知识很简答, 用一个list去装数据,就很好求

class Solution(object):
    def calPoints(self, ops):
        """
        :type ops: List[str]
        :rtype: int
        """
        stack = []
        for s in range(len(ops)):       
            if ops[s] == '+':
                stack.append(stack[-1]+stack[-2])     
            elif ops[s] == 'D':
                stack.append(2*stack[-1])
            elif ops[s] == 'C':
                stack.pop()
            else:
                stack.append(int(ops[s]))      
        return sum(stack)
                

503. 下一个更大元素 II

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

示例 1:

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

这道题我感觉和上面的那道题差不多。然后就用单调栈做了。

class Solution(object):
    def nextGreaterElements(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        stack = []
        dic = {}
        for i in nums:
            while stack and i > stack[-1]:
                dic[stack.pop()] = i
            stack.append(i)
        for j in range(len(nums)):
            nums[j] = dic.get(nums[j],-1)
        return nums
        

但是有一个测试用例没有过:

解答错误

输入          [5,4,3,2,1]

输出          [-1,-1,-1,-1,-1]

预期结果   [-1,5,5,5,5]

这个测试用例能叫题目中所说的’循环数组‘吗? 最后一个元素的下一个元素是数组的第一个元素我以为是循环数组是他给的那样   【1,2,1】  再比如  【1,2,5,6,7,1】  .

后面查资料知道了原来循环数组,可以把它想象成一个圆环,所以需要循环比较。

思路:

首先想到用单调栈来解决,但是此时输入的是一个循环数组而且其中包含了重复元素,对于循环数组的问题一个常见的处理手段就是通过余数,然后将数组的长度扩大两倍即可。对于包含重复元素,其实并没有什么,它并不能决定我们是建立一个严格的栈还是非严格的栈。关键问题在于如果我们找不到下一个更大的元素的话要怎么办?对于例子中的2,由于是循环数组,所以我们循环一圈后必然会碰到同样的2,此时我们要不要弹出栈顶元素呢?当然不要。基于此,我们可以确定我们的单调栈是一个非严格单调减的栈。剩下的部分就很简单了.

class Solution(object):
    def nextGreaterElements(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        stack = []
        res = [-1] * len(nums)
        for i in range(len(nums)*2):
            while stack and nums[stack[-1]]<nums[i%len(nums)]:
                res[stack.pop()] = nums[i%len(nums)]
            stack.append(i%len(nums))

        return res

取余运算

('0%10=', 0)
('1%10=', 1)
('2%10=', 2)
('3%10=', 3)
('4%10=', 4)
('5%10=', 5)
('6%10=', 6)
('7%10=', 7)
('8%10=', 8)
('9%10=', 9)

猜你喜欢

转载自blog.csdn.net/baidu_36697353/article/details/88050782