当前位置:网站首页>Leetcode+ 81 - 85 monotone stack topic
Leetcode+ 81 - 85 monotone stack topic
2022-07-04 20:53:00 【Sauerkraut】
Search rotation sort array II
Algorithm tags : Array 、 Two points search
Refer to the first 33 topic
LeetCode+ 31 - 35 Two sub topics _ Xiaoxuecai's blog -CSDN Blog
( Linear scanning ) O(n)
Refer to the explanation of the question
LeetCode 81 Search in Rotated Sorted Array II - AcWing
This problem is similar to that in No 33 topic , The difference is that the array in this problem may contain the same elements .
At present, the worst time complexity of the conceivable dichotomy is O(n), So we simply did linear scanning ^^
Time complexity analysis : The whole array is scanned only once , So time complexity is O(n)
class Solution {
public:
bool search(vector<int>& nums, int target) {
for (auto &v : nums)
if (v == target)
return true;
return false;
}
};
With the first 33 The difference between questions is that there may be repeated elements , That means that the number before the first paragraph and after the second paragraph may be the same
If there is no such situation , We can divide the dividing point in two , Why can we divide the dividing point in two ?
Suppose no first paragraph is equal to the next one , Suppose there is no later paragraph , There will be later numbers that are strictly smaller than the number in the first paragraph , This property is binary , Any property with duality can distinguish the dividing point
But this question does not have the above properties , It is possible that the latter paragraph is equal to the first paragraph , The nature of this paragraph is not tenable
When we are about a x, If it is greater than or equal to nums[ 0 ] Words , It is not certain whether it is at the beginning or at the end , So we can't divide , In order to make it binary, we can do some optimization , But in the worst case, the time complexity cannot be optimized
Just delete the part with the same beginning or end first , Only the end is the same as the beginning , Just delete the end , So you can split in two
Because the deleted scores are repeated in the front , The deleted numbers are all duplicate numbers , So it will not affect our judgment , It does not affect the accuracy of the answer , But after we delete all the repeated numbers , We can split in two , Into the first 33 Problem solving
The question requires to judge whether the given target value exists in the array . If nums
There is a target value in target
, Then return to true
, Otherwise return to false
.
The idea is to remove the equal parts of the back and the front first , After removing it, divide it into two parts first , After the dividing point , Divide it in two in each paragraph , Just see if there is an answer
while (R >= 0 && nums[R] == nums[0]) R- -; Will execute n Time , The worst case of time complexity is O( n )
class Solution {
public:
bool search(vector<int> &nums, int target) {
// Array is empty and returns false
if(nums.empty()) return false;
// Define the end point
int R = nums.size() - 1;
// When the end point is greater than 0 also nums[R] If it is equal to the beginning, you can delete this number
while (R >= 0 && nums[R] == nums[0]) R--;
// If you find that the entire array has been deleted All numbers of the whole array are the same
if (R < 0)
// Because all numbers are the same, they are equal to nums[0], Just judge nums[0] Is it equal to target That's all right.
return nums[0] == target;
// Delete the same part at the end Into the first 33 Problem solving
// Bisection dividing point
int l = 0, r = R;
while (l < r) {
int mid = l + r + 1 >> 1;
// If nums[mid] Greater than or equal to nums[0] Explain that it is in the first half The dividing point to be bisected is actually the last number that satisfies this property
if (nums[mid] >= nums[0]) l = mid;
else r = mid - 1;
}
// Judge after getting the dividing point target Which part does it belong to , If target >= nums[0], explain target It's in the first part , The range of two points should be from 0 To the dividing point just now
if (target >= nums[0]) l = 0,r = r;
// Otherwise, the interval of two points is in the right half It should be the next position of the dividing point just now
else l++, r = R;
// Last in l ~ R Between two points to find whether there is target This value is enough
while (l < r) {
int mid = l + r >> 1;
// Two points greater than or equal to target The first number of , If nums[mid] > = target, Explain that the answer is mid Left or mid Location
if (nums[mid] >= target) r = mid;
else l = mid + 1;
}
// Finally, judge nums[r] Is it equal to target That's all right.
return nums[r] == target;
}
};
Delete duplicate elements from the sort list II
Algorithm tags : Linked list 、 Double pointer
Give us a sort list , Sorting a linked list means that all the same elements are arranged together , Delete all repeated elements inside , As long as an element appears twice or more, delete it , Note that it is not to delete the repeated elements, leaving only one
Simulation example
3 Repeat , Two 3 All have to be deleted , Similar to ancient punishment " Continuous sitting "
Sorting a linked list means that all adjacent elements are next to each other , When traversing to the position of a certain point , I want to see if the length of the continuous equal part behind this point is greater than 1
Look at the back 4 How many are there , If 4 The number of is greater than 1, You need to delete the following , If 4 There are only 1 There is no need to delete , The next thing to do is to count how many there are 4, It can be regarded as a double pointer algorithm , Scan the current continuous equal segment , First, use a pointer to record the first number of a paragraph , Another pointer , Start with the second number in the next paragraph , As long as the second pointer and the first pointer point to the same number , Just move the second pointer back one bit , Until it is not equal or empty . When we move to 5 Found that 5 and 4 Dissimilarity , Stop moving , In this way, we can find this equal interval
This section is equal to an interval that is left closed and right open , How to judge how many elements there are in the current paragraph ?
Just judge whether the next position of the first pointer is equal to the second pointer , If there is only one number in this paragraph , The next position of the first pointer is the position of the second pointer , If there is more than one number in this paragraph , It means that the next position of the first pointer and the position of the second pointer are not equal , In this way, we can judge how many elements there are in this paragraph
① If there is only one number in the next paragraph , Just move the first pointer back one bit
② If there is more than one number in the next paragraph , You need to delete all the numbers in the next paragraph , Put the last node's next Just point to the second pointer directly
Every time the pointer points to the previous number of a certain section , The previous number of the head node should also exist , In order to facilitate the establishment of a virtual head node
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
auto dummy = new ListNode(-1);
// Of the virtual head node next The pointer is equal to the real head node
dummy->next = head;
// Define a pointer to the front of a paragraph
auto p = dummy;
// When there is the next paragraph Find the second one in the next paragraph every time
while(p->next) {
auto q = p->next->next;
// The second number of the next paragraph exists and the value of the second number of the next paragraph is equal to the value of the first number of the next paragraph The second pointer goes straight back
while(q && q->val == p->next->val) q = q->next;
// If the first pointer next If it's equal to q Words , Explain that there is only one number in the next paragraph
if(p->next->next == q)
//p Just go to the next position
p = p->next;
// Otherwise, delete the next paragraph
else p->next = q;
}
// Return to the next position of the virtual head node
return dummy->next;
}
};
Delete duplicate elements from the sort list
Algorithm tags : Linked list
Because the linked list is sorted , Explain that all the same elements are arranged together
For the same number in a certain paragraph , In order to keep only one , We stipulate that the first item should be reserved for the same number of each item
Simulation example
There's a lot of 2, Choose only the first 2, There's a lot of 3, Choose only the first 3 , Next, let's see how to store the first number of each paragraph . First , The first number of the whole linked list must be stored , Because it must be the first number of a certain paragraph , After the first number is stored , Then traverse from the second number of the whole linked list , Each time, judge whether the number currently traversed is the first number of this section , If it is the first number in this paragraph , Just move this node , If not, skip
How to judge whether the current number is the first number in this paragraph ?
Just check whether the current number is the same as the last number of the linked list we stored , You can find 2 != 1, So this 2 It must be the first 2, Put this 2 Move over here , Continue to look back at the next number 2 == 2, explain 2 It already exists , Just skip . Let's look at 3, because 3 != 2, So this 3 Is the first 3, Put this 3 Move over here , And so on , At last, just add a null pointer
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
// It's empty Returns an empty
if(!head) return head;
// use cur Represents the last node of the new linked list
auto cur = head;
// Traverse from the second point of the original linked list
for(auto p = head->next; p; p = p->next)
// Each time, compare whether the current node is the same as the last node of the new linked list
if(p->val != cur->val)
// If not, move the current point to the new linked list cur Last p It is the last point of the new linked list
cur = cur->next = p;
// Finally, point the tail node of the new linked list to null
cur->next = NULL;
// Return to the new list
return head;
}
};
The largest rectangle in the histogram
Algorithm tags : Stack 、 Array 、 Monotonic stack
Classic application of monotone stack
Monotone stack can solve the problem of finding the subscript of the number smaller than it on the left of each number in a sequence , Next, let's see if there is such a model in some topics
The title gives n Vertical bar , this n The width of each vertical bar is 1, The height is given ,n A vertical bar is located on a coordinate axis , The two are close together , We need to find out the largest rectangle in the vertical bar ?
This topic is actually an enumeration plus optimization problem , Next, think about how to enumerate all the situations , When enumerating, you can enumerate many things , You can enumerate the left and right boundaries of the rectangle , It takes two cycles , The time complexity is O(n^2), When the left and right boundaries are determined , Look at the maximum height
We can also consider enumerating the upper boundary of the rectangle , The upper boundary of the rectangle must be stuck by a vertical line , It can't be in the middle of the vertical line , For example, we want to take a look at 5 This side is a rectangle with an upper boundary , What is the maximum left and right width → What is the maximum left ? What is the maximum right ?
The left and right boundaries are the positions of the first lower rectangle on the left and right sides of this vertical line
The area is the height of the upper boundary multiplied by the distance between the left and right boundaries
We can enumerate the upper boundary , After we enumerate the upper boundary , Just ask for each upper boundary , With this side as the upper boundary , Count to the left the farthest place ? And the farthest place to the right ?
The farthest place to the left is actually to find out the position of the column shorter than it on the left of the vertical bar
The farthest place to the right is actually to find out the position of the shorter column on the right of the vertical bar that is closest to it
Then we can find the maximum area
In essence, it is to find the position of the first smaller number on the left of each number , And the position of the first smaller number on the right of each number
Scan from left to right to find the first smaller one on the left , Then scan it from right to left , Just find the first smaller one on the right
How to use monotone stack to find the first number smaller than it on the left of each number ?
When scanning from left to right , Record all the numbers in the stack , Abscissa is its subscript , The ordinate is the size of the number , How to find the first smaller number on the left of the current number every time ? We scan from the top of the stack , Until the first number smaller than it is scanned
Optimize
On the right is the top of the stack , On the left is the bottom of the stack , Suppose the number on the left ① Than the number on the right ② Big , If there is a ratio ① It must be bigger than ② Big , and ② stay ① To the right of , as long as ② There is ,① It will not be used , You can put the ① Delete , As long as the previous number is larger than the latter , You can delete the previous number , After this deletion , This stack becomes a monotonous stack
For the current number , When looking for the first number smaller than this number , We can start from the top of the stack , As long as the stack top element is larger than the current number, it means that the stack top element is useless , The top element of the stack can be deleted , Until the element at the top of the stack is smaller than the current element , Add the current number to the stack , Plus before , The top of the stack is the number of the current number
Time complexity analysis
Each number will only enter the stack once , And it only comes out of the stack once , So the time complexity of the whole process is O(n)
class Solution {
public:
int largestRectangleArea(vector<int>& h) {
// use n Represents the maximum length
int n = h.size();
// Define the position of the first smaller number to the left of each number 、 The position of the first smaller number on the right of each number
vector<int> left(n),right(n);
// Define a stack
stack<int> stk;
// Scan each number from front to back
for(int i = 0; i < n;i ++ ) {
// When there are elements in the stack And the element at the top of the stack is greater than or equal to the current element Just delete the top element of the stack
while(stk.size() && h[stk.top()] >= h[i]) stk.pop();
// If the stack is empty , It means that any number is larger than the current one , The left boundary can take the leftmost side , Assign it to -1
if(stk.empty()) left[i] = -1;
// otherwise left[i] Equal to the subscript of the element at the top of the stack
else left[i] = stk.top();
// Insert the current element into the stack
stk.push(i);
}
// Empty the stack
stk = stack<int>();
// Scan each number from back to left
for(int i = n - 1; i >= 0; i-- ) {
// When there are elements in the stack And the element at the top of the stack is greater than or equal to the current element Just delete the top element of the stack
while(stk.size() && h[stk.top()] >= h[i]) stk.pop();
// If the stack is empty
if(stk.empty()) right[i] = n;
// otherwise right[i] Equal to the subscript of the element at the top of the stack
else right[i] = stk.top();
// Insert the current element into the stack
stk.push(i);
}
// Traverse each upper boundary Update answers
int res = 0;
// Understand in combination with boundary conditions
for(int i = 0; i < n; i++ ) {
res = max(res,h[i] * (right[i] - left[i] - 1));
cout << "h[" << i << "]:"<< h[i] << "\t" << "l[" << i
<< "]:" << left[i] << "\t" << "r[" << i << "]:" << right[i] << "\t";
}
return res;
}
};
stdout
h[0]:2 l[0]:-1 r[0]:1 h[1]:1 l[1]:-1 r[1]:6 h[2]:5 l[2]:1 r[2]:4
h[3]:6 l[3]:2 r[3]:4 h[4]:2 l[4]:1 r[4]:6 h[5]:3 l[5]:4 r[5]:6
The largest rectangle
Algorithm tags : Stack 、 Array 、 Dynamic programming 、 matrix 、 Monotonic stack
Give us one 0、1 matrix , To be in this 0、1 The largest one found in the matrix only contains 1 The rectangular , You need to consider how to enumerate all the schemes , In the worst case, you can enumerate the coordinates of the upper left corner first, and then the coordinates of the lower right corner , Then judge whether the rectangle is full of 1, The time complexity is O(n^6), Judge whether the rectangle is full of 1 You can use prefixes and optimizations , The time complexity is O(n^4)
The last question is to give us a pile of pillars , Find the largest rectangle inside the column , This question is about how to find that pile of columns
With the help of the model of the previous question , First enumerate the lower boundary of the rectangle , Then preprocess how many consecutive cells are up in each grid 1, Note that this is the maximum height , It's full of 0, The pillars are all 1, Of course, the height of the column is 0 The situation of
After the lower boundary is determined , To find the largest rectangle in this pile of columns , Just find out this pile of pillars , You can go to O(n) In time , Find out that all the lower boundaries are of this line 、 Is full of 1 Inside the rectangle 、 What is the largest rectangle ? Enumerating the lower boundary of the rectangle requires O(n) Time for , So the time complexity of the whole algorithm is O(n^2)
How to preprocess each position to count up , At most how many consecutive 1 Well ? You can pass it on
use f(i,j) Express (i,j) This grid counts up 、 At most how many consecutive 1, There are two situations
①(i,j) This grid is 0 Words , that f(i,j) Namely 0
②(i,j) This grid is not 0 Words , that f(i,j) Namely 1 +(i - 1,j) How many rectangles does this grid have up to f(i - 1,j)
class Solution {
public:
int largestRectangleArea(vector<int>& h) {
// Maximum length
int n = h.size();
// Define the position of the first smaller number to the left of each number 、 The position of the first smaller number on the right of each number
vector<int> left(n),right(n);
// Define a stack
stack<int> stk;
// Scan each number from front to back
for(int i = 0; i < n;i ++ ) {
// When there are elements in the stack And the element at the top of the stack is greater than or equal to the current element Just delete the top element of the stack
while(stk.size() && h[stk.top()] >= h[i]) stk.pop();
// If the stack is empty , It means that any number is larger than the current one , The left boundary can take the leftmost side , Assign it to -1
if(stk.empty()) left[i] = -1;
// otherwise left[i] Equal to the subscript of the element at the top of the stack
else left[i] = stk.top();
// Insert the current element into the stack
stk.push(i);
}
// Empty the stack
stk = stack<int>();
// Scan each number from back to left
for(int i = n - 1; i >= 0; i-- ) {
// When there are elements in the stack And the element at the top of the stack is greater than or equal to the current element Just delete the top element of the stack
while(stk.size() && h[stk.top()] >= h[i]) stk.pop();
// If the stack is empty
if(stk.empty()) right[i] = n;
// otherwise right[i] Equal to the subscript of the element at the top of the stack
else right[i] = stk.top();
// Insert the current element into the stack
stk.push(i);
}
// Traverse each upper boundary Update answers
int res = 0;
for(int i = 0; i < n; i++ ) res = max(res,h[i] * (right[i] - left[i] - 1));
return res;
}
int maximalRectangle(vector<vector<char>>& matrix) {
// Empty return 0
if(matrix.empty() || matrix[0].empty()) return 0;
// use n Said height use m Width
int n = matrix.size(),m = matrix[0].size();
// Use a two-dimensional array h Indicates the maximum number of consecutive 1
vector<vector<int>> h(n,vector<int>(m));
// seek h(i,j)
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++) {
//matrix[i][j]!='0'
if(matrix[i][j] == '1') {
// If i>0 Recurrence
if(i) h[i][j] = 1 + h[i - 1][j];
else h[i][j] = 1;
}
}
int res = 0;
// Enumerate the lower boundary
for(int i = 0;i < n; i++ ) res = max(res,largestRectangleArea(h[i]));
return res;
}
};
边栏推荐
- How does win11 search for wireless displays? Win11 method of finding wireless display device
- #夏日挑战赛#带你玩转HarmonyOS多端钢琴演奏
- In the face of the same complex test task, why can the elder sort out the solution quickly? Ali's ten-year test engineers showed their skills
- 接口設計時的一些建議
- 伦敦银走势图分析的新方法
- 太方便了,钉钉上就可完成代码发布审批啦!
- idea恢复默认快捷键
- Six stones programming: about code, there are six triumphs
- idea大小写快捷键
- Implementation of redis distributed lock
猜你喜欢
电脑共享打印机拒绝访问要怎么办
NLP, vision, chip What is the development direction of AI? Release of the outlook report of Qingyuan Association [download attached]
Flet教程之 04 FilledTonalButton基础入门(教程含源码)
LeetCode+ 81 - 85 单调栈专题
Form组件常用校验规则-1(持续更新中~)
Win11怎么搜索无线显示器?Win11查找无线显示器设备的方法
How to adapt your games to different sizes of mobile screen
Practical examples of node strong cache and negotiation cache
Flet教程之 05 OutlinedButton基础入门(教程含源码)
AP8022开关电源小家电ACDC芯片离线式开关电源IC
随机推荐
Practice examples to understand JS strong cache negotiation cache
强化学习-学习笔记2 | 价值学习
Selected review | machine learning technology for Cataract Classification / classification
What if the computer page cannot be full screen? The solution of win11 page cannot be full screen
In the face of the same complex test task, why can the elder sort out the solution quickly? Ali's ten-year test engineers showed their skills
Win11共享文件打不开怎么办?Win11共享文件打不开的解决方法
NLP、视觉、芯片...AI重点方向发展几何?青源会展望报告发布[附下载]
15million employees are easy to manage, and the cloud native database gaussdb makes HR office more efficient
Common verification rules of form components -1 (continuously updating ~)
Win11亮度被锁定怎么办?Win11亮度被锁定的解决方法
Flet教程之 05 OutlinedButton基础入门(教程含源码)
易周金融 | Q1保险行业活跃人数8688.67万人 19家支付机构牌照被注销
idea插件
AP8022开关电源小家电ACDC芯片离线式开关电源IC
What if the win11 shared file cannot be opened? The solution of win11 shared file cannot be opened
栈:如何实现有效括号的判断?
一文搞懂Go语言中文件的读写与创建
What should I do if my computer sharing printer refuses access
[ismb2022 tutorial] the picture shows the precision medicine of learning. Marinka zitnik, Harvard University, keynote speaker, with 87 ppt
Automatic generation of interface automatic test cases by actual operation