有效括号
Given a string containing just the characters ‘(’, ‘)’, ‘{’, ‘}’, ‘[’
and ‘]’, determine if the input string is valid.An input string is valid if:
Open brackets must be closed by the same type of brackets. Open
brackets must be closed in the correct order. Note that an empty
string is also considered valid.Example 1:
Input: “()” Output: true
// 执行用时 :0 ms, 在所有 C++ 提交中击败了100.00%的用户
// 内存消耗 :8.4 MB, 在所有 C++ 提交中击败了86.49%的用户
class Solution {
public:
bool isValid(string s) {
if(!s.length()) return 1;
stack<char> st;
for(char &i : s){//重点
switch (i){
case '(':
case '{':
case '[':
st.push(i);
break;
case ')':
if(!st.size()||st.top() != '(') return 0;
st.pop();
break;
case ']':
if(!st.size()||st.top() != '[') return 0;
st.pop();
break;
case '}':
if(!st.size()||st.top() != '{') return 0;
st.pop();
}//代码还能优化吗
}
if(!st.size()) return 1;
return 0;
}
};
#python解法 时间复杂度O(n2)
class Solution:
def isValid(self, s):
while '{}' in s or '()' in s or '[]' in s:
s = s.replace('{}', '')
s = s.replace('[]', '')
s = s.replace('()', '')
return s == ''
栈实现队列
class MyQueue {
public:
/** Initialize your data structure here. */
MyQueue() {
}
/** Push element x to the back of queue. */
void push(int x) {
s1.push(x);
}
/** Removes the element from in front of queue and returns that element. */
int pop() {
if(!s2.size()){
while(s1.size()){
s2.push(s1.top());
s1.pop();////弹出栈顶元素, 但不返回其值
}
}
int val = s2.top();
s2.pop();
return val;
}
/** Get the front element. */
int peek() {
if(!s2.size()){
while(s1.size()){
s2.push(s1.top());
s1.pop();
}
}
return s2.top();
}
/** Returns whether the queue is empty. */
bool empty() {
return !(s1.size()+s2.size());
}
private:
stack<int> s1,s2;
};
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue* obj = new MyQueue();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->peek();
* bool param_4 = obj->empty();
*/
队列实现栈
class MyStack {
public:
/** Initialize your data structure here. */
MyStack() {
}
/** Push element x onto stack. */
void push(int x) {
q1.push(x);
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
while(q1.size() != 1){
q2.push(q1.front());
q1.pop();
}
int num = q1.front();
q1.pop();
while(q2.size()){
q1.push(q2.front());
q2.pop();
}
return num;
}
/** Get the top element. */
int top() {
return q1.back();
}
/** Returns whether the stack is empty. */
bool empty() {
return !(q1.size()+q2.size());
}
private:
queue<int> q1,q2;
};
/**
* Your MyStack object will be instantiated and called as such:
* MyStack* obj = new MyStack();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->top();
* bool param_4 = obj->empty();
*/
返回数据流中第k大的元素(小顶堆)
在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征。通常采用堆或二叉搜索树来实现。
Design a class to find the kth largest element in a stream. Note that
it is the kth largest element in the sorted order, not the kth
distinct element.Your KthLargest class will have a constructor which accepts an integer
k and an integer array nums, which contains initial elements from the
stream. For each call to the method KthLargest.add, return the element
representing the kth largest element in the stream.Example:
int k = 3; int[] arr = [4,5,8,2]; KthLargest kthLargest = new
KthLargest(3, arr); kthLargest.add(3); // returns 4
kthLargest.add(5); // returns 5 kthLargest.add(10); // returns 5
kthLargest.add(9); // returns 8 kthLargest.add(4); // returns 8
- 算法一:维护一个自动排序的数组,保存整个数组中k个较大值:插入新数并自动排序后,若有k个以上的元素,则去除最小的那个即开头元素。时间复杂度N*klog(k) (插入N个数据,每次都排序)
class KthLargest {
public:
//维护一个新数组st,是数组nums中的k个较大值
KthLargest(int k, vector<int>& nums) {
for(int i : nums){
st.insert(i);
if(st.size() > k){
//如果st有k+1个元素,那么去除最小的元素,也就是开头那个
st.erase(st.begin());
}
}
K = k;//需要把k保存起来
}
int add(int val) {
st.insert(val);
//如果元素超过k个,去除最小的那个
if(st.size() > K){
st.erase(st.begin());
}
return *st.begin();
}
private:
int K;
multiset<int> st;//自动排序 允许重复
};
/**
* Your KthLargest object will be instantiated and called as such:
* KthLargest* obj = new KthLargest(k, nums);
* int param_1 = obj->add(val);
*/
- 算法二:维护一个大小为k的小顶堆。每次插入数据时,如果比堆顶元素小,则不用插入;如果大,则插入并调整堆。输出堆底最后一个元素即为第k个最大元素。时间复杂度:最好N*1,最坏N*log(2k)=N*logk(取后者)。
class KthLargest {
int K;
priority_queue<int, vector<int>, greater<int>> pq;
/*
priority_queue<Type, Container, Functional>
Type为数据类型, Container为保存数据的容器,Functional为元素比较方式。
如果不写后两个参数,那么容器默认用的是vector,比较方式默认用operator<,
也就是优先队列是大顶堆,队头元素最大,本题为小顶堆。
*/
public:
KthLargest(int k, vector<int>& nums) {
for (int n : nums) {
pq.push(n);
if (pq.size() > k) pq.pop();
}
K = k;
}
int add(int val) {
pq.push(val);
if (pq.size() > K) pq.pop();
return pq.top();
}
};
/*作者:guohaoding
链接:https://leetcode-cn.com/problems/kth-largest-element-in-a-stream/solution/703-shu-ju-liu-zhong-de-di-kda-yuan-su-liang-chong/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
*/
滑动窗口最大值(优先队列)
Given an array nums, there is a sliding window of size k which is
moving from the very left of the array to the very right. You can only
see the k numbers in the window. Each time the sliding window moves
right by one position. Return the max sliding window.Example:
Input: nums = [1,3,-1,-3,5,3,6,7], and k = 3 Output: [3,3,5,5,6,7]
Explanation:
Window position | Max |
---|---|
[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 |
- 算法一:multiset保存当前的窗口,每次将当前窗口最大值传入answer数组中。pos指针从nums数组第一个元素指向最后一个元素,每次移动过程中向集合中插入所指元素。以k=3为例,pos = 3,4…时,窗口内元素个数大于3个,需要删除最左边的数据;pos=2,3,4…时,窗口元素个数大于等于3个,可以向ans数组写入当前窗口最大值。时间复杂度n*klog(k)
注意C++中,end()不是指向最后一个元素,而是最后一个元素的后一个元素,所以返回最后一个元素时不能用*st.end()而要用*st.rbegin()
// 执行用时 :92 ms, 在所有 C++ 提交中击败了37.34%的用户
class Solution {
multiset<int> st;
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> ans;
for(int pos = 0;pos < nums.size();pos++){
if(pos >= k) st.erase(st.find(nums[pos-k]));//删除左边数据
st.insert(nums[pos]);
if(pos >= k-1) ans.push_back(*st.rbegin());
}
return ans;
}
};
- 算法二:优先队列(大顶堆)
思想同算法一,维护一个多重集合变为维护一个大顶堆,但是我不会C++优先队列中删除某特定值的元素,即删除窗口最左边的数据,挖坑。时间复杂度n*logk - 算法三:双端队列
进新元素时,干掉比自己小的元素,时间复杂度n
class Solution {
vector<int> ans;
deque<int> dequ;
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
for (int pos = 0; pos < nums.size(); pos++) {
if (!dequ.empty() && dequ.front() == pos-k) {
dequ.pop_front();
}
while (!dequ.empty() && nums[pos] > nums[dequ.back()]){
dequ.pop_back();
}
dequ.push_back(pos);
if (pos >= k-1) ans.push_back(nums[dequ.front()]);
}
return ans;
}
};