翻转数组--赛码

题目描述

给定一个长度为n的整数数组a,元素均不相同,问数组是否存在这样一个片段,只将该片段翻转就可以使整个数组升序排列。其中数组片段[l,r]表示序列a[l], a[l+1], …, a[r]。原始数组为

a[1], a[2], …, a[l-2], a[l-1], a[l], a[l+1], …, a[r-1], a[r], a[r+1], a[r+2], …, a[n-1], a[n],

将片段[l,r]反序后的数组是

a[1], a[2], …, a[l-2], a[l-1], a[r], a[r-1], …, a[l+1], a[l], a[r+1], a[r+2], …, a[n-1], a[n]。

示例
java实现

import java.util.*;

public class Main {
    
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = Integer.parseInt(scanner.nextLine());
        int[] data = new int[n];
        for(int i = 0; i < n; i++) {
            data[i] = scanner.nextInt();
        }
        //是否已经翻转过? 题干要求“是否存在这样一个片段”,即只翻转一次
        //如果hasReverse=true,即已翻转,但在向后遍历的过程中又遇到元素值比上一个小,即数组不满足一次翻转即有序
        boolean hasReverse = false;
        //用以标识是否处在 寻找这个需要翻转的“片段”,即向后找比当前元素值小的元素
        //对于1 2 5 4 3 6,(遍历从i=1开始,与前一个元素比较)如果处在i=1,i=2,处在向后找大,isLower=false;
        //如果处在i=3,即刚好5->4,此时置isLower为true;i=4时,因为4->3,所以也为true;
        boolean isLower = false;
        //记录前面递增子数组的最后一个元素的值
        int endUpper = data[0];
        //记录递减的子数组的第一个值,即这个子数组(题干中的数组片段)的最大值
        int startLower = data[0];
        //记录递减子数组的最后一个值,即子数组的最小值
        int endLower = data[0];
        String ans = "yes";
        for(int i = 1; i < n; i++) {
        	//当前元素比前一个大
            if(data[i] > data[i-1]) {
            	//isLower为true,即已经走完了递减子数组
            	//此时需要判断当前元素是否大于startLower(递减子数组的最大值)以及当前元素的前一个(递减数组的最小值)是否大于endUpper
            	//例如:1 2  5 4 3  6
            	//i=5时,data[i]=6,data[i-1]=3
            	//endUpper=2,startLower=5
            	/*如果data[i-1]=1 < endUpper=2,即data[i-1] < endUpper,翻转过去为1 2 1 4 5 6,不满足,直接返回;
            	如果data[i]=4 < startLower=5,即data[i] < startLowe,翻转过去为1 2 3 4 5 4,也不满足,直接返回*/
                if(isLower) {
                    if(data[i-1] < endUpper || data[i] < startLower) {
                        ans = "no";
                        break;
                    }
                    //标记已翻转
                    hasReverse = true;
                    //再向后遍历不再是递减,是找递增
                    isLower = false;
                }
                //正常递增,需要维护endUpper为递增的最后一个元素的值
                endUpper = data[i-1];
            }
            //当前元素比前一个小
            else {
            	//已经存在一个递减数组了,再有递减即不满足题干
                if(hasReverse) {
                    ans = "no";
                    break;
                }
                //第一个元素就开始递减需要特判
                if(i == 1) {
                	//因为在此之前不存在递增数组,所以endUpper置为极小
                    endUpper = Integer.MIN_VALUE;
                    //开始递减的子数组的第一个值为data[0]
                    startLower = data[i-1];
                    //正在递减
                    isLower = true;
                    continue;
                }
                //第一次碰到递减,维护startLower,并置isLower为true,标记 在递减
                if(!hasReverse && !isLower){
                    startLower = data[i-1];
                    isLower = true;
                }
            }
        }
        scanner.close();
        System.out.println(ans);
    }
    
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值