其他题目---路径数组变为统计数组

来源:互联网 发布:socket编程书籍 编辑:程序博客网 时间:2024/05/18 00:13

【题目】

  给定一个路径数组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)。

【基本思路】

  分两部分来处理。第一步先将paths数组转换为距离数组,即数组中每一个位置的值表示的是该城市到首都的距离。第二步,根据距离数组计算得到统计数组。

  如何得到距离数组呢?根据paths数组,我们可以得到每一个城市连向的城市,我们可以采用跳跃的方式,从一个城市一直往下一个城市跳,直到跳到首都位置,跳的次数就是该城市到首都的距离。下面以题目的例子来说明这一过程的实现:

  1、从左到右遍历paths,先遍历到位置0。
  paths[0] == 9,首先令paths[0] == -1(这是为了标记起跳的城市),因为城市0指向城市9,所以跳到城市9.
  跳到城市9之后,paths[9] == 1,说明下一个城市是1,因为城市9是由城市0跳过来的,所以先令paths[9] = 0,然后跳向城市1。
  跳到城市1之后,paths[1] == 1,说明城市1是首都。现在开始往回跳,城市1是由城市9跳过来的,所以跳回城市9。
  根据之前设置的paths[9] == 0,我们知道城市9是由城市0跳过来的,在回跳之前先设置paths[9] = -1,表示城市9到首都的距离为1,之后回跳到0。
  根据之前的设置paths[0] == -1,我们知道城市0是起跳位置,所以不再回跳,令paths[0] == -2,表示到首都的距离为2。
  以上在跳向首都的过程中,paths数组有一个路径反指的过程,这是为了保证找到首都之后,能够完全跳回来。在跳回来的过程中,设置好这一路所跳的城市即可。

  2、对于其他位置,跳跃的过程同上,但是跳跃终止的条件可以不是跳到首都,当我们跳到下一个位置发现它的值是负数,说明这个位置已经计算出了到首都的距离,我们只要在这个基础上来设置距离即可。

  3、首都我们单独处理即可,找到首都的位置然后将它的值设为0,表示距离为0。

  得到距离数组后,数组中的距离值都用负数表示。接下来我们根据距离数组来计算得到统计数组。该过程也是一个跳跃的过程。从左到右遍历数组,假设遍历到为i,paths[i] == -j,那么我们可以知道城市i距离首都的距离是j,先令paths[i] == 0,表示此位置不再代表距离,然后跳到位置j处,如果位置j处的值为负数-k,我们令paths[j] = 1,表示我们已经找到一个距离为j的城市(城市i)。然后根据k继续往下跳。如果位置j处的值为正数,说明该位置已经是距离为j的城市的数量统计,直接加1即可。

  paths数组转成距离数组的过程中,每一个城市只经历跳出去和跳回来两个过程;距离数组转成统计数组,每一个城市只经历跳出的过程,所以整个时间复杂度是O(N)。

【代码实现】

#python3.5def pathsToNums(paths):    def pathsToDistance(paths):        cap = -1        for i in range(len(paths)):            if paths[i] == i:                cap = i            elif paths[i] > -1:                curI = paths[i]                preI = i                paths[i] = -1                while paths[curI] != curI:                    if paths[curI] > -1:                        next = paths[curI]                        paths[curI] = preI                        preI = curI                        curI = next                    else:                        break                value = 0 if paths[curI] == curI else paths[curI]                while paths[preI] != -1:                    index = paths[preI]                    paths[preI] = value - 1                     value -= 1                    preI = index                paths[preI] = value - 1        paths[cap] = 0    def distanceToNums(disArr):        for i in range(len(disArr)):            index = disArr[i]            if index < 0:                disArr[i] = 0                index = -index                while disArr[index] < 0:                    tmp = disArr[index]                    disArr[index] = 1                    index = -tmp                disArr[index] += 1        disArr[0] = 1    if paths == None or len(paths) == 0:        return    pathsToDistance(paths)    distanceToNums(paths)    return paths
阅读全文
2 0
原创粉丝点击