求助|2023百度Java第三批笔试题
1937
2023.04.08
发布于 未知归属地

参加了百度2023Java笔试第三场,实在想不通这个题为什么只能过10%,求问是什么地方没有考虑到,以下是题目描述和我的题解,如果对代码规范有什么建议求求也指出来,谢谢!

题目描述

小红拿到了一个排列,她想知道有多少区间满足区间内部的数构成一个排列
排列的定义:1到k,每个数都出现过且恰好出现一次,被称为一个长度为k的排列。

输入描述:

有多组数据,首先输入一个正整数T,表示有T组数据(1<=T<=2)。
每组数据的第一行输入一个正整数n,代表排列的大小(1<=n<=2*10^5)。
每组数据的第二行输入n个正整数

输入示例

5
1 2 3 4 5
5
2 1 5 3 4 

输出示例

5
3

解释

对于[1,2,3,4,5],可以拆分为[1],[1,2],[1,2,3],[1,2,3,4],[1,2,3,4,5] 5个排列
对于[2,1,5,3,4],可以拆分为[1],[2,1],[2,1,5,3,4]3个排列

我的题解

import java.sql.Array;
import java.util.HashMap;
import java.util.Scanner;

public class Main {

    
    /*
     * 判断数组nums中下标从l到r的区间是否可以组成一个排列
     * 因为元素组本身就是一个排列,故数组内不可能有重复元素且从1开始
     * 所以通过遍历这个区间查找是否有元素超过排列范围来判断是否可以组成排列
     */
    public static boolean isConnected(int l,int r,int[] nums){
        boolean flag = true;
        for(int i = l;i <=r;i++){
            if(nums[i] > r-l+1) {
                flag = false;
                break;
            }
        }
        return flag;
    }
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        for(int i = 0;i < n;i++){
            //len : 排列的长度
            int len = in.nextInt();
            int [] nums = new int[len];
            //beginPos : 数组内值为1的元素的下标
            int beginPos = -1;
            //position : 一个以排列对应的数组的值为key,下标为value的哈希表,用于通过值来获取下标
            HashMap<Integer,Integer> position = new HashMap<>();
            for(int j = 0;j < len;j++){
                nums[j] = in.nextInt();
                if(nums[j] == 1) beginPos = j;
                position.put(nums[j],j);
            }
            //curValue : 当前遍历到的值,循环从值为2开始,遍历到len(排列的长度)
            int curValue = 2;
            //res : 最终的结果
            int res = 1;
            //l : 当前排列的左边界
            int l = beginPos;
            //r : 当前排列的左边界
            int r = beginPos;
            int cur ;
            if(len <=2) System.out.println(len);
            else{
                while(curValue <= len){
                    cur = position.get(curValue);
                    // 如果下一个值处在的位置是当前可以构成排列的区间内,即l < cur < r,遍历可以继续,但是不增加res
                    // 如果下一个值处在的位置是当前构成排序的左/右,判断是否可以将当前排列、下一个值以及他们中间的部分三者合并是否可以构成一个新的排列,如果可以遍历可以继续,并增加res
                    // 如果上述均不满足,结束遍历
                    if(cur > r&&isConnected(l,cur,nums)|| cur < l &&isConnected(cur,r,nums)|| cur>l&&cur<r){
                        if(cur > r ){
                            res++;
                            r = cur;
                        }
                        else if(cur < l){
                            res++;
                            l = cur;
                        }
                    }
                    else break;
                    curValue++;
                }
                // 如果通过遍历最终的结果边界达到和原排列不一致,则可以给结果+1,表示原排列也是一个子排列
                if(!(l == 0&& r ==len-1)) res++;
            }
            System.out.println(res);
        }

    }
}   
评论 (7)