前端面試的一道演算法題,面試演算法題

來源:互聯網
上載者:User

前端面試的一道演算法題,面試演算法題

(使用canvas解答)

下面說一個跟前端有點相關並且有點趣的一道演算法題。

題目:

平面上有若干個不特定的形狀,如所示。請寫程式求出物體的個數,以及每個不同物體的面積。


 分析

想要知道有多少個圖形,想到的就是先擷取圖片中的每一個像素點然後判擷取像素點的背景顏色(RGBA)。想要獲得圖片中的每一個像素點,那就可以聯想到使用h5的canvas。
如下:

菜鳥教程中canvas的getimagedata方法http://www.runoob.com/tags/canvas-getimagedata.html

  • 書寫html標籤。

    <canvas id="canvas" height="200" width="350">對不你,你的瀏覽器不支援Canvas</canvas>
  • js擷取canvas對象

    let ctxt = canvas.getContext('2d');
  • js建立image對象
    let img = new Image;img.src = './image.png'; //圖片路徑img.onload = function(){}  //載入成功後的執行函數,之後的代碼就寫在其中
  • 建立儲存圖片像素點的二維數組
    let coordinates = [];for(let i=0; i<200; i++){     coordinates[i] = [];}
  • 擷取像素點,也就是使用getimagedata方法。
    ctxt.drawImage(img, 0, 0);  //將圖片畫如canvaslet data = ctxt.getImageData(0, 0, 350, 200).data;//讀取整張圖片的像素。
  • 將像素存入二維數組
    let x=0,y=0;  //二維數組的行和列, x:列  y:行for(let i =0,len = data.length; i<len;i+=4){      let red = data[i],//紅色色深      green = data[i+1],//綠色色深      blue = data[i+2],//藍色色深      alpha = data[i+3];//透明度      //把每個像素點,以二位元組的形式展開      if(`${red} ${green} ${blue}` === '210 227 199'){          coordinates[y][x] = 0;      }else{          coordinates[y][x] = 1;      }      x++;      if(x >= 350){          x = 0;          y++;      }}
  • 目前代碼如下:
    (function(){      let ctxt = canvas.getContext('2d');      let img = new Image;      let coordinates = [];      let h = 200,          w = 350;      for(let i=0; i<200; i++){          coordinates[i] = [];      }      img.src = './image.png'; //圖片路徑      img.onload = function(){          ctxt.drawImage(img, 0, 0);          let data = ctxt.getImageData(0, 0, 350, 200).data;//讀取整張圖片的像素。          let x=0,y=0;          for(let i =0,len = data.length; i<len;i+=4){                  let red = data[i],//紅色色深                  green = data[i+1],//綠色色深                  blue = data[i+2],//藍色色深                  alpha = data[i+3];//透明度                  //把每個像素點,以二位元組的形式展開                  if(`${red} ${green} ${blue}` === '210 227 199'){                      coordinates[y][x] = 0;                  }else{                      coordinates[y][x] = 1;                  }                  x++;                  if(x >= 350){                      x = 0;                      y++;                  }              }              console.log(coordinates);      }  })();

image.png
  • 構成類似如下二維數組:

    0,0,0,0,0,0,0,0,0,0,0,0
    0,0,1,1,1,0,0,0,0,0,0,0
    0,1,1,1,1,0,0,0,0,0,0,0
    0,1,1,1,0,0,0,1,1,1,1,0
    0,0,0,0,0,0,1,1,1,0,0,0
    0,0,0,0,0,0,1,1,1,0,0,0
    0,0,0,0,0,0,0,0,0,0,0,0

那麼我們就只需要知道二維數組中這種連續為1的塊有多少個就知道了圖片中形狀有多少個,並且塊中有多少個1,那麼這個塊的面積就是1的個數。

遞迴回溯演算法
//計算連續的面積和個數const linkSum = (i,j,num)=>{        //走過的路就置0      coordinates[i][j] = 0;      num++;      //向上      if((i+1 < h) && coordinates[i+1][j] == 1){        num = linkSum(i+1 , j , num);      }      //向下      if((j+1 < w) && coordinates[i][j+1] == 1){        num = linkSum(i , j+1 , num);      }      //向左      if((i-1 >= 0) && coordinates[i-1][j] == 1){        num = linkSum(i-1 , j , num);      }      //向右    if((j-1 >= 0) && coordinates[i][j-1] == 1){        num = linkSum(i , j-1 , num);    }    return num;}

不熟悉的,直接百度就好,這裡就不多說了,其實代碼就反應了很多資訊。

使用演算法,統計並計算出結果。
const getCountAndArea = () =>{    let sum = [];    let count = 0;    for(let i = 0; i < h; i++)  //遍曆二維數組    {      for(let j = 0; j < w; j++)      {       //連續1的個數       if(coordinates[i][j] == 1)       {        let buf = 0;  //連續1的個數        buf = linkSum(i,j,buf);        count++;  //形狀的總數        sum.push({            index: count,   //第幾個形狀            area: buf         //形狀的面積        });       }      }    }    return {        count,        sum    };}
最後的代碼
(function(){        let ctxt = canvas.getContext('2d');        let img = new Image;        let coordinates = [];        let h = 200,            w = 350;        for(let i=0; i<200; i++){            coordinates[i] = [];        }        img.src = './image.png'; //圖片路徑        img.onload = function(){            ctxt.drawImage(img, 0, 0);            let data = ctxt.getImageData(0, 0, 350, 200).data;//讀取整張圖片的像素。            let x=0,y=0;            for(let i =0,len = data.length; i<len;i+=4){                    let red = data[i],//紅色色深                    green = data[i+1],//綠色色深                    blue = data[i+2],//藍色色深                    alpha = data[i+3];//透明度                    //把每個像素點,以二位元組的形式展開                    if(`${red} ${green} ${blue}` === '210 227 199'){                        coordinates[y][x] = 0;                    }else{                        coordinates[y][x] = 1;                    }                    x++;                    if(x >= 350){                        x = 0;                        y++;                    }                }                // console.log(coordinates);                let rst = getCountAndArea();                // console.log(rst);                console.log('個數: ' + rst.count);                for(let i=0; i<rst.sum.length; i++){                    console.log(`第${i+1}個面積為: ${rst.sum[i].area} px`);                }        }        const getCountAndArea = () =>{            let sum = [];            let count = 0;            for(let i = 0; i < h; i++)            {              for(let j = 0; j < w; j++)              {               //連續1的個數               if(coordinates[i][j] == 1)               {                let buf = 0;                buf = linkSum(i,j,buf);                count++;                sum.push({                    index: count,                    area: buf                });               }              }            }            return {                count,                sum            };        }        //計算連續的面積和個數        const linkSum = (i,j,num)=>{            //走過的路就置0          coordinates[i][j] = 0;          num++;          //向上          if((i+1 < h) && coordinates[i+1][j] == 1){            num = linkSum(i+1 , j , num);          }          //向下          if((j+1 < w) && coordinates[i][j+1] == 1){            num = linkSum(i , j+1 , num);          }          //向左          if((i-1 >= 0) && coordinates[i-1][j] == 1){            num = linkSum(i-1 , j , num);          }          //向右        if((j-1 >= 0) && coordinates[i][j-1] == 1){            num = linkSum(i , j-1 , num);        }        return num;        }    })();
啟動並執行結果:

學習過程中遇到什麼問題或者想擷取學習資源的話,歡迎加入學習交流群
343599877,我們一起學前端!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.