将路径数组变为统计数组(树的层序遍历,双层队列)----BAT实习内推笔试卷(第一场)

[编程题] 将路径数组变为统计数组
给定一个路径数组paths,表示一张图。
paths[i]==j代表城市i连向城市j,如果paths[i]==i表示i城市是首都,一张图里只会有一个首都,不会有分图且图中除了首都指向自己之外不会有环; 
例如:paths={9,1,4,9,0,4,8,9,0,1} 由这个数组表示的图如下图所示。
城市1是首都所以距离为0;离首都距离为1的城市只有城市9;离首都距离为2的城市有城市0,3,7;离首都距离为3的城市有城市4,8;离首都距离为4的城市有城市2,5,6; 所以,距离为0的城市有1座;距离为1的城市有1座;距离为2的城市有3座;距离为3的城市有2座;距离为4的城市有3座;那么统计数组为numArr={1,1,3,2,3,0,0,0,0,0},numArr[i]==j代表距离为i的城市有j座; 要求实现一个void类型的函数,输入一个路径数组paths,直接在原数组上调整,使之变为numArr数组。 paths={9,1,4,9,0,4,8,9,0,1},函数处理后,paths={1,1,3,2,3,0,0,0,0,0}。 要求:如果paths长度为N,时间复杂度为O(N),额外空间复杂度为O(1);

// c++.cpp : 定义控制台应用程序的入口点。
//
 
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <string>
#include <functional>
 
using namespace::std;
class Solution {
public:
    /**
    *   将路径数组变为统计数组
    *   输入:代表一张图的数组paths
    *  len path的长度
    *   将paths数组变为距离数组numArr
    */
    void pathArrToNumArr(vector<int>& vec, int len) {
        int cap = 0;
        for (int i = 0; i < vec.size(); ++i) {
            if (vec[i] == i) {
                cap = i;
                break;
            }
        }
 
        // 采用层序遍历,设置两个队列
        // 当 first_q 队列为空时,表示一层遍历完毕
        // second_q 用来装下一层的节点
        //               1
        //               |
        //               9
        //             / | \
        //            0  3  7   first_q (装载第 i 层节点)
        //           / \
        //          4   8       second_q(装载第 i + 1 层节点)
        //         / \   \
        //        2   5   6
        deque<int> first_q;
        deque<int> second_q;
        first_q.push_back(cap);
        deque<int> result;
        int count = 0;
        while (first_q.empty() == false) {
            int tmp = first_q.front();
            first_q.pop_front(); // 从第 i 层中出一个节点
            for (int i = 0; i < vec.size(); ++i) {
                if (vec[i] == tmp && vec[i] != i) {
                    ++count; // 统计该节点的孩子数
                    second_q.push_back(i); // 把孩子节点加入到 second_q 队列
                }
            }
            // 如果 first_q 不为空,说明我们还没有遍历完一层
            if (first_q.empty() == false){
                continue; // 继续 while 循环,直至 first_q 队列为空,这时我们以完成第 i 层的遍历
            }
            else{
                first_q = second_q; // 把第 i + 1 层节点赋给 first_q 队列
                second_q.clear(); //
                result.push_back(count); // 把第 i 层的孩子数加入结果集
                count = 0;
            }
        }
        result.push_front(1); // 首都到首都的距离(1)放入结果集的开始
        while (result.size()>vec.size())result.pop_back();
        while (result.size()<vec.size())result.push_back(0);
        int length = vec.size();
        vec.clear();
        for (int i = 0; i < length; ++i){
            vec.push_back(result[i]);
        }
    }
};
 
int main() {
    vector<int> vec = { 0 };
    Solution obj;
    obj.pathArrToNumArr(vec, vec.size());
 
    return 0;
}


第二次做:

class Solution {
public:
	/**
	*	将路径数组变为统计数组
	*	输入:代表一张图的数组paths
	*  len path的长度
	*	将paths数组变为距离数组numArr
	*/
	void pathArrToNumArr(vector<int>& vec, int len) {
		int cap;
		for (int i = 0; i < vec.size(); ++i) {
			if (i == vec[i]) {
				cap = i;
				break;
			}
		}

		map<int, vector<int>> mp;
		for (int i = 0; i < vec.size(); ++i) {
			if (i != cap) {
				mp[vec[i]].push_back(i);
			}
		}

		deque<int> result;
		deque<int> first;
		deque<int> second;
		first.push_back(cap);
		int count = 0;

		while (first.empty() == false) {
			int tmp = first.front();
			first.pop_front();
			for (int i = 0; i < mp[tmp].size(); ++i) {
				second.push_back(mp[tmp][i]);
                ++ count ;
			}
			if (first.empty() == false) continue;
			else {
				result.push_back(count);
				first = second;
				second.clear();
                count = 0 ;
			}
		}

		result.push_front(1);
		while (result.size() > vec.size()) result.pop_back();
		while (result.size() < vec.size()) result.push_back(0);
		int length = vec.size();
		vec.clear();
		for (int i = 0; i < length; ++i) {
			vec.push_back(result[i]);
		}
	}
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值