查看: 2965| 回复: 8
跳转到指定楼层
上一主题 下一主题
收起左侧

请教number of islands一行一行读的情况

全局:

注册一亩三分地论坛,查看更多干货!

您需要 登录 才可以下载或查看附件。没有帐号?注册账号

x
number of islands这道题有多种解法:dfs, bfs, union find.
这里有个问题,有些公司,比如Dropbox, 会问如果一行一行读怎么办?
Union find+一行一行读的解法想不明白,算islands的count算不对,求大神指点

评分

参与人数 1大米 +1 收起 理由
14417335 + 1 给你点个赞!

查看全部评分


上一篇:希望找到小伙伴交流对算法的理解。
下一篇:面试通常会要求重写 最基本的 data structure 吗?
推荐
magicsets 2018-1-23 04:55:24 | 只看该作者
全局:
我写了一份代码,可以通过LC 200:

  1. import java.util.Arrays;

  2. class Solution {
  3.   private static final int INVALID = 0;

  4.   public int numIslands(char[][] grid) {
  5.     if (grid.length == 0) {
  6.       return 0;
  7.     }

  8.     SimpleUnionFind uf = new SimpleUnionFind();
  9.     int[] tags = new int[grid[0].length];
  10.     int tagCounter = 0;

  11.     // 逐行处理
  12.     for (char[] row : grid) {
  13.       for (int i = 0; i < row.length; ++i) {
  14.         // Case 1. 当前格子为'0',则标记为"无效"编号
  15.         if (row[i] == '0') {
  16.           tags[i] = INVALID;
  17.           continue;
  18.         }

  19.         // Case 2. 当前格子为'1',先获取左边和上方格子编号
  20.         int leftTag = (i == 0 ? 0 : tags[i-1]);
  21.         int upTag = tags[i];

  22.         if (leftTag == INVALID) {
  23.           if (upTag == INVALID) {
  24.             // Case 2.1. 如果左边和上方格子都是无效编号,则分配一个新编号给当前格子
  25.             uf.makeSet(tags[i] = ++tagCounter);
  26.           } else {
  27.             // Case 2.2. 继承上方编号
  28.             // NO-OP
  29.           }
  30.         } else {
  31.           if (upTag == INVALID) {
  32.             // Case 2.3. 继承左边编号
  33.             tags[i] = leftTag;
  34.           } else {
  35.             // Case 2.4. Union左边和上方的编号,并继承
  36.             tags[i] = uf.union(tags[i-1], tags[i]);
  37.           }
  38.         }
  39.       }
  40.     }

  41.     // 返回并查集中等价类数量
  42.     return uf.numGroups(tagCounter);
  43.   }
  44. }


  45. // 一个简易并查集,没有做路径折叠
  46. class SimpleUnionFind {
  47.   private int[] data = new int[256];

  48.   private void resize() {
  49.     data = Arrays.copyOf(data, data.length * 2);
  50.   }

  51.   public void makeSet(int value) {
  52.     while (value >= data.length) {
  53.       resize();
  54.     }
  55.     data[value] = value;
  56.   }

  57.   public int find(int value) {
  58.     while (data[value] != value) {
  59.       value = data[value];
  60.     }
  61.     return value;
  62.   }

  63.   public int union(int lhs, int rhs) {
  64.     int root = find(lhs);
  65.     data[find(rhs)] = root;
  66.     return root;
  67.   }

  68.   public int numGroups(int limit) {
  69.     int count = 0;
  70.     for (int i = 1; i <= limit; ++i) {
  71.       if (data[i] == i) {
  72.         ++count;
  73.       }
  74.     }
  75.     return count;
  76.   }
  77. }
复制代码

评分

参与人数 2大米 +4 收起 理由
14417335 + 1 给你点个赞!
flykite083 + 3 给你点个赞!

查看全部评分

回复

使用道具 举报

🔗
Miracle58 2018-1-22 07:18:03 | 只看该作者
全局:
一行一行读什么意思,请贴代码
回复

使用道具 举报

🔗
dingshilun 2018-1-22 08:09:21 | 只看该作者
全局:
大概想了一下。。。欢迎讨论

一行一行从左向右读,那么一个格子的左边和上面一定已经被并入相应的island了,那么一个新的点会有三种情况:
1.左边上边都没有island,明显这个时候我们应该开一个新的island
2.相邻有一个island,那么我们把它并入这个island
3.有两个island,那么合并这两个island(如果需要),并且取更小的数字作为island编号(主要是为了下一个节点不要重蹈覆辙)

评分

参与人数 1大米 +1 收起 理由
14417335 + 1 给你点个赞!

查看全部评分

回复

使用道具 举报

🔗
fisherhust 2018-1-22 08:22:55 | 只看该作者
全局:
dingshilun 发表于 2018-1-22 08:09
大概想了一下。。。欢迎讨论

一行一行从左向右读,那么一个格子的左边和上面一定已经被并入相应的island ...

如果一行一行读, 是不是意味着无法读取当前位置"左上"的格子?
回复

使用道具 举报

🔗
dingshilun 2018-1-22 08:40:55 | 只看该作者
全局:
fisherhust 发表于 2018-1-22 08:22
如果一行一行读, 是不是意味着无法读取当前位置"左上"的格子?

如果可以向八个方向扩展那就简单了呀、不需要unionfind了
回复

使用道具 举报

🔗
hawkingsecond 2018-1-22 08:52:59 | 只看该作者
全局:
我觉得用union find,读完第一行后,后面每个格子只要union左边和上面的格子就行。这样就能保证所有临接的都合并过了。
回复

使用道具 举报

🔗
 楼主| flykite083 2018-1-22 23:19:02 | 只看该作者
全局:
fisherhust 发表于 2018-1-22 08:22
如果一行一行读, 是不是意味着无法读取当前位置"左上"的格子?

如果一行一行读,那么我们需要保存上一行的信息。这个信息可以是一个list of intervals of 1s. 或者干脆把整个上一行保存。
回复

使用道具 举报

🔗
 楼主| flykite083 2018-1-22 23:20:19 | 只看该作者
全局:
dingshilun 发表于 2018-1-22 08:09
大概想了一下。。。欢迎讨论

一行一行从左向右读,那么一个格子的左边和上面一定已经被并入相应的island ...

看起来是正解!不过估计这个算法实现起来会有些复杂。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表