[编程题] 将路径数组变为统计数组
给定一个路径数组paths,表示一张图。
paths[i]==j代表城市i连向城市j,如果paths[i]==i表示i城市是首都,一张图里只会有一个首都,不会有分图且图中除了首都指向自己之外不会有环;
例如:paths={9,1,4,9,0,4,8,9,0,1} 由这个数组表示的图如下图所示。
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]);
}
}
};