Leetcode (Likou) brushing notes (c++) [Part 2]

leetcode (c++, python) [Part 1]
leetcode (c++) [medium]

Reference brush question link code random thoughts

monotonic stack

739. Daily temperature

Act 1: Violence
beyond the time limit

class Solution {
    
    
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
    
    
        vector<int> result(temperatures.size(),0);
        for(int i=0;i<temperatures.size();i++){
    
    
            for(int j=i+1;j<temperatures.size();j++){
    
    
                if(temperatures[j]>temperatures[i]){
    
    
                    result[i]=j-i;
                    break;
                }
            }
        }
        return result;
    }
};

Method 2: Monotonic stack
The stack must first determine whether it is empty before taking the top element of the stack

class Solution {
    
    
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
    
    
        // 递增栈  栈内放元素下标,因为要计算距离
        stack<int> st;
        vector<int> result(temperatures.size(), 0);
        st.push(0);//先放入第一个元素
        for(int i=1;i<temperatures.size();i++){
    
    
            if(temperatures[i]<=temperatures[st.top()]){
    
    
                st.push(i);
            }
            else{
    
    
                while(!st.empty()&&temperatures[i]>temperatures[st.top()]){
    
    //判断空必须放在前面
                    result[st.top()]=i-st.top();
                    st.pop();
                }
                st.push(i);
            }           
        }
        return result;
    }
};

496. The Next Greater Element I

Method 1: Monotonic stack
Using a monotonic stack for nums2, you can get the next larger element of each element in nums2, and judge whether nums2[i] appears in nums1 in the loop, because nums1 is a subset of nums2.
Writing method 1: Use unordered_map to record the element value and subscript of nums1
Using umap is easy to find

class Solution {
    
    
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
    
    
        vector<int> result(nums1.size(),-1);
        stack<int> st;//存放nums的元素值
        unordered_map<int, int> umap;
        for(int i=0;i<nums1.size();i++){
    
    
            umap[nums1[i]]=i;//key为元素值,value为下标
        }
        st.push(nums2[0]);
        for(int i=1;i<nums2.size();i++){
    
    
            while(!st.empty()&&nums2[i]>st.top()){
    
    
                if(umap.find(st.top())!=umap.end()){
    
    //说明在nums1中找到了
                    result[umap[st.top()]]=nums2[i];
                }
                st.pop();
            }
            st.push(nums2[i]);
        }
        return result;

    }
};

Writing method 2: directly use the find function to search nums1
and subtract iterators to obtain the distance

class Solution {
    
    
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
    
    
        vector<int> result(nums1.size(),-1);
        stack<int> st;//存放nums的元素值
        st.push(nums2[0]);
        for(int i=1;i<nums2.size();i++){
    
    
            while(!st.empty()&&nums2[i]>st.top()){
    
    
                auto it=find(nums1.begin(),nums1.end(),st.top());
                if(it!=nums1.end()){
    
    //说明在nums1中找到了
                    result[it-nums1.begin()]=nums2[i];
                }
                st.pop();
            }
            st.push(nums2[i]);
        }
        return result;

    }
};

503. The Next Greater Element II

Method 1: Monotonic stack

class Solution {
    
    
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
    
    
        //使用单调栈
        stack<int> st;
        vector<int> new_nums;
        //拼接成一个新数组
        for(int i=0;i<nums.size();i++){
    
    
            new_nums.push_back(nums[i]);
        }
        for(int i=0;i<nums.size();i++){
    
    
            new_nums.push_back(nums[i]);
        }
        vector<int> result(new_nums.size(),-1);
        st.push(0);
        for(int i=1;i<new_nums.size();i++){
    
    
            while(!st.empty()&&new_nums[i]>new_nums[st.top()]){
    
    
                result[st.top()]=new_nums[i];
                st.pop();
            }
            st.push(i);
        }
        result.resize(new_nums.size()/2);
        return result;
    }
};

42. Catching rainwater

Method 1: Double pointer. The time complexity is O(n^2). The space complexity is O(1). Find by column to find the height of the shortest column between the tallest column on the left and the tallest column on the right.
time limit exceeded

class Solution {
    
    
public:
    int trap(vector<int>& height) {
    
    
        //使用双指针
      int result=0;
      for(int i=0;i<height.size();i++){
    
    
          if(i==0||i==height.size()-1) continue;//第一个和最后一个不接水
          int right_maxh=0;
          for(int j=i+1;j<height.size();j++){
    
    
              //找右边最大值
              if(height[j]>right_maxh) right_maxh=height[j];
          }
          int left_maxh=0;
          for(int j=0;j<i;j++){
    
    
              //找i左边最高值
              if(height[j]>left_maxh) left_maxh=height[j];
          }
          int h=min(left_maxh,right_maxh)-height[i];
          if(h > 0) result+=h;

      }  
      return result;
    }
};

