【LeetCode - Java】36. 有效的数独(中等)| 只需一次遍历

本文探讨了一种优化的数独有效性检查方法,通过将行、列和3x3子区域的重复检查合并到两次遍历中,利用哈希表和数组的数据结构来减少空间复杂度。作者展示了如何使用数组替代哈希表以提高运行效率,并提供了相应的代码实现和性能分析。
摘要由CSDN通过智能技术生成

1. 题目描述

在这里插入图片描述
在这里插入图片描述

2. 解题思路

题意所示,有效的数独需要满足三个条件:行中无重复、列中无重复和3X3中无重复,因此我们可以用一个哈希表记录元素是否出现过,针对三种不同的情况分别遍历一次数独就可以得出答案了,一共遍历三次,但是这样做比较浪费时间,可以遍历两次就得出答案吗?

观察一下发现,其实的重复判断与的重复判断可以在一次遍历中同时实现的,只需要把二维数组的下标互换就可以了,这样就需要两个哈希表用于记录元素是否出现过,一个记录行,一个记录列。

既然行与列的判断可以合并在一次遍历中,那3X3的判断可以合并吗?其实也是可以的,只要能找出下标的对应规律就可以了,这样就需要三个哈希表用于记录元素是否出现过,其下标的对应规律如下:

  • a = (i / 3) * 3 + j / 3
  • b = (i % 3) * 3 + j % 3

从三次遍历优化到一次遍历了,还有什么地方可以优化的吗?看过我文章的朋友应该知道,之前提到过好几次在条件允许的情况下,采用数组代替哈希表可以提高运行效率,同样的这里也可以使用三个数组代替三个哈希表用于储存记忆。

3. 代码实现

3.1 哈希表

public boolean isValidSudoku(char[][] board) {
        for (int i = 0; i < 9; i++) {
            HashSet<Character> setLine = new HashSet<>();
            HashSet<Character> setColumn = new HashSet<>();
            HashSet<Character> setCube = new HashSet<>();
            for (int j = 0; j < 9; j++) {
                if (board[i][j] != '.' && !setLine.add(board[i][j])) {
                    return false;
                }
                if (board[j][i] != '.' && !setColumn.add(board[j][i])) {
                    return false;
                }
                int a = (i / 3) * 3 + j / 3;
                int b = (i % 3) * 3 + j % 3;
                if (board[a][b] != '.' && !setCube.add(board[a][b])) {
                    return false;
                }
            }
        }
        return true;
    }

在这里插入图片描述

3.2 数组

public boolean isValidSudoku(char[][] board) {
        for (int i = 0; i < 9; i++) {
            int[] line = new int[9];
            int[] column = new int[9];
            int[] cube = new int[9];
            for (int j = 0; j < 9; j++) {
                if (board[i][j] != '.' && ++line[board[i][j] - '1'] > 1) {
                    return false;
                }
                if (board[j][i] != '.' && ++column[board[j][i] - '1'] > 1) {
                    return false;
                }
                int a = (i / 3) * 3 + j / 3;
                int b = (i % 3) * 3 + j % 3;
                if (board[a][b] != '.' && ++cube[board[a][b] - '1'] > 1) {
                    return false;
                }
            }
        }
        return true;
    }

在这里插入图片描述

3.3 对比

两种算法的时间复杂度和空间复杂度都是O(1),一共只需要遍历81次,存储27个变量(不算循环变量)。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值