资讯专栏INFORMATION COLUMN

前端面试的一道算法题(使用canvas解答)

hot_pot_Leo / 3250人阅读

摘要:据了解,现在前端面试也喜欢考算法题了。下面说一个跟前端有点相关并且有点趣的一道算法题。遍历二维数组连续的个数连续的个数形状的总数第几个形状形状的面积最后的代码图片路径读取整张图片的像素。

据了解,现在前端面试也喜欢考算法题了。前几天去面试,果不其然的,面试官给我四道算法题,让我自己回去做。下面说一个跟前端有点相关并且有点趣的一道算法题。

题目:

平面上有若干个不特定的形状,如下图所示。请写程序求出物体的个数,以及每个不同物体的面积。

分析

想要知道有多少个图形,想到的就是先获取图片中的每一个像素点然后判获取像素点的背景颜色(RGBA)。想要获得图片中的每一个像素点,那就可以联想到使用h5的canvas。
如下:

菜鸟教程中canvas的getimagedata方法

书写html标签。

</>复制代码

  1. 对不你,你的浏览器不支持Canvas

js获取canvas对象

</>复制代码

  1. let ctxt = canvas.getContext("2d");

js创建image对象

</>复制代码

  1. let img = new Image;
  2. img.src = "./image.png"; //图片路径
  3. img.onload = function(){} //加载成功后的执行函数,之后的代码就写在其中

创建存储图片像素点的二维数组

</>复制代码

  1. let coordinates = [];
  2. for(let i=0; i<200; i++){
  3. coordinates[i] = [];
  4. }

获取像素点,也就是使用getimagedata方法。

</>复制代码

  1. ctxt.drawImage(img, 0, 0); //将图片画如canvas
  2. let data = ctxt.getImageData(0, 0, 350, 200).data;//读取整张图片的像素。

将像素存入二维数组

</>复制代码

  1. let x=0,y=0; //二维数组的行和列, x:列 y:行
  2. for(let i =0,len = data.length; i= 350){
  3. x = 0;
  4. y++;
  5. }
  6. }

目前代码如下:

</>复制代码

  1. (function(){
  2. let ctxt = canvas.getContext("2d");
  3. let img = new Image;
  4. let coordinates = [];
  5. let h = 200,
  6. w = 350;
  7. for(let i=0; i<200; i++){
  8. coordinates[i] = [];
  9. }
  10. img.src = "./image.png"; //图片路径
  11. img.onload = function(){
  12. ctxt.drawImage(img, 0, 0);
  13. let data = ctxt.getImageData(0, 0, 350, 200).data;//读取整张图片的像素。
  14. let x=0,y=0;
  15. for(let i =0,len = data.length; i= 350){
  16. x = 0;
  17. y++;
  18. }
  19. }
  20. console.log(coordinates);
  21. }
  22. })();

如图:

构成类似如下二维数组:

</>复制代码

  1. 0,0,0,0,0,0,0,0,0,0,0,0
  2. 0,0,1,1,1,0,0,0,0,0,0,0
  3. 0,1,1,1,1,0,0,0,0,0,0,0
  4. 0,1,1,1,0,0,0,1,1,1,1,0
  5. 0,0,0,0,0,0,1,1,1,0,0,0
  6. 0,0,0,0,0,0,1,1,1,0,0,0
  7. 0,0,0,0,0,0,0,0,0,0,0,0

那么我们就只需要知道二维数组中这种连续为1的块有多少个就知道了图片中形状有多少个,并且块中有多少个1,那么这个块的面积就是1的个数。

递归回溯算法

</>复制代码

  1. //计算连续的面积和个数
  2. const linkSum = (i,j,num)=>{
  3. //走过的路就置0
  4. coordinates[i][j] = 0;
  5. num++;
  6. //向上
  7. if((i+1 < h) && coordinates[i+1][j] == 1){
  8. num = linkSum(i+1 , j , num);
  9. }
  10. //向下
  11. if((j+1 < w) && coordinates[i][j+1] == 1){
  12. num = linkSum(i , j+1 , num);
  13. }
  14. //向左
  15. if((i-1 >= 0) && coordinates[i-1][j] == 1){
  16. num = linkSum(i-1 , j , num);
  17. }
  18. //向右
  19. if((j-1 >= 0) && coordinates[i][j-1] == 1){
  20. num = linkSum(i , j-1 , num);
  21. }
  22. return num;
  23. }

不熟悉的,直接百度就好,这里就不多说了,其实代码就反应了很多信息。

使用算法,统计并计算出结果。