insert image description hereMethod 2: Dynamic Programming

Current column rainwater area: min (the highest height of the left column, record the highest height of the right column) - current column height.
In order to get the highest height on both sides, double pointers are used to traverse, and each column is traversed to both sides, which is actually repeated calculation. We record the highest height on the left (including the current position) of each position in an array (maxLeft), and record the highest height on the right (including the current position) in an array (maxRight). This avoids double calculation, which uses dynamic programming.
The reason for including the current location: If the highest height is the same as the current location, it means that water cannot be filled, and the calculated area is 0, which does not affect the subsequent calculations, and there is no need to judge the size

class Solution {
    
    
public:
    int trap(vector<int>& height) {
    
    
        //使用动态规划计算每个位置左边和右边最高柱子高度
        if (height.size() <= 2) return 0;
        vector<int> maxLeft(height.size(), 0);//maxLeft[i]:i位置前(包括i)的最高柱子
        vector<int> maxRight(height.size(), 0);//maxRight[i]:i位置后(包括i)的最高柱子
        maxLeft[0]=height[0];
        int size=height.size();
        for(int i=1;i<size;i++){
    
    
           maxLeft[i]=max(height[i],maxLeft[i-1]);
        }
        maxRight[size-1]=height[size-1];
        for(int i=size-2;i>=0;i--){
    
    
            maxRight[i]=max(height[i],maxRight[i+1]);
        }

        int result=0;
        for(int i=0;i<size;i++){
    
    
            int h=min(maxLeft[i],maxRight[i])-height[i];
            result+=h;
        }
        return result;
    }
};

Method 3: Monotonic stack
Since it is a horizontal calculation, it is necessary to skip columns with the same height, otherwise the calculation of the area will be repeated

class Solution {
    
    
public:
    int trap(vector<int>& height) {
    
    
        if (height.size() <= 2) return 0; // 可以不加
        stack<int> st; // 存着下标,计算的时候用下标对应的柱子高度
        st.push(0);
        int sum = 0;
        for (int i = 1; i < height.size(); i++) {
    
    
            if (height[i] < height[st.top()]) {
    
         // 情况一
                st.push(i);
            } 
            else if (height[i] == height[st.top()]) {
    
      // 情况二
                st.pop(); // 其实这一句可以不加,效果是一样的,但处理相同的情况的思路却变了。
                st.push(i);
            } else {
    
                                    // 情况三
                while (!st.empty() && height[i] > height[st.top()]) {
    
     // 注意这里是while
                    int mid = st.top();
                    st.pop();
                    if (!st.empty()) {
    
    
                        int h = min(height[st.top()], height[i]) - height[mid];
                        int w = i - st.top() - 1; // 注意减一,只求中间宽度
                        sum += h * w;
                    }
                }
                st.push(i);
            }
        }
        return sum;
    }
};

It is also possible to pass without skipping columns of the same height, because h = min(height[st.top()], height[i]) - height[mid] is calculated as 0 for the column on the right of the column of the same height, because the The pillar on the left of the pillar is the same height as itself

class Solution {
    
    
public:
    int trap(vector<int>& height) {
    
    
        if (height.size() <= 2) return 0; // 可以不加
        stack<int> st; // 存着下标,计算的时候用下标对应的柱子高度
        st.push(0);
        int sum = 0;
        for (int i = 1; i < height.size(); i++) {
    
    
            if (height[i] <= height[st.top()]) {
    
         // 情况一
                st.push(i);
            } 
            // else if (height[i] == height[st.top()]) {  // 情况二
            //     st.pop(); // 其实这一句可以不加,效果是一样的,但处理相同的情况的思路却变了。
            //     st.push(i);
            // } 
            else {
    
                                    // 情况三
                while (!st.empty() && height[i] > height[st.top()]) {
    
     // 注意这里是while
                    int mid = st.top();
                    st.pop();
                    if (!st.empty()) {
    
    
                        int h = min(height[st.top()], height[i]) - height[mid];
                        int w = i - st.top() - 1; // 注意减一,只求中间宽度
                        sum += h * w;
                    }
                }
                st.push(i);
            }
        }
        return sum;
    }
};

84. Largest rectangle in histogram

The idea of ​​stepping on the pit: At the beginning, I thought about finding the highest pillar, and then extending from both sides of the highest pillar, but the largest rectangle does not necessarily contain the tallest pillar

Idea analysis:
We can traverse each column, and take the height of the current column i as the height of the rectangle, then the width boundary of the rectangle is to find the first column whose height is less than the current column i to the left, and find the first column to the right Bars whose height is less than the current bar i.

For each column, we calculate the rectangular area with the current column as the height as above, and finally compare the largest rectangular area.

