2019.4.5 腾讯暑期实习生常规批后台开发笔试

晚上七点半开始的笔试,两个小时,20个不定项选择题(少选不得分),3道编程题。
先说一说不定项选择题,涉及到的知识有

  1. TCP和UDP的区别(有无连接、TCP是否支持一对一,一对多,多对一,多对多)
  2. 平衡二叉树的高度以及调整
  3. 栈(入栈顺序是1,2,3、、、n,出栈顺序是s1,s2,s3,s2 = 2,问s1,s3等可能或者不可能出现的值)
  4. 最小堆的删除(删除最小堆的堆顶元素后剩下的元素的顺序是怎么样的)
  5. 进程调度算法(给出每个作业的时间以及优先级,计算哪种进程调度算法的平均执行时间为给定值)
  6. 页面置换算法(给定一个序列,求在FIFO的情况下,下一个将会被置换出去的元素是多少)
  7. LRU
  8. 二叉树的遍历(给了五棵树,判断哪些树的先序和中序遍历一致)
  9. 虚函数(没记错的话至少有五个题在这个知识点上面,很少写C++的我很慌,蒙了,感觉Java程序员凉凉)
  10. 判断时间复杂度:
    代码如下:
int fun(int n){
	if(n <= 0) return 1;
	return fun(n - 1) + 2 * fun(n - 2); 
}

大概就记得这么些了,用了45分钟吧,答得很差,今天是清明第一天,出去玩了,答题前还匆忙吃了泡面。
接下来就是三道编程题。

1. 最少硬币个数

有m个币种,每种币种数量无限,现在要求最少需要多少个硬币,才可以凑齐1到n元中的任何钱。
比如:
币种有4个币种,分别是 1 2 5 10,现在要凑1到20,那么至少需要5个硬币,分别是 1 2 2 5 10
1 = 1;
2 = 2;
3 = 2 + 1;
4 = 2 + 2;
5 = 5;
6 = 5 + 1;
。。。
20 = 10 + 5 + 2 + 2 + 1;
上例中的输入是:
4(币种个数)
1 2 5 10(每种币种是多少)
输出是最少需要的硬币个数,不存在输出-1.
借鉴同学的代码:

import java.util.Arrays;
import java.util.Scanner;

public class Coins {
    private static int[] money;
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()){
            int m = sc.nextInt(); //要凑齐1到m
            int n = sc.nextInt(); //n个币种

            money = new int[n];
            for(int i = 0; i < n; i++){
                money[i] = sc.nextInt();
            }

            Arrays.sort(money);

            int ans = cal(m, n);

            System.out.println(ans);
        }
    }

    public static int cal(int m, int n){
        int ans = 0;
        int nowTemp = 0;
        int nowIndex = 0;
        if(money[0] != 1){
            return -1;
        }
        while (nowTemp < m){
            if(nowIndex < n - 1){
                if(nowTemp < money[nowIndex+1] - 1){
                    ans++;
                    nowTemp += money[nowIndex];
                }else{
                    nowIndex++;
                }
            }else{
                ans++;
                nowTemp += money[nowIndex];
            }
        }
        return ans;
    }
}




2. 剩下的字符