</>复制代码

  1. const getCountAndArea = () =>{
  2. let sum = [];
  3. let count = 0;
  4. for(let i = 0; i < h; i++) //遍历二维数组
  5. {
  6. for(let j = 0; j < w; j++)
  7. {
  8. //连续1的个数
  9. if(coordinates[i][j] == 1)
  10. {
  11. let buf = 0; //连续1的个数
  12. buf = linkSum(i,j,buf);
  13. count++; //形状的总数
  14. sum.push({
  15. index: count, //第几个形状
  16. area: buf //形状的面积
  17. });
  18. }
  19. }
  20. }
  21. return {
  22. count,
  23. sum
  24. };
  25. }
最后的代码

</>复制代码

  1. (function(){
  2. let ctxt = canvas.getContext("2d");
  3. let img = new Image;
  4. let coordinates = [];
  5. let h = 200,
  6. w = 350;
  7. for(let i=0; i<200; i++){
  8. coordinates[i] = [];
  9. }
  10. img.src = "./image.png"; //图片路径
  11. img.onload = function(){
  12. ctxt.drawImage(img, 0, 0);
  13. let data = ctxt.getImageData(0, 0, 350, 200).data;//读取整张图片的像素。
  14. let x=0,y=0;
  15. for(let i =0,len = data.length; i= 350){
  16. x = 0;
  17. y++;
  18. }
  19. }
  20. // console.log(coordinates);
  21. let rst = getCountAndArea();
  22. // console.log(rst);
  23. console.log("个数: " + rst.count);
  24. for(let i=0; i{
  25. let sum = [];
  26. let count = 0;
  27. for(let i = 0; i < h; i++)
  28. {
  29. for(let j = 0; j < w; j++)
  30. {
  31. //连续1的个数
  32. if(coordinates[i][j] == 1)
  33. {
  34. let buf = 0;
  35. buf = linkSum(i,j,buf);
  36. count++;
  37. sum.push({
  38. index: count,
  39. area: buf
  40. });
  41. }
  42. }
  43. }
  44. return {
  45. count,
  46. sum
  47. };
  48. }
  49. //计算连续的面积和个数
  50. const linkSum = (i,j,num)=>{
  51. //走过的路就置0
  52. coordinates[i][j] = 0;
  53. num++;
  54. //向上
  55. if((i+1 < h) && coordinates[i+1][j] == 1){
  56. num = linkSum(i+1 , j , num);
  57. }
  58. //向下
  59. if((j+1 < w) && coordinates[i][j+1] == 1){
  60. num = linkSum(i , j+1 , num);
  61. }
  62. //向左
  63. if((i-1 >= 0) && coordinates[i-1][j] == 1){
  64. num = linkSum(i-1 , j , num);
  65. }
  66. //向右
  67. if((j-1 >= 0) && coordinates[i][j-1] == 1){
  68. num = linkSum(i , j-1 , num);
  69. }
  70. return num;
  71. }
  72. })();
运行的结果:

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/87030.html

相关文章

  • 深入理解js

    摘要:详解十大常用设计模式力荐深度好文深入理解大设计模式收集各种疑难杂症的问题集锦关于,工作和学习过程中遇到过许多问题,也解答过许多别人的问题。介绍了的内存管理。 延迟加载 (Lazyload) 三种实现方式 延迟加载也称为惰性加载,即在长网页中延迟加载图像。用户滚动到它们之前,视口外的图像不会加载。本文详细介绍了三种延迟加载的实现方式。 详解 Javascript十大常用设计模式 力荐~ ...

    caikeal 评论0 收藏0
  • canvas getImageData 做点有趣

    摘要:回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法。代码请点这里这里有一个示例,展示下用回溯法怎么找到这些形状的。 说明 canvas元素标签强大之处在于可以直接在HTML上进行图形操作,具有极大的应用价值。 canvas 可以实现对图像的像素操作,这就要说到 getImag...

    chenatu 评论0 收藏0
  • 2017 前端面试准备 - 收藏集 - 掘金

    摘要:最近遇到的前端面试题更新版前端掘金个人博客已上线,欢迎前去访问评论无媛无故的个人博客以下内容非本人原创,是整理后觉得更容易理解的版本,欢迎补充。 一道面试题引发的对 javascript 类型转换的思考 - 前端 - 掘金 最近群里有人发了下面这题:实现一个函数,运算结果可以满足如下预期结果: ... 收集 JavaScript 各种疑难杂症的问题集锦 - 前端 - 掘金 从原博客迁移...

    王晗 评论0 收藏0
  • 2017 前端面试准备 - 收藏集 - 掘金

    摘要:最近遇到的前端面试题更新版前端掘金个人博客已上线,欢迎前去访问评论无媛无故的个人博客以下内容非本人原创,是整理后觉得更容易理解的版本,欢迎补充。 一道面试题引发的对 javascript 类型转换的思考 - 前端 - 掘金 最近群里有人发了下面这题:实现一个函数,运算结果可以满足如下预期结果: ... 收集 JavaScript 各种疑难杂症的问题集锦 - 前端 - 掘金 从原博客迁移...

    xiaochao 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<