Method 1: Dynamic programming
Use two arrays to record the boundary of the matrix when the current i is high, so that the width of the rectangle can be calculated

class Solution {
    
    
public:
    int largestRectangleArea(vector<int>& heights) {
    
    
        int size=heights.size();
        vector<int> left(size,0);//左边第一个高度小于当前柱体 i 的柱体的下标
        vector<int> right(size,0);//右边第一个高度小于当前柱体 i 的柱体的下标
        left[0]=-1;//防止while死循环
        for(int i=1;i<size;i++){
    
    //向左查找
            int t=i-1;
            while(t>=0&&heights[i]<=heights[t]){
    
    //这里有等号
                t=left[t];//这里并不是通过t--来找,t--这样比较费时
            }
            left[i]=t;
        }
        right[size-1]=size;//防止while死循环
        for(int i=size-2;i>=0;i--){
    
    //向右查找
            int t=i+1;
            while(t<size&&heights[i]<=heights[t]){
    
    
                t=right[t];
            }
            //如果右边没有比当前位置小的,那right[i]=size
            //也就是当前位置作为高时,右边的所有柱子都可以和i组成矩形
            right[i]=t;
        }
        int result=0;
        for(int i=0;i<size;i++){
    
    
            int sum=right[i]-left[i]-1;//矩形的宽
            result=max(sum*heights[i],result);
        }
        return result;
        
        
    }
};

Method 2: Monotonic
stack From the bottom of the stack to the top of the stack, the order is increasing. When entering the while loop, the next element on the top of the stack is the first height on the left that is less than i, and the stack head is the first height on the right.

class Solution {
    
    
public:
    int largestRectangleArea(vector<int>& heights) {
    
    
        //单调栈,栈底到栈顶为递增顺序
        heights.insert(heights.begin(), 0); // 数组头部加入元素0
        heights.push_back(0); // 数组尾部加入元素0
        int size=heights.size();
        stack<int> st;
        st.push(0);
        int result=0;
        for(int i=1;i<size;i++){
    
    
            if(heights[i]>=heights[st.top()]){
    
    
                st.push(i);
            }
            else{
    
    
                while(!st.empty() && heights[i]<heights[st.top()]){
    
    
                    int mid=st.top();
                    st.pop();
                    int w=i-st.top()-1;
                    result=max(result,w*heights[mid]);

                }
                st.push(i);
            }
        }
        
        return result;
    }
};

extra topic

1365. How many numbers are smaller than the current number

Law One: Violence

class Solution {
    
    
public:
    vector<int> smallerNumbersThanCurrent(vector<int>& nums) {
    
    
        vector<int> result(nums.size(),0);
        for(int i=0;i<nums.size();i++){
    
    
            for(int j=0;j<nums.size();j++){
    
    
                if(j==i) continue;
                if(nums[j]<nums[i]) result[i]++;
            }
        }
        return result;
    }
};

941. Valid Mountain Arrays

Method 1: First find the maximum value of arr, and then judge the situation on both sides

class Solution {
    
    
public:
    bool validMountainArray(vector<int>& arr) {
    
    
        if(arr.size()<3) return false;
        int max_num=0;
        int index=0;
        for(int i=0;i<arr.size();i++){
    
    
            if(max_num<arr[i]){
    
    
                max_num=arr[i];
                index=i;
            }
        }
        if(index==0||index==arr.size()-1) return false;
        for(int i=0;i<index;i++){
    
    
            if(arr[i]>=arr[i+1]) return false;
        }
        for(int i=index;i<arr.size()-1;i++){
    
    
            if(arr[i]<=arr[i+1]) return false;
        }
        return true;
    }
};

Method 2: Double pointer
Find the highest point that is strictly increasing from left to right, find the highest point that is strictly increasing from right to left, and then compare whether the two positions are equal

class Solution {
    
    
public:
    bool validMountainArray(vector<int>& arr) {
    
    
        int left=0;
        int right=arr.size()-1;
        while(left<arr.size()-1&&arr[left]<arr[left+1]){
    
    
            left++;            
        }
        while(right>0&&arr[right]<arr[right-1]){
    
    
            right--;
        }
        if(left==right&&left!=0&&right!=arr.size()-1) return true;
        return false;
    }
};

1207. Unique Occurrences

class Solution {
    
    
public:
    bool uniqueOccurrences(vector<int>& arr) {
    
    
        unordered_map<int,int> m;
        for(int i=0;i<arr.size();i++){
    
    //统计出现次数
            m[arr[i]]++;
        }
        map<int,int> count_m;//key不允许有重复的
        for(auto it=m.begin();it!=m.end();it++){
    
    
            count_m[it->second]++;
        }
        if(m.size()!=count_m.size()) return false;
        return true;
    }
};

189. Rotate array

