2021届秋招--网易笔试--输出指定最小字典序

题目:先输入两个数n,m。然后接着输入m个数(每个数小于等于n)输出最小字典序。同时保证在输出结果中删去无关数字后可以得到输入的m个数的正确序列。

示例:

输入: 5 2

           4 2

输出:1 3 4 2 5 

解释:1 2 3 4 5是n为5时候最小的字典序,但是输出要4在2前面,所以这个输出才是最小的。

(先上代码,思路详述在下面)

public class Num2 {
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int m = in.nextInt();
        int index = 0;
        //mapIndex,key是输入的数的值,val是第几次输入的
        HashMap <Integer,Integer> mapIndex = new HashMap <Integer,Integer>();
        //mapRe,上面map的key和val相反的,这个map是要遍历的基准,因为最终序列必须包括这个顺序
        HashMap <Integer,Integer> mapRe = new HashMap <Integer,Integer>();
        while (index < m){
            ++index;
            int tempVal = in.nextInt();
            mapIndex.put(tempVal,index);
            mapRe.put(index,tempVal);
        }
        int tempRe = 1;//从1开始递增理想情况当前应该输出的数
        int outNum = 0;//已得到的正确序列的当前个数
        int mapMax = 0;//当前遍历过的map中,输入的数最大值
        StringBuffer resString = new StringBuffer();//存放结果
        //对mapRe进行遍历,因为他的key从小到大对应的val是结果中必须成立的顺序
        while (true){
            //这个if是如果mapRe中的key没有现在递增的tempRe,说明我已经就m个数的出现顺序遍历完了,剩下只要把m个数中最大的到n之间顺序补全就行了
            if(!mapRe.containsKey(tempRe)){
                while (mapMax < n-1){
                    ++mapMax;
                    resString.append(mapMax);
                    resString.append(" ");
                }
                resString.append(n);
                break;
            }
            //取到输入时候第tempRe次输入的值
            int indexMapNum = mapRe.get(tempRe);
            ++tempRe;
            //如果当前遍历到顺序的indexMapNum比之前所有的值都大,那就要补全最大值到现在的这个次序
            if (indexMapNum > mapMax){
                int i = mapMax + 1;
                while (i < indexMapNum){
                    //补全过程中,如果该值出现过(直接用key为值的map进行判断),就跳过,不出现才补全
                    if ( !mapIndex.containsKey(i)){
                        ++outNum;
                        resString.append(i);
                        resString.append(" ");
                    }
                    ++i;
                }
            }
            ++outNum;
            resString.append(indexMapNum);
            if(outNum < n)
                resString.append(" ");
            else
                break;
            mapMax = Math.max(mapMax, indexMapNum);
        }
        System.out.println(resString.toString());
    }
}

思路详述:

输入的数n是要输出1-n,输入的m个数,是要让这m个数的序列在输出中存在。所以我先把输入放了两个map,mapIndex<inputVal,index>是用来判断输出当前数是不是在输入的范围中。mapRe是前一个key,val反过来,是用来遍历的,因为他的key值1-m对应的val就是输入的顺序。

当遍历到第k个时,首先要判断k在不在mapRe中(可以用k > m,或者map判定),如果不在,说明指定的排列顺序(m个数)已经存在于输出序列中了,那么只要把 k到n之间直接从小到大补全到输出序列中就可以了。

当k在mapRe中,这个数个要判断第k个val是否比之前k-1个都大,所以用mapMax进行存储临时最大值。如果比他大,那么就需要补全mapMax+1到第k-1个对应的val,同时要注意补全的时候判断该值是否是输入的m个数(如果是,那一定还不到他的出场时间,因为他比mapMax大,说明他还要在后面才出现),如果是就跳过,不是才输出。

刚刚之所以是补全到第k-1个是因为这样少写两行代码,因为不管当前遍历值比mpMax大还是小,都要在最后补上的。区别只是如果大于mapMax需要上面的操作,小于则不需要。

数字举例:5  2  4  2

过程:mapIndex有<4,1><2,2>mapRe中有<1,4><2,2>。遍历时候第一个值是4,且之前最大的mapMax是0(初始),从0+1开始输出第一个数1,第二数2发现在mapIndex的key中,就不输出,输出下一个3,补全当前4(暂时输出为1 3 4)。遍历到下一个mapRe,val是2,小于mapMax(4),就直接补在后面(输出为1 3 4 2)。这时候发现mapRe遍历完了,那就把mapMax到n直接补全(输出为 1 3 4 2 5)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值