中兴笔试题(2018.8.28)

版权声明:版权归作者所有,转发请标明 https://blog.csdn.net/weixin_40087851/article/details/82151827

题目一:披萨问题

简介

  • 一家披萨电制作素食披萨和肉类披萨,顾客在店里下达N个订单后,订单号码会打印在他们的账单上,该店会在显示器屏幕上同时显示N个订单中的K个素食和肉类披萨订单,这家店非常有名,会收到很多订单。因此,为了避免混淆,素食披萨订单显示为正订单号,肉类披萨订单显示为负订单号,所有订单按照其在屏幕上显示的顺序派送。每当有显示的订单完成后,就将它从显示屏幕上删除,并将下一个订单添加到末尾。

  • 一对夫妇带着他们的孩子来吃披萨,孩子非常调皮,为了让他一直有事可做,他的父母要他列出店中屏幕上显示的每K个订单中第一个肉类披萨的订单号。

  • 编写一个算法,帮助他列出每派送一个订单给顾客后,屏幕上显示的第一个肉类披萨的订单号

  • 输入

    • numOfOrders,表示所下达的订单总数(N)的整数。
    • size,表示屏幕上所显示订单数(K)的整数。
    • orders,表示顾客下达的订单中素食披萨和肉类披萨订单号的订单列表。
  • 输出

    • 返回每次向顾客派送订单后,屏幕上显示的每组K个订单的第一个肉类披萨的订单号,如果屏幕未显示任何肉类披萨订单,则返回0。
  • 约束条件

    • 0 n u m O f O r d e r s 10 6
    • 0 s i z e n u m O f O r d e r s
    • 0 o r d e r [ i ] 10 9
    • 0 i n u m O f O r d e r s

示例

  • 输入

    • numOfOrders = 6
    • size = 3
    • orders = [-11,-2,19,37,64,-18]
  • 输出

    • [-11,-2,0,-18]
  • 说明

    • 第1步:第一次显示时,显示的订单号是[-11,-2,19],所以显示的第一个肉类披萨订单号是-11。
    • 第2步:第二次显示时,显示的订单号是[-2,19,37],所以显示的第一个肉类披萨订单号是-2。
    • 第3步:第三次显示时,显示的订单号是[19,37,64],由于未显示肉类披萨订单,因此输出为0。
    • 第4步:第四次显示时,显示的订单号是[37,64,-18],所以显示的第一个肉类披萨订单号是-18。

分析

  • 我们很直观的可以想到一个笨办法,即显示的K个订单中,第一个订单下标为i,那么我们可以遍历[i,i+3),查看范围内是否有负订单号,是则遇到第一个负订单号即停止,否则为0。笨办法的时间复杂度为O(N*K)。

  • 屏幕每次显示K个订单,当K个订单中的第一个订单派送后,若第一个订单为负订单号,则下一次计算出的第一个负订单号变;若第一个订单号为正订单号,则下一次计算出的第一个负订单号不变,仍为原来的负订单号。如何记录负订单号呢,我们想到了队列,队列有先进先出的优点,符合我们的要求。

  • 但同时我们注意到,如何判断队列中的负订单号应该出队列?显然,下标可以做到。当队列中的第一个负订单号下标为i时,我们遍历到i+2下标时就需要出队列操作。因此,队列中的元素应为负订单号的下标值。

  • 这种思路的时间复杂度为O(N)。

步骤

  • 前k-1个订单,直接判断订单号:若为负订单号,则下标进队列;若为正订单号,直接++i。

  • 从第K个订单起,先判断订单号:若为负订单号,则下标进队列。

  • 若队列为空,说明没有负订单号,结果为0。

  • 若队列不为空,将第一个负订单号记录到结果中,并且判断第一个负订单号是否应该出队列(下标判断)。

代码段

#include<vector>
#include<iostream>
#include<queue>

using namespace std;

vector<int> pizzaOrder(int numOfOrders, int size, int* orders) {
    vector<int> res;
    queue<int> index;
    for (int i = 0; i < numOfOrders; ++i) {
        //前k-1个订单,直接判断订单号:若为负订单号,则下标进队列
        if (i < size-1 ) {
            if(orders[i] < 0)
                index.push(i);
            continue;
        }
        //从第K个订单起,先判断订单号,若为负订单号,则下标进队列
        if (orders[i] < 0)
            index.push(i);
        //此时,若队列为空,说明没有负订单号,结果为0
        if (index.empty()) {
            res.push_back(0);
        }
        else {
            //若队列不为空,将第一个负订单号记录到结果中。判断第一个负订单号是否应该出队列
            res.push_back(orders[index.front()]);
            if(i-index.front()+1==size)
                index.pop();
        }
    }
    return res;
}

int main(int argc, char* argv[]) {
    int n = 7;
    int k = 4;
    int order[] = { 35,-42,23,-56,-84,92,39 };
    vector<int> res = pizzaOrder(n, k, order);
    getchar();
    return 0;
}

题目二:最小信号强度

