单调栈:最短无序连续子数组

梦想不抛弃苦心追求的人,只要不停止追求,你们会沐浴在梦想的光辉之中。再美好的梦想与目标,再完美的计划和方案,如果不能尽快在行动中落实,最终只能是纸上谈兵,空想一番。只要瞄准了大方向,坚持不懈地做下去,才能够扫除挡在梦想前面的障碍,实现美好的人生蓝图。单调栈:最短无序连续子数组,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

单调栈:最短无序连续子数组

问题:

在这里插入图片描述

1.排序法( O(nlogn))

思路:

建立一个新数组,其元素为原数组的升序排列,比较两数组,得到第一个和最后一个不匹配的元素,它们都需重新排列,且是子数组的边界

代码:

class Solution {
public:
    int findUnsortedSubarray(vector<int>& nums) {
        int n=nums.size();
        vector<int> sort_array( n );
        sort_array=nums;
        int i;
        int j;
        sort( sort_array.begin(),sort_array.end() );
        for( i=0;i<n;i++ )
        {
            if( sort_array[i]!=nums[i] )
                break;
        }
        for( j=n-1;j>0;j-- )
        {
            if( sort_array[j]!=nums[j] )
                break;
        }
        return max( j-i+1,0 );
    }
};

2.单调栈( O(n))

思路:

为寻找无序子数组中最小元素与最大元素在已排好序的整体数组中应处于的位置,使用单调栈。

先从头遍历数组并将数组元素的下标入栈,若出现当前需入栈的元素值小于栈顶元素所对应的元素值,我们需找到该元素应处于的正确位置。设该元素的正确位置对应的下标为k。将k赋为st.top(),并退栈,若该元素仍比st.top()对应的元素小,重复上述操作。最后得到的k即为该元素正确位置对应的下标。在一次遍历后,找到最小的k值,即为无序子数组的下边界。

设栈为st,在遍历完成后用st = stack() 清空栈。

再从尾部向前遍历数组,按上述相同的方法进行,若出现当前需入栈的元素值大于栈顶元素所对应的元素值,设其正确位置对应的下标为j。不断pop直至当前元素值不大于栈顶元素所对应的值。在一次遍历后,找到最大的j值,即为无序子数组的上边界。

当下边界大于上边界时,返回j-k+1,否则返回0

代码:

class Solution {
public:
    int findUnsortedSubarray(vector<int>& nums) {
        int n=nums.size();
        stack<int> st;
        int i;
        int k=n-1;
        int j=0;
        for( i=0;i<n;i++ )
        {
            while (!st.empty() && nums[st.top()] > nums[i])
            {
                k = min(k, st.top());
                st.pop();
            }
            st.push(i);
        }
        st = stack<int>();
        for( i=n-1;i>=0;i-- )
        {
            while (!st.empty() && nums[st.top()] < nums[i])
            {
                j = max(j, st.top());
                st.pop();
            }
            st.push(i);
        }
        return (j > k) ? j - k + 1 : 0;
    }
};

3.不使用额外存储空间的方法( O(n))

思路:

设数组为nums[n]

从数组头开始遍历,若出现nums[i]<nums[i-1],则nums[i]不处于其正确位置,找到不处于其正确位置的最小nums[i],设为min,此即为无序子数组的最小值。再从数组头进行第二次遍历,找到第一个大于此最小值的值,该值所处的位置即为最小值的正确位置,也即为子数组的下边界。

从数组尾开始遍历,同理,若出现nums[i]>nums[i+1],则nums[i]不处于其正确位置,找到不处于其正确位置的最大nums[i],设为max,此即为无序子数组的最大值。再从数组尾进行第二次遍历,找到第一个小于此最大值的值,该值所处的位置即为最大值的正确位置,也即为子数组的上边界。

代码:

class Solution {
public:
    int findUnsortedSubarray(vector<int>& nums) {
        int n=nums.size();
        int i;
        int min_num=nums[n-1];
        int max_num=nums[0];
        int k;
        int j;
        for( i=1;i<n;i++ )
            if( nums[i]<nums[i-1] )
            {
                min_num=min(nums[i],min_num);
            }
        for( i=n-2;i>=0;i-- )
            if( nums[i]>nums[i+1] )
            {
                max_num=max(nums[i],max_num);
            }
        for( i=0;i<n;i++ )
            if( nums[i]>min_num )
                break;
        k=i;
        for( i=n-1;i>=0;i-- )
            if( nums[i]<max_num )
                break;
        j=i;
        return ( j-k>0? j-k+1:0 );
    }
};

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/153872.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!