黑白点的最大匹配数目 – JS

黑白点的最大匹配数目

[描述]
--------------------------------------------------------------------------------------
设B = {b1, b2, …, bn} 和 W = {w1, w2, …, wn}分别为平面上黑点和白点的两个集合。
一黑点bi = (xi, yi) 与一白点wj = (xj, yj)
匹配当且仅当 xi <= xj 和 yi <= yj 同时成立,
每个点最多只能用于一次匹配,
请找出黑白点之间的最大匹配数目。
黑点和白点各自的数量均不超过100000;
平面为(0, 0)到(10000, 10000)的矩形中的整数点
黑点白点坐标可能相同,B集合、W集合中也可能包含相同的元素。
--------------------------------------------------------------------------------------

[输入]
--------------------------------------------------------------------------------------
输入的第一行包括一个整数T (1 <= T <= 10),表示有T组测试数据.
对于每组测试数据:
第一行两个整数,n(黑点个数) m(白点个数),0 < n, m <= 100000
接下来n行每行有两个整数并用空格隔开:
黑点的横坐标x   黑点的纵坐标y
再接下来m行每行有两个整数同样用空格隔开:
白点的横坐标x   白点的纵坐标y
--------------------------------------------------------------------------------------

[输出]
--------------------------------------------------------------------------------------
对于每组测试数据,输出一行一个整数,表示最大匹配数。
--------------------------------------------------------------------------------------

[样例输入]
--------------------------------------------------------------------------------------
2
2 2
1 0
0 1
1 1
0 0
1 1
1 1
0 0
--------------------------------------------------------------------------------------

[样例输出]
--------------------------------------------------------------------------------------
1
0
--------------------------------------------------------------------------------------

[答案提示]
第一组中选择黑点(1,0)可以和白点(1,1)匹配,匹配数为1。
任何其他方式匹配都不能达到匹配数为2,所以答案为1。

第二组中黑点和白点不满足x、y的相对关系,没法配对,答案为0。
/*========================================================
// 来源: cnblogs
// 作者: Tong Zeng
// Javascript 随机数函数 学习之一:产生服从均匀分布随机数
// https://www.cnblogs.com/zztt/p/4024906.html
==========================================================*/
// [min, max]
let randomMinAndMax = (min, max) => {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

// [min , max)
let randomMinOffMax = (min, max) => {
  return Math.floor(Math.random() * (max - min)) + min;
}

// (min, max]
let randomOffMinMax = (min, max) => {
  return Math.ceil(Math.random() * (max - min )) + min;
}

/*========================================================
// 来源: csdn
// 作者: SundayAaron
// js生成不重复的随机数
// https://blog.csdn.net/SundayAaron/article/details/80181380
==========================================================*/
let randomIntegerArr = (minNum, maxNum, len) => {
  if (maxNum > minNum) {
    let [i, setArr, result, diffLen] = [minNum, [], [], maxNum - minNum];

    while (i < maxNum) {
      setArr.push(i);
      i++;
    }
    // 随机出现一次
    setArr.sort(() => {
      return 0.5 - Math.random();
    });

    // 均匀输出
    i = 0;
    while (i < len) {
      result.push(setArr[randomMinOffMax(0, diffLen)]);
      i++;
    };

    return result;
  } else {
    return;
  }
};

/*========================================================
// 黑白点计算
// [运行时间限制]: 未考虑
// [内存限制]: 未考虑
==========================================================*/
function getBWMatchCount(input) {
  let inputArray = input.split('\n');
  let testTotal = +(inputArray.splice(0, 1));

  while (testTotal > 0) {
    let nmArray = inputArray.splice(0, 1)[0].split(' ');
    let count = 0;
    let BW = [];
    let bTree = [];

    // 黑点
    inputArray.splice(0, +nmArray[0]).forEach(node => {
      node = node.split(' ');
      BW.push({
        x: +(node[0]),
        y: +(node[1]),
        color: 1
      });
    });

    // 白点
    inputArray.splice(0, +nmArray[1]).forEach(node => {
      node = node.split(' ');
      BW.push({
        x: +(node[0]),
        y: +(node[1]),
        color: 0
      });
    });

    BW.sort((a, b) => {
      if (a.x != b.x) {
        /**
         * > 0: b,a;
         * < 0: a,b;
         */
        return a.x - b.x; // 
      } else {
        /**
         * x坐标相同,黑点在前
         * 1: 黑点 
         * 0: 白点
         * 需要 a,b 排序的话, 需要负数 
         */
        return -(a.color - b.color);
      }
    });

    BW.forEach((node) => {
      if (node.color === 1) {
        // 黑点
        bTree.push(node.y);
      } else {
        // 白点
        let len = bTree.length;
        bTree.sort((a, b) => {
          return a - b;
        });
        if (len > 0 && bTree[0] <= node.y) {
          let i = 1;
          for (; i < len; i++) {
            if (bTree[i] > node.y) {
              break;
            }
          }
          // 移除 黑点集合中, y最大的小于白点y值的 黑点 
          bTree.splice(i - 1, 1);
          count++;
        }
      }
    });
    console.log(count);

    nmArray = null;
    BW = null;
    bTree = null;
    count = null;
    testTotal--;
  }
}