华为OD统一考试 - 结队编程

题目描述

某部门计划通过结队编程来进行项目开发,

已知该部门有 N 名员工,每个员工有独一无二的职级,每三个员工形成一个小组进行结队编程,结队分组规则如下:

从部门中选出序号分别为 i、j、k 的3名员工,他们的职级分贝为 level[i],level[j],level[k],

结队小组满足 level[i] < level[j] < level[k] 或者 level[i] > level[j] > level[k],

其中 0 ≤ i < j < k < n。

请你按上述条件计算可能组合的小组数量。同一员工可以参加多个小组。

输入描述

第一行输入:员工总数 n

第二行输入:按序号依次排列的员工的职级 level,中间用空格隔开

限制:

  • 1 ≤ n ≤ 6000
  • 1 ≤ level[i] ≤ 10^5

输出描述

可能结队的小组数量

用例

输入

4

1 2 3 4

输出

4

说明

可能结队成的组合(1,2,3)、(1,2,4)、(1,3,4)、(2,3,4)

输入

3

5 4 7

输出

0

说明

根据结队条件,我们无法为该部门组建小组

题目解析

本题的意思其实就是让我们求解给定输入数组中,比如用例1中 [1,2,3,4] ,每个数组元素:

  • 左边比自己大的元素的个数,设为:leftBiggerCount
  • 左边比自己小的元素的个数,设为:leftSmallerCount
  • 右边比自己大的元素的个数,设为:rightBiggerCount
  • 右边比自己小的元素是的个数,设为:rightSmallerCount

当我们求解出每个数组元素的上述信息后,累加每个数组元素的如下计算结果:

leftBiggerCount * rightSmallerCount + leftSmallerCount * rightBiggerCount

比如题目用例1中,数组 [1,2,3,4],索引为 idx

  • idx=0元素,leftBiggerCount = 0,leftSmallerCount = 0,rightBiggerCount = 3,rightSmallerCount = 0leftBiggerCount * rightSmallerCount + leftSmallerCount * rightBiggerCount = 0
  • idx=1元素,leftBiggerCount = 0,leftSmallerCount = 1,rightBiggerCount = 2,rightSmallerCount = 0leftBiggerCount * rightSmallerCount + leftSmallerCount * rightBiggerCount = 2
  • idx=2元素,leftBiggerCount = 0,leftSmallerCount = 2,rightBiggerCount = 1,rightSmallerCount = 0leftBiggerCount * rightSmallerCount + leftSmallerCount * rightBiggerCount = 2
  • idx=3元素,leftBiggerCount = 0,leftSmallerCount = 3,rightBiggerCount = 0,rightSmallerCount = 0leftBiggerCount * rightSmallerCount + leftSmallerCount * rightBiggerCount = 0

因此数组[1,2,3,4]的结队编程数量为4。

二叉搜索树解法

本题更优策略可以使用二叉搜索树,将时间复杂度降到O(NlogN)。

二叉搜索树,也叫二叉排序树,特点是其中序遍历序列是有序的。而构建二叉搜索树的步骤很简单,每次向二叉搜索树加入新节点时,都去和遇到的(子树)根节点进行比较:

  • 如果 新节点的值 < 根节点的值,则插入到根节点的左子树中,然后继续递归和左子树根比较
  • 如果 新节点的值 > 根节点的值,则插入到根节点的右子树中,然后继续递归和右子树根比较

因此,二叉搜索树中每个节点的左子树中所有节点的值都比自己小,右子树中所有节点的值都比自己大。

那么如何利用二叉搜索树解决本题呢?这里我通过图示说明。

首先我们来定义出二叉搜索树节点结构:

这里的二叉搜索树节点和数组元素是互相关联的。

然后,我们需要按照输入数组的倒序取元素插入到二叉搜索树中(PS:原因后面说明)

由于题目用例太极端,这里我自己建一个 [3, 1, 7, 2, 8, 6, 4 , 9, 5]

[3, 1, 7, 2, 8, 6, 4 , 9, 5]

插入5

[3, 1, 7, 2, 8, 6, 4 , 9, 5]

插入9

[3, 1, 7, 2, 8, 6, 4, 9, 5]

插入4

[3, 1, 7, 2, 8, 6, 4 , 9, 5]

插入6

[3, 1, 7, 2, 8, 6, 4 , 9, 5]

插入8

[3, 1, 7, 2, 8, 6, 4 , 9, 5]

插入2

后面就不画了,大家可以自己继续往下推导。

总结一下,插入新节点到二叉搜索树中,新节点需要不断和各种子树的根进行比较:

  • 如果新节点的值 < 根节点的值,则Node(根).leftChildCount++新节点递归进入根的左子树,继续比较
  • 如果新节点的值 > 根节点的值,则Node(新).rightSmallerCount新节点递归进入根的右子树,继续比较

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

2024华为OD机试卷题 文章被收录于专栏

本专栏给大家提供了华为2024最新华为OD 题目汇总。华为OD机试刷题记录机考算法题库,帮助你上岸华为。提供C++/Java、JavaScript、Python四种语言的解法。

全部评论

相关推荐

1 收藏 评论
分享
牛客网
牛客企业服务