广联达笔试 2020 7 29

第一题


杰夫非常喜欢种草,他自己有一片草地,为了方便起见,我们把这片草地看成一行从左到右,并且第 i 个位置的草的高度是hi。
杰夫在商店中购买了m瓶魔法药剂,每瓶魔法药剂可以让一株草长高x,杰夫希望每次都能有针对性的使用药剂,也就是让当前长得最矮的小草尽量高,现在杰夫想请你告诉他在使用了m瓶魔法药剂之后,最矮的小草在这种情况下最高能到多少。

输入描述
第一行三个整数n, m, x分别表示小草的个数,魔法药剂的个数以及每瓶魔法药剂让小草长高的高度。(1≤n,m,x≤1e5)
第二行n个整数分别表示第i株小草的高度ai。(1≤ai≤1e9)

输出描述
使用了m瓶药剂之后最矮的小草的最高高度。

样例
输入
3 2 3
3 3 7
输出
6

代码

package 广联达;

import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Scanner;

public class Question1 {

    public static void main(String[] args) {
        Queue<Integer> q = new PriorityQueue<>();
        Scanner sc = new Scanner( System.in );
        int n,m,x;
        n = sc.nextInt();//n 小草的个数
        m = sc.nextInt();//m 瓶药剂
        x = sc.nextInt();//x 长高的高度
        int temp;
        for( int i = 0 ; i < n ; i ++ ){
            temp = sc.nextInt();
            q.add( temp );
        }

        for( int i = 0 ; i < m ; i ++ ){
            temp = q.poll() + x;
            q.add( temp );
        }
        System.out.println( q.poll() );
    }
}

第二题

我们希望一个序列中的元素是各不相同的,但是理想和现实往往是有差距的。现在给出一个序列A,其中难免有些相同的元素,
现在提供了一种变化方式,使得经过若干次操作后一定可以得到一个元素各不相同的序列。

这个操作是这样的,令x为序列中最小的有重复的数字,你需要删除序列左数第一个x,并把第二个x替换为2*x。

请你输出最终的序列。

例如原序列是[2,2,1,1,1],一次变换后变为[2,2,2,1],两次变换后变为[4,2,1],变换结束


输入描述
输入第一行包含一个正整数n,表示序列的长度为n。(1<=n<=50000)

第二行有n个整数,初始序列中的元素。(1<=a_i<=10^8)

输出描述
输出包含若干个整数,即最终变换之后的结果。

样例
输入
5
2 2 1 1 1
输出
4 2 1

代码:不知道代码的是否能AC,没得测了...仅记录,提供思路。现在知道了,我自己写的代码没有考虑,原数组的顺序,这个也简单,用map记录一下就行了。

package 广联达;

import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Scanner;
import java.util.Vector;

public class Question2 {

    //优先级队列
    public static Queue<Integer> q = new PriorityQueue<>();
    //优先级队列
    public static Vector<Integer> v = new Vector<>();

    使用自定义的队列,使其降序排列
    //public int compare(Integer e1, Integer e2) {
    //    return e2 - e1;
    //}

    //判断队列中的前两个数字是否相等
    public static boolean judge(){
        //如果此时数量不足,那么将优先级队列中的数直接给vector
        if( q.size() < 2 ){
            return false;
        }
        else{
            //如果此时优先级队列中的值大于1
            int first = q.poll();
            int second = q.peek();
            //这里少抛出一次
            q.add( first );
            //如果相等才进行自我合并
            if( first == second ){
                return true;
            }
            return false;
        }
    }
    public static void main(String[] args) {
        /**
         * 解题的想法,找一个可变的容器,并且其内部会自动排序
         * 那么想到了优先级队列,因为时间复杂度允许,1s,优先级队列的时间复杂度是nlogn(不超过80000就行)
         */
        Scanner sc = new Scanner( System.in );
        //n个数
        int n = sc.nextInt();
        int temp;
        for( int i = 0 ; i < n ; i ++ ){
            temp = sc.nextInt();
            q.add( temp );
        }

        //用来进行合并的两个数
        int first,second;
        while ( !q.isEmpty() ){
            //进行判断,看是否是进行合并还是进行 “ 转移 ”
            //如果返回true,说明能进行合并
            if( judge() ){
                first = q.poll();
                second = q.poll();
                q.add( first * 2 );
            }
            else{
                v.add( q.poll() );
            }
        }
        //输出vector
        System.out.print( v.get(0) );
        for( int i = 1 ; i < v.size() ; i ++ ){
            System.out.print( " " + v.get( i ) );
        }
    }
}


//第二种解法
//来自 https://www.nowcoder.com/discuss/462425?type=all&order=time&pos=&page=1&channel=666&source_id=search_all
public class Question222 {
    public static void setAdd(Set<Integer> set, Integer i) {
        //如果已经有这个数了,那么将其移除,再乘以2
        if (!set.add(i)) {
            set.remove(i);
            setAdd(set, i << 1);
        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        Integer[] array = new Integer[n];
        for (int i = 0; i < array.length; i++) {
            array[i] = scanner.nextInt();
        }
        //前面都是进行正常的输入
        LinkedHashSet<Integer> res = new LinkedHashSet<>();
        for (int i = 0; i < array.length; i++) {
            //挨个放入,如果已经有这个数字了,那么进行移除,并且乘以2
            setAdd(res, array[i]);
        }
        //后面进行正常的输出
        Iterator<Integer> iterator = res.iterator();
        while (iterator.hasNext()) {
            System.out.print(iterator.next());
            if (iterator.hasNext()) System.out.print(" ");
        }
    }

}

第三题

同同在玩积木,每个积木上都有一个独一无二的二进制数字。同同的积木有特殊的规则,只有满足规则的积木才能被垒到一起。

对于一个积木,如果积木上写的数字是a,则对于所有的写着数字b的积木,只要满足a∩b=b,其中∩代表二进制与运算,则积木b可以放到积木a的上面。每一堆积木最多仅有一个积木可以充当底座,被放在底座上的所有积木都必须满足上述关系。(只要底座和积木满足关系即可以放在一堆,不需要考虑如何码放)

同同有一只笔,只能使用一次,效果是把某一个积木上数字的某一位从0改成1或者从1改成0。请问同同最少能让积木分在几堆里。

二进制与运算的定义:对于两个数a,b,写出它们的二进制形式a0a1am...和b0b1bm,设c 为与运算的结果,则有当a0和b0同时为1 时c0为1,其他位同理。

输入描述
第一行两个数n,m(1≤m≤20,1≤n≤min(10^5,2m)),分别代表积木的数量和积木上数字对应二进制位最多有几位

第二行n个整数a1,a2,...,an(0≤ai≤2m),代表每个积木上写的二进制数字的十进制表示形式。

输入保证每个积木上的数字不重复。

输出描述
一行一个整数代表最少的堆数。

样例

输入

5 4

10 2 4 8 9

输出

2

 

提示

样例数据

五个数的二进制形式分别是

1010

0010

0100

1000

1001

首先可以吧数字为8,9的两个积木放到同一堆,数字为10,20的积木放在同一堆,然后把4的最高位从1改成0,这样就变成了0,可以与第一个积木放到同一堆。一共两堆。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值