题解 | #Sudoku#回溯+剪枝

Sudoku

https://www.nowcoder.com/practice/78a1a4ebe8a34c93aac006c44f6bf8a1

import java.math.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.stream.*;
import java.util.regex.*;
import java.util.function.*;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);

        String[][] m = new String[9][9];
        for (int i = 0; i < 9; i++) {
            m[i] = in.nextLine().split(" ");
        }
        fulfill(m);
        Arrays.stream(m).forEach(a-> {
            System.out.println(String.join(" ", a));
        });
    }

    // 回溯
    static boolean fulfill(String[][] m) {
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                String curr = m[i][j];
                if ("0".equals(curr)) {
                    // 剪枝
                    List<String> candidates = getCandidates(i, j, m);
                    if (candidates.isEmpty()) {
                        return false;
                    }
                    // 递归 DFS
                    for (String c : candidates) {
                        // continue fulfill 多次尝试
                        m[i][j] = c;
                        if (fulfill(m)) {
                            return true;
                        }
                        // 回溯(仅有 37 行是不可以的)
                        m[i][j] = "0";
                    }
                    return false;
                }
            }
        }
        return true;
    }

    static List<String> getCandidates(int i, int j, String[][] m) {
        String h = String.join("", m[i]);
        List<String> hSet = IntStream.rangeClosed(1, 9)
                            .mapToObj(String::valueOf)
                            // n->!h.contains(n) 可以换成 Predicate.not(h::contains)
                            .filter(n->!h.contains(n))
                            .collect(Collectors.toList());


        String[] vArr = new String[9];
        for (int k = 0; k < 9; k++) {
            vArr[k] = m[k][j];
        }
        String v = String.join("", vArr);
        List<String> vSet = IntStream.rangeClosed(1, 9)
                            .mapToObj(String::valueOf)
                            .filter(n->!v.contains(n))
                            .collect(Collectors.toList());

        String[] bArr = new String[9];
        int bIndex = 0;
        for (int p = 0; p < 3; p++) {
            for (int q = 0; q < 3; q++) {
                bArr[bIndex++] = m[(i / 3) * 3 + p][(j / 3) * 3 + q];
            }
        }
        String b = String.join("", bArr);
        List<String> bSet = IntStream.rangeClosed(1, 9)
                            .mapToObj(String::valueOf)
                            .filter(n->!b.contains(n))
                            .collect(Collectors.toList());

        vSet.retainAll(bSet);
        hSet.retainAll(vSet);
        return hSet;
    }
}


全部评论

相关推荐

鼠鼠没有找到暑期实习,简历太空了,感觉直接去秋招会完蛋,这个时间点找个日常实习混个简历,边实习边准备秋招有没有搞头啊
梦想是成为七海千秋:可以的完全可以的,找不到暑期就找日常,秋招之前还是有很多时间可以实习的,哪怕只实习了一个月都可以写在简历上
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务