给定一个字符串,只包含0和1,只要0和1或者1和0是挨着的,那么他们两就同归于尽,一起消失。求最后剩下的字符个数。
例子1:
输入为:
5(字符个数)
11010(字符串)
输出为:1
例子2:
输入为:
6
110100
输出为:0
解题思路:从字符数组开始,找两个有效(非2,看后面)字符,如果这两字符是01或者10,那么他两就消失(都变成2)。然后继续往后找,一轮结束后,查看当前字符数组除了2之外是否全是1,或者全是0,如果是的话,就说明结束了,直接输出字符数组中不是2的个数。否则继续从字符数组开始查找。
代码如下:
代码写得比较乱,改了几次才AC。
代码比较乱,思路也比较烂。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int res = 0; //最后输出的结果
        String s = scanner.next();
        char[] arr = s.toCharArray();
        int i = 0;
        while(i < n - 1){
            while(i < n - 1 && arr[i] == '2') i++; //找第一个不是2的字符
            if(i == n - 1) { //如果i已经到了n - 1,说明不能往下找了,已经到结尾了,这个时候要判断数组除了2之外是否全1或者全0
                int k = 0; //数组中2的个数
                int num = 0; //数组数字的总和
                for(int p = 0;p < n;p++){
                    if(arr[p] == '2') k++;
                    num += arr[p] - '0';
                }
                if((num - k * 2 == 0) || (num - k * 2 == n - k)) break;
                else i = 0; //如果不是的话说明数组还有01或者10这种形式,还得从头开始继续查找
                continue;
            }
            int j = i + 1;
            while(j < n && arr[j] == '2') j++;//在i的基础上继续找第二个不是2的字符
            if(j == n) { //理由同上i
                {
                    int k = 0;
                    int num = 0;
                    for(int p = 0;p < n;p++){
                        if(arr[p] == '2') k++;
                        num += arr[p] - '0';
                    }
                    if((num - k * 2 == 0) || (num - k * 2 == n - k)) break;
                    else i = 0;
                    continue;
                }
            }
            //找到了两个不是2的字符后,先判断是否是01或者10这种形式
            //如果是,则把i j都置为2,就等于消失了,然后i接着从j的下一个位置继续找
            if((arr[i] == '0' && arr[j] == '1') || (arr[i] == '1' && arr[j] == '0')){
                arr[i] = '2';
                arr[j] = '2';
                i = j + 1;
            }
            //否则说明i j 同0或者同1,i从j的位置继续找
            else i = j;
            if(i >= n - 1){//这里还需要判断,因为也有可能结束,如果没有这一步,那么可能直接在最外层while中跳出,没有判断是否还有01 或者10情况的存在
                int k = 0;
                int num = 0;
                for(int p = 0;p < n;p++){
                    if(arr[p] == '2') k++;
                    num += arr[p] - '0';
                }
                if((num - k * 2 == 0) || (num - k * 2 == n - k)) break;
                else i = 0;
            }
        }
        i = 0;
        for(;i < n;i++){
            if(arr[i] != '2') res++;
        }
        System.out.println(res);
    }
}

3. 打怪兽

一个有钱人要穿越森林,森林里面有很多怪兽,每个怪兽都有武力值,还有其价钱。这个人可以用每个怪兽对应的价钱收买怪兽,那么怪兽就会保护他。如果一个怪兽比这个人所有怪兽的武力值都大的话,那么怪兽就会攻击这个人。求问这个人穿越森林,最少花费多少钱。
示例1:
输入:
3(3个怪兽)
8 6 10(每个怪兽的武力值)
1 1 2(每个怪兽的价钱)
输出:2(买第一只和第二只就够了)
示例2:
输入:
3
8 6 9
1 2 1
输出:
2(买第一只和第三只就够了)
解题思路:
利用回溯,遇到必须要买的情况,也就是当前的怪兽的武力值比这个人拥有的怪兽的武力值之和还要大,那么必须买啊,没得商量,不然要被打死了。剩下的就是可买可不买的情况,这种情况下分两步走,买或者不买,走到最后计算每一种走法所需的金钱,比较求出最小值即可。
代码写好第一次提交,90%,还不错,我寻思边界没判断,搞了半天还不对。然后想着数字溢出?有可能,看了一眼题,怪兽武力值 >=1, <= 10 ^ 12,我寻思这已经大于int了吧,改成long,然后完整AC了。
代码如下:


import java.util.Scanner;

public class Main {
    static long min = Long.MAX_VALUE;
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt(); //怪兽个数
        long[] values = new long[n]; //每个怪兽的武力值
        int[] prices = new int[n];//每个怪兽的价钱
        for(int i = 0;i < n;i++)
            values[i] = scanner.nextLong();
        for(int i = 0;i < n;i++)
            prices[i] = scanner.nextInt();
        helper(values, prices, 0L, 0L, 0);
        System.out.println(min);
    }
    private static void helper(long[] values, int[] prices, long value, long price, int i){
        if(i >= values.length) {//遍历完所有怪兽了
            min = Math.min(min, price);
            return;
        }
        if(value > values[i]){ //可买可不买的情况
            helper(values, prices, value, price, i + 1); //不买
            value += values[i];
            price += prices[i];
            helper(values, prices, value, price, i + 1);//买
        }
        else{//必须买的情况
            value += values[i];
            price += prices[i];
            helper(values, prices, value, price, i + 1);
        }
    }
}

总结,基础知识不够扎实,有些知识点掌握不够牢固。
编程方面还有待加强,那道题别急着做,先想思路。
over。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值