【程序员面试金典】面试题 16.16. 部分排序

【程序员面试金典】面试题 16.16. 部分排序

题目描述

描述:给定一个整数数组,编写一个函数,找出索引m和n,只要将索引区间[m,n]的元素排好序,整个数组就是有序的。注意:n-m尽量最小,也就是说,找出符合条件的最短序列。函数返回值为[m,n],若不存在这样的m和n(例如整个数组是有序的),请返回[-1,-1]。

示例:

输入: [1,2,4,7,10,11,7,12,6,7,16,18,19]
输出: [3,9]

提示:

0 <= len(array) <= 1000000

解题思路

思路1:最直观的想法是,先将原有数组a备份为b,然后使用sort对a进行排序,再一次遍历比较a和b不同的元素,并将对应的下标加入到res数组中,遍历完成后,如果res数组长度小于等于1,则不满足要求,直接返回{-1,-1},反之返回res第一个元素和最后一个元素即可。

class Solution {
public:
    vector<int> subSort(vector<int>& array) {
        //备份一份整数数组
        vector<int> b(array);
        //对原有整数数组排序
        sort(array.begin(),array.end());
        //存储结果元素 第一个和最后一个即为所求
        vector<int> res;
        //遍历排序后的数组和原有数组找到第一个不同和最后一个不同
        for(int i=0;i<array.size();i++)
        {
            if(array[i]!=b[i])
                //注意这里是下标
                res.push_back(i);
        }
        //区间至少两个
        if(res.size()<=1)
            return {-1,-1};
        return {res[0],res.back()};
    }
};

思路2:默认数组是按照升序排序的,如果数组中出现元素a[i],其左边存在比其大的数,或者其右边存在比其小的数,那么a[i]就需要参与到排序中去。现在所需要寻找的元素,一是最靠右的那个数r(该数满足其左边存在比其大的数),二是最靠左的那个数i(该数满足其右边存在比其小的数)。寻找r的方法是:从左向右遍历,先寻找当前最大的并更新为maxx,然后一旦找到右边比maxx小的数,则更新r为i;寻找l的方法是:从右向左遍历,先寻找当前最小的并更新为minx,然后一旦找到左边比minx大的数,则更新l为i。其中l和r默认为-1,最后返回{l,r}即可。

vector<int> subSort(vector<int>& array) 
{
   //寻找最靠右的一个数(满足左边存在大于它的数)
   //寻找最靠左的一个数(满足右边存在小于它的数)
   int n=array.size();
   int maxx=INT_MIN;
   int minx=INT_MAX;
   //默认l和r均为-1
   int l=-1,r=-1;
   //正向遍历寻找最靠右的一个数
   for(int i=0;i<n;i++)
   {
      //左边寻找当前最大的 寻找右边比当前最大数小的
      if(array[i]<maxx)
         r=i;
      else
         maxx=array[i];
   }
   //反向遍历寻找最靠左的一个数
   for(int i=n-1;i>=0;i--)
   {
      //右边寻找当前最小的 寻找左边比当前最小数大的
      if(array[i]>minx)
        l=i;
      else
        minx=array[i];
   }
   return {l,r};
}

总结:理解如何寻找最靠右的那个数r(该数满足其左边存在比其大的数)和最靠左的那个数i(该数满足其右边存在比其小的数)。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值