Counting Shape
油彩
Dec 1 2019

# 前言

今天看到一个面试题 【平面上有若干个不特定的形状,如上图所示。请写程序求出物体的个数,以及每个不同物体的面积】

原来是烂大街的题目。。。完全不知道

首先需要

解法如下【打开控制台可看见结果】


<script>
  const ctx = document.createElement('canvas').getContext('2d')
  const img = new Image()
  img.src = '/img/20191201.png'

  img.onload = function() {
    ctx.drawImage(img, 0, 0, 40, 40)
    const originData = ctx.getImageData(0, 0, 40, 40)

    console.log('originData', originData)
    formatArr(originData.width, originData.height, originData.data)
  }

  function formatArr(width, height, arr) {
    const foo = []

    // 合并 rgba 通道
    const bar = new Array(width * height).fill(0)
    arr.forEach((x, index) => {
      bar[Math.floor(index / 4)] += x === 255 ? 0 : 1
    })
    console.log('rgba 通道合并后结果数组', bar)

    // 构造二维数组,二维数组长度为图形宽度
    bar.forEach((x, index) => {
      let i = index % width,
        j = Math.floor(index / width)

      foo[i] = foo[i] || []
      foo[i][j] = x
    })

    console.log('转置为二维数组', foo)
    breadthFirstSearch(JSON.parse(JSON.stringify(foo)))
  }

  // 计算有多少个图形,以及各自面积
  // 思路,遍历数组,找到为1的就开始路径搜素,递归走完【右下左上】,走完的部分置为 0。当全部走完,就可以得出面积。
  // 全部走完后,构造新的对象再次进行上述操作。最终得出结果
  function breadthFirstSearch(twiceArr) {
    const BasicObj = class {
      constructor() {
        this.hasEnd = false
        this.points = []
        this.areaSize = 0
      }
    }

    const result = [new BasicObj()]

    function setState({ xAxis, yAxis, isOver }) {
      if (isOver) {
        result[0].hasEnd = true
        return
      }
      if (result[0].hasEnd) result.unshift(new BasicObj())

      result[0].areaSize++
      result[0].points.push({ x: xAxis, y: yAxis })
    }

    // 一层循环
    for (let i = 0, l = twiceArr.length; i < l; i++) {
      // 二层
      for (let ii = 0, ll = twiceArr[i].length; ii < ll; ii++) {
        if (twiceArr[i][ii] !== 0) {
          // 开始广搜
          let tempList = [{ x: ii, y: i }]
          let nextList = []
          while (tempList.length !== 0) {
            tempList.forEach(({ x, y }) => {
              if (twiceArr[y][x]) {
                twiceArr[y][x] = 0
                setState({ xAxis: x, yAxis: y })

                // 右
                if (twiceArr[y] && twiceArr[y][x + 1]) {
                  nextList.push({ x: x + 1, y: y })
                }
                // 下
                if (twiceArr[y + 1] && twiceArr[y + 1][x]) {
                  nextList.push({ x: x, y: y + 1 })
                }
                // 左
                if (twiceArr[y] && twiceArr[y][x - 1]) {
                  nextList.push({ x: x - 1, y: y })
                }
                // 上
                if (twiceArr[y - 1] && twiceArr[y - 1][x]) {
                  nextList.push({ x: x, y: y - 1 })
                }
              }
            })
            tempList = nextList
            nextList = []
            if (tempList.length === 0) setState({ isOver: true })
          }
        }
      }
    }

    console.log('result', result)
  }
</script>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106