2021-3.24_3.25

1.给你一个整数数组 nums ,数组中共有 n 个整数。132 模式的子序列 由三个整数 nums[i]、nums[j] 和 nums[k] 组成,并同时满足:i < j < k 和 nums[i] < nums[k] < nums[j] 。
如果 nums 中存在 132 模式的子序列 ,返回 true ;否则,返回 false 。
进阶:很容易想到时间复杂度为 O(n^2) 的解决方案,你可以设计一个时间复杂度为 O(n logn) 或 O(n) 的解决方案吗?
https://leetcode-cn.com/problems/132-pattern/
思路:
1. 第一遍看答错题目了。。。所以写的是是否有123存在123,用的方法是:初始时令h=l=0,记录上一个元素,下一个比上一个大记为新的波峰,小则记为新的波谷,相等时删除该元素(我甚至都注意到了返回的iterator要–),每次查找是否存在h-l>1存在则成立,结果是123存在132。
2. 对第一个,只需要和后一个比,确定是波峰还是波谷,其余的每一个和旁边的两个值比,均大于是波峰,均小于是波谷(跳过等于的),这样就保证了每一个波谷里都有一个波峰,记录每一次的波峰和波谷为两个数组,我们要找的相当于波谷1-波峰-波谷2,而且要求波谷2>波谷1,所以遍历波谷,若存在后一个波谷大于前一个波谷的,由于其中一定存在波峰,因此存在,没有则不存在;也就是说:当不满足含有一个波峰两个波谷且后一个大于前一个时,不存在。故我们发现,不必存储波峰,只需存储每个波谷的值即可。
3. 学习到的别人的方法之单调栈:
相当于定位中间那个数,比该数小的在该数前的值可以用该数前的最小值代替,从前向后遍历一遍即可得到,最后一个值可以通过暴力便利得到。但是也可以通过从后向前扫描一遍,当该数大于对应最小值时入栈,由于是从后向前,因此最小值会变大不会变小,因此当每次复符合要求的值也就是满足j条件的值入栈之前,先查看当前栈中有无满足,大于最新的最小值的,并将小于的弹出,若栈飞空且小于当前的j则满足。知道扫描完一遍,不存在则无。
代码:

#include<vector>
class Solution {
public:
    bool find132pattern(vector<int>& nums) {
        int min[nums.size()];
        min[0]=nums[0];
        for(int i=1;i<nums.size();i++){//遍历得到0-i的最小值
            min[i]=nums[i]<min[i-1]?nums[i]:min[i-1];
        }
        stack <int> st;
        for(int i=nums.size()-1;i>0;i--){
            if(nums[i]>min[i]){//满足j,k条件,先按3找不行则按k入栈
                while(!st.empty()&&st.top()<=min[i]){//维护栈,去除不再满足的值(因为min值在变大)
                    st.pop();
                }
                if(!st.empty()&&st.top()<nums[i]){//按j查找是否存在满足条件的例子
                    return true;
                }
                st.push(nums[i]);//该数按k处理,继续向前找
            }
        }
        return false;
    }
};

2.给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器。
思路:首先第一反应动态规划,仔细一想,不对啊,区间之间没直接关系。只有暴力了,无奈去看官方解法。
官方双指针法:左右两个指针从端点向里扫描,每次移动边相对来说小的。原因:1.距离远的更好,所以从两端开始。2.产生限制的是短边,移动长边会排除可能存在的最大值,而抛弃短边一定删除的是无效值,因为现在的距离最远了。3.相等时相当于两边都是短边,因此随便移动即可,不会比现在的值要大了。该思路的应用范围:左右两边。
代码:

class Solution {
public:
    int maxArea(vector<int>& height) {
        int r=1,l=height.size();
        int result=0;
        while(r!=l){
            result=max(result,min(height[r-1],height[l-1])*(l-r));
            if(height[r-1]<height[l-1]){
                r++;
            }else{
                l--;
            }
        }
        return result;
    }
};

2.存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除链表中所有存在数字重复情况的节点,只保留原始链表中 没有重复出现 的数字。
返回同样按升序排列的结果链表。
https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list-ii/
思路:和STL的unique类似,查找,为了统一操作加上新的头结点,当下一个和下下一个存在时:1.若值相等则循环开始,首先记录相等值x,当存在下一个时,等于x则跳过,直到不等于x,停止对下一个数进行相同的操作;2.若不等则指针后移。
代码:

/**
 * 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) {
        if(!head){
            return head;
        }
        struct ListNode* first=(ListNode*)malloc(sizeof(struct ListNode));
        first->next=head;
        struct ListNode* cur = first;
        while(cur->next&&cur->next->next){
            if(cur->next->val==cur->next->next->val){
                int x=cur->next->val;
                while(cur->next&&cur->next->val==x){
                    cur->next=cur->next->next;
                }
            }else{
                cur=cur->next;
            }
        }
        return first->next;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值