Method 1: Set up a new array, first take the following k numbers, and then take the previous nums.size()-k numbers, but it should be noted that if k>nums.size(), k needs to be processed

class Solution {
    
    
public:
    void rotate(vector<int>& nums, int k) {
    
    
        if(nums.size()<k) k=k-k/nums.size()*nums.size();
        vector<int> result;
        for(int i=nums.size()-k;i<nums.size();i++){
    
    
            result.push_back(nums[i]);
        }
        for(int i=0;i<nums.size()-k;i++){
    
    
            result.push_back(nums[i]);
        }
        nums=result;
    }
};

Method 2: Use an in-place algorithm with a space complexity of O(1)
Note that reverse is an interval that is closed before and then opened

class Solution {
    
    
public:
    void rotate(vector<int>& nums, int k) {
    
    
        if(nums.size()<k) k=k-k/nums.size()*nums.size();
        reverse(nums.begin(),nums.end());
        reverse(nums.begin(),nums.begin()+k);
        reverse(nums.begin()+k,nums.end());
    }
};

724. Find the Center Index of an Array

1. Traversing once to find the sum sum
2. Traversing the second time to find the left half of the center index and leftSum
judgment sum-nums[i]=2*k?

class Solution {
    
    
public:
    int pivotIndex(vector<int>& nums) {
    
    
        int sum=0;
        for(int i=0;i<nums.size();i++){
    
    
            sum+=nums[i];
        }
        int k=0;
        for(int i=0;i<nums.size();i++){
    
    
            if(i==0||(i==nums.size()-1)){
    
    
                if(sum-nums[i]==0)
                return i;
            }
            else{
    
    
                k+=nums[i-1];
                if(sum-nums[i]==2*k) return i;
            }
            
        }
        return -1;
    }
};

922. Sort Arrays by Odd-Even II

Method 1: Extra space is not applicable.
The first layer while traverses each element, the second while is equivalent to traversing each element, and the time complexity is O(n^2)

class Solution {
    
    
public:
    vector<int> sortArrayByParityII(vector<int>& nums) {
    
    
        //使用双指针
        int slow=0;
        int fast=0;
        while(slow<nums.size()){
    
    
            if(nums[slow]%2==1 && slow%2==0){
    
    //只对这种情况进行交换
                fast=0;
                while(!(nums[fast]%2==0&&fast%2==1)){
    
    
                    fast++;
                    if(fast>=nums.size()) break;
                }
                if(fast>=nums.size()) break;
                //交换
                int temp=nums[slow];
                nums[slow++]=nums[fast];
                nums[fast]=temp;
            }
            slow++;
        }
        return nums;
    }
};

Optimized writing: In fact, it is consistent with the previous idea.

class Solution {
    
    
public:
    vector<int> sortArrayByParityII(vector<int>& nums) {
    
    
        int index=1;//奇数位
        for(int i=0;i<nums.size();i+=2){
    
    //遍历偶数位
            if(nums[i]%2==1){
    
    
                while(nums[index]%2!=0) index+=2;
                swap(nums[index],nums[i]);
            }
        }
        return nums;
    }
};

Each while loop fast does not necessarily start searching from the beginning, because the previous ones that need to be replaced have already been replaced, and reading it again will cause waste

class Solution {
    
    
public:
    vector<int> sortArrayByParityII(vector<int>& nums) {
    
    
        //使用双指针
        int slow=0;
        int fast=1;
        while(slow<nums.size()){
    
    
            if(nums[slow]%2==1 ){
    
    //只对这种情况进行交换
                while(nums[fast]%2!=0){
    
    
                    fast+=2;
                    if(fast>=nums.size()) break;
                }
                if(fast>=nums.size()) break;
                //交换
                swap(nums[slow],nums[fast]);
            }
            slow+=2;
        }
        return nums;
    }
};

follow-up record

21 Merge sorted linked list

/**
 * 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* mergeTwoLists(ListNode* list1, ListNode* list2) {
    
    
        ListNode* virtul_head=new ListNode(0);//虚拟头节点
        ListNode* temp=virtul_head;
        while(list1&&list2){
    
    
            //将两个链表中较小的节点加到新链表的下一个
            //类似于双指针的思想,list1和list2指向两个链表中还未加入新链表的第一个节点
            if(list1->val<list2->val){
    
    
                temp->next=list1;
                list1=list1->next;
            }
            else{
    
    
                temp->next=list2;
                list2=list2->next;
            }
            temp=temp->next;//temp指向新链表的最后一个节点
            // temp->next=NULL;

        }
        if(list1!=NULL){
    
    
            temp->next=list1;
        }
        if(list2!=NULL){
    
    
            temp->next=list2;
        }
        return virtul_head->next;
    }
};

Guess you like

Origin blog.csdn.net/qq_43050258/article/details/128824069