求海岛周长

LeetCode原题:

Island Perimeter

Description:

You are given a map in form of a two-dimensional integer grid where 1 represents land and 0 represents water. Grid cells are connected horizontally/vertically (not diagonally). The grid is completely surrounded by water, and there is exactly one island (i.e., one or more connected land cells). The island doesn’t have “lakes” (water inside that isn’t connected to the water around the island). One cell is a square with side length 1. The grid is rectangular, width and height don’t exceed 100. Determine the perimeter of the island.

Example:

[[0,1,0,0],
 [1,1,1,0],
 [0,1,0,0],
 [1,1,0,0]]

Answer: 16

解法一:

遍历数组,当数组元素为1时,perimeter+=4,且如果此元素某侧(上、下、左、右)的元素为1,则perimeter-=2;
注:明显,这不是一种好的解法,编者提交后其运行时间只超过了30%的Java程序员

解法二:

同样遍历数组,当数组元素为1时,perimeter+=4,且如果此元素某侧(只判断左侧和下侧)的元素为1,则perimeter-=2;
注:提交后,LeetCode显示运行时间超过了70%的Java程序员,说明此解法是明显优于解法一的。

解法三:

在二的基础上,使用递归方法——即从第一个为1的元素开始遍历元素为1的部分。
这种解法的优点在于当表格很大且只有中间一部分是“海岛”时,速度会很快。
注:提交后,LeetCode显示运行时间超过了68%的Java程序员,貌似和解法二没有多大的区别,说明其运行速度受输入影响较大。

附代码:

//解法二
class Solution {
    public int islandPerimeter(int[][] grid) {
        int perimeter = 0;
        for(int i = 0 ; i < grid.length ; i++){
            for(int j = 0 ; j < grid[i].length ; j ++){
                if(grid[i][j] == 1){
                    perimeter += 4;
                    //对于船,只判断其左、下部是否为船
                    if(j > 0 && grid[i][j-1] == 1)
                        perimeter -= 2;
                    if(i < grid.length -1 && grid[i+1][j] == 1)
                        perimeter -= 2;
                }
            }
        }
        return perimeter;
    }
}
//解法三
class Solution {
    private int[][] travel;
    public int islandPerimeter(int[][] grid) {
        if(grid == null || grid.length <= 0 || grid[0].length <= 0)
            return 0;
        travel = new int[grid.length][grid[0].length];
        for(int i = 0 ; i < grid.length ; i ++){
            for(int j = 0 ; j < grid[0].length ; j ++){
                if(grid[i][j] == 1){
                    return getPerimeter(grid, i, j);
                }
            }
        }
        return 0;
    }
    public int getPerimeter(int[][] grid, int pos1, int pos2){
        int minus = -4;//减去的部分
        int left = 0, right = 0, up = 0, down = 0;//标志左右是否为1
        if(pos1 < 0 || pos1 > travel.length-1 || 
                pos2 < 0 || pos2 > travel[0].length-1 ||
                travel[pos1][pos2] == 1)
            return 0;//如果已经探索过,则结束
        if(grid[pos1][pos2] == 1){
//          System.out.println("pos:"+pos1+" "+pos2);
            travel[pos1][pos2] = 1;
            travel[pos1][pos2] = 1;//之前未探索,则做个标记表示已经探索过
            if(pos1 > 0 && grid[pos1-1][pos2] == 1){
                up = 1;
                minus += 1;
            }
            if(pos1 < grid.length -1 && grid[pos1+1][pos2] == 1){
                down = 1;
                minus += 1;
            }
            if(pos2 > 0 && grid[pos1][pos2-1] == 1){
                left = 1;
                minus += 1;
            }
            if(pos2 < grid[0].length - 1 && grid[pos1][pos2+1] == 1){
                right = 1;
                minus += 1;
            }
//          System.out.println("minus:"+minus);
//          System.out.println("direction:"+up+" "+down+" "+left+" "+right);
            return -minus + up*getPerimeter(grid, pos1-1, pos2)
                           + down*getPerimeter(grid, pos1+1, pos2)
                           + left*getPerimeter(grid, pos1, pos2-1)
                           + right*getPerimeter(grid, pos1, pos2+1);
        }
        return 0;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值