简介

  • X位工程师正在进行公司的一个项目,他们需要一个媒介来互相联系和共享数据。网络管理员奥斯汀建立了一个分级网络,使得每个工程师可以进一步连接到网络中最多两名工程师。他在网络中建立了所有的全双工连接,即如果A和B之间有连接,则数据可以从A传输到B,也能从B传输到A。信号的强度在每个跃点减少一个单位。因此,为了让所有人都能收到信号,他需要确定每个工程师发送信号所需的最小强度。

  • 编写一个算法,帮助奥斯汀找出每个工程师发送信号所需的最小强度,以便网络中的每个人都能收到信号。

  • 输入

    • 该函数的输入包括一个字符串网络network,表示处于一种层级顺序的网络,该层级顺序使得索引 2 i + 1 2 i + 2 处的字符是索引 i 处字符的子项。
  • 输出

    • 返回一个非负整数列表,表示每个工程师按照层级顺序发送数据所需的最小信号强度。
  • 注意

    • 在输入字符串中用1表示一位工程师。如果某一位工程师不能进一步连接到其他工程师,则应该在其子节点位置出现0,以表示一个空的子项。
  • 约束条件

    • 0 l e n 1000 其中len表示给定字符串的长度。

示例

  • 输入

    • network = 111110000010000
  • 输出

    • [3,2,4,3,3,4]
  • 解释

    • 对于network = 111110000010000的情况,网络表示为:
      这里写图片描述
    • 距离节点A最远的节点为F。所以节点A发送信号所需的最小信号强度为3。
    • 距离节点B最远的节点是F和C,而距离C最远的是F。所以节点B和C发送信号所需的最小信号强度为2和4。
    • 距离节点D和E最远的节点为C。所以节点D和E发送信号所需的最小信号强度为3。
    • 距离节点F最远的节点为C。所以节点F发送信号所需的最小信号强度为4。

分析

  • 我们可以看出,对节点的存储和描述和的定义很相似。

  • 字符串相当于数组,下标访问为父节点到左节点: = 2 + 1 ,父节点到右节点: = 2 + 2

  • 左右节点到父节点: = 1 / 2

  • 先遍历一遍字符串,记录字符串中字符为1(某工程师)的节点到叶子节点的最小信号强度,即 1 。用map来存储(map<字符下标,最小信号强度> m;),节点高度用length函数计算。

  • 再遍历一遍字符串,从该节点向父节点查询是否还存在更远的节点。以节点F为例:

    • 节点F的下标为10,则m[10]=0;设上查找操作的最大值为 m a x R e s = 0 ;
    • 找到节点F的父节点E,即 ( 10 1 ) / 2 = 4 ,信号强度+1=1,因节点E无左子树, m a x R e s = 1 ; ,进入下一步。
    • 找到节点E的父节点B,即 ( 4 1 ) / 2 = 1 ,信号强度+1=2,因节点B存在左子树,需计算一下左子树的高度,D的高度=D的最小强度+1=1,则 m a x R e s = m a x ( m a x R e s , + D ) = 3 ; ,进入下一步。
    • 找到节点B的父节点A,即 ( 1 1 ) / 2 = 0 ,信号强度+1=3,因节点A存在右子树,需计算一下右子树的高度,C的高度=C的最小强度+1=1,则 m a x R e s = m a x ( m a x R e s , + C ) = 4 ; ,进入下一步。
    • 因访问到根节点,跳出循环,判断上查找操作的最大值与下查找操作的值(即节点到叶子节点的最小信号强度)的大小,找到最小信号强度。
      这里写图片描述

代码段

#include<vector>
#include<iostream>
#include<map>
#include<algorithm>
#include<string>

using namespace std;

int length(string network,int i) {
    if ((i >= network.length()) || network[i]=='\0' || network[i] == '0')
        return 0;
    int left = lens(network, 2 * i + 1);
    int right = lens(network, 2 * i + 2);
    return left > right ? left+1 : right+1;
}

vector<int> mm(string network) {
    vector<int> res;
    map<int, int> m;
    for (int i = 0; network[i] != '\0'; ++i) {
        if (network[i] == '1') {
            m[i] = lens(network,i)-1;
        }
    }
    for (int i = 0; network[i] != '\0'; ++i) {
        if (network[i] == '1') {
            if (i == 0) {
                res.push_back(m[i]);
            }
            else {
                int max_res = 0;
                int temp = 0;
                int j = (i-1)/2;
                int z = i;
                int flag = 0;
                while (j >= 0) {
                    if (flag == 1)
                        break;
                    if (flag == 0 && j == 0) {
                        flag = 1;
                    }
                    ++temp;
                    if (z == 2 * j + 1 && network[2*j+2]!='0') {
                        int k = 2 * j + 2;
                        max_res = max(max_res, m[k] + temp + 1);
                    }
                    else if (z == 2 * j + 2 && network[2 * j + 1] != '0') {
                        int k = 2 * j + 1;
                        max_res = max(max_res, m[k] + temp + 1);
                    }
                    z = j;
                    j = (z - 1) / 2;
                }
                max_res = max(m[i], max_res);
                res.push_back(max_res);
            }
        }
    }
    return res;
}

int main(int argc, char* argv[]) {
    string network;
    cin >> network;
    mm(network);
    getchar();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_40087851/article/details/82151827