zoukankan      html  css  js  c++  java
  • 普林斯顿算法课Part2第四周作业_Boggle

    作业地址:http://coursera.cs.princeton.edu/algs4/assignments/boggle.html

    作业难点:

    1、如何保证求解速度,满分要求是求解速度 >= 0.5 * 参考速度,约在5000次/5s。

      1)最直观的算法思想:要明确查找单词即为对一个游戏板(board)上的一个顶点向8个方向进行深度优先遍历,在遍历过程中查找单词是否在词典中,将在词典中的单词记录保存下来。为顺利找出所有满足条件的单词,可以使用广度、深度优先遍历该顶点。重复遍历完所有顶点即可找出在词典中的所有单词。

      2)根据算法思想构建数据结构:游戏板-board[][]一个二维数组,构建词典使用教材提及的TST(三叉单词查找树)或者Trie(单词查找树),保存已找出的单词(因为按题目要求重复单词只保留一个)使用HashSet,遍历方法采用dfs(深度优先搜索)方法。

      3)根据dfs原理构建算法求解,使用marked[][]标记已访问的顶点,使用TST构建词典,求解速度约在2500次/5s,需要优化。

      4)为避免回溯过程中重复查找单词树,为TST新增一个hasPrefix(String key)函数(查找单词树中是否包含key前缀),返回TST的Node类型:root——未查找到,非root——查找到。因为返回的是Node,所以每次只需查找Node以后的枝叶即可,key也即board[i][j]的字母即可。此时,求解速度约在3500次/5s,需要优化。

      5)弃用TST,改用Trie构建词典,修改hasPrefix()函数为getNext(String key)函数,此时求解速度上次到6500次/5s,可以满分,离参考值还有一段距离。

      6)因为查找的过程中存在重复单词,所以在开始的时候使用HashSet来保存找到的单词,存在查找重复单词并将其重复插入的情况。为避免对重复单词进行多次处理,设置处理过的单词的val值为-1,并记录该节点的位置,将其保存下来,在处理的最后对节点的val进行恢复。没有了重复单词,也就不需要HashSet来保存查找到的单词,使用简单的链表来保存即可,保存单词的速度更快。此时求解速度可以上升到10000次/5s。

    容易扣分点:

    同作业难点。

    部分代码:

    1、数据结构:

        private Trie dict;
        private String[][] gameStr;
        private Bag<String> words;       // found words
        private Bag<Trie.Node> nodes;    // nodes of found words
        private static class Trie {
            private static int R = 26;   // Radix, English alphabet
            private static final int OFFSET = 'A'; 
    public Node root; class Node { int val; Node[] next = new Node[R]; }
    }

    2、getAllValidWords(BoggleBoard board):

        public Iterable<String> getAllValidWords(BoggleBoard board) {
            words = new Bag<String>();
            nodes = new Bag<Trie.Node>();
            int col = board.cols(), row = board.rows();  
            boolean[][] marked = new boolean[row][col];
            gameStr = new String[row][col];  
            for (int i = 0; i < row; i++)
                for (int j = 0; j < col; j++) 
                gameStr[i][j] = representQ(i, j, board);
            for (int i = 0; i < row; i++) {
                for (int j = 0; j < col; j++) {    
                    Trie.Node pNode = dict.getNext(dict.root, gameStr[i][j]);
                    if (pNode != null)
                     dfs(board, marked, i, j, pNode, gameStr[i][j]);
                }
            }
            for (Trie.Node n : nodes)
                n.val = 1;
            return words;
        }
        private void dfs(BoggleBoard board, boolean[][] marked,
                         int x, int y, Trie.Node pNode, String preStr) {  
            marked[x][y] = true;  
            String curStr;
            int xNeighbor, yNeighbor;
            Trie.Node queryNode;
            if (pNode.val == 1 && preStr.length() > 2) {
                words.add(preStr);
                nodes.add(pNode);
                pNode.val = -1;
            }
            for (int i = 0; i < XDELTA.length; i++) {
                xNeighbor = x + XDELTA[i];
                yNeighbor = y + YDELTA[i];
                if (validPos(xNeighbor, yNeighbor, board)
                        && !marked[xNeighbor][yNeighbor]) {
                    queryNode = dict.getNext(pNode, gameStr[xNeighbor][yNeighbor]);
                    if (queryNode != null) {
                        curStr = preStr + gameStr[xNeighbor][yNeighbor];
                        dfs(board, marked, xNeighbor, yNeighbor, queryNode, curStr);
                    }
                }
            }
            marked[x][y] = false;
        }
    View Code
  • 相关阅读:
    STM32使用定时器实现输入捕获
    Leetcode#101 Symmetric Tree
    Leetcode#100 Same Tree
    Leetcode#26 Remove Duplicates from Sorted Array
    Leetcode#27 Remove Element
    Leetcode#83 Remove Duplicates from Sorted List
    Leetcode#70 Climbing Stairs
    Leetcode#66 Plus One
    Leetcode#36 Valid Sudoku
    Leetcode#67 Add Binary
  • 原文地址:https://www.cnblogs.com/notTao/p/6389629.html
Copyright © 2011-2022 走看看