- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我希望能为我遇到的这个问题找到一些方向。两周以来我一直在为此苦思冥想。本质上,我要编写一个函数,public static int FindWords(char[][] puzzle)
,其中给定一个 2D char 数组,我可以找到给定字符串集出现的次数.鉴于:
public static class PuzzleSolver
{
public static string[] DICTIONARY = {"OX","CAT","TOY","AT","DOG","CATAPULT","T"};
static bool IsWord(string testWord)
{
if (DICTIONARY.Contains(testWord))
return true;
return false;
}
}
例如像这样的二维数组:
public static char[][] puzzle = {{'C','A','T'},
{'X','Z','T'},
{'Y','O','T'}};
对于以下实例将返回 8:(AT、AT、CAT、OX、TOY、T、T、T)因为我们将水平、垂直、对角线和反向搜索所有相同的方向。
我的方法是访问数组中的每个字符,然后使用 SearchChar
函数搜索所有可能的方向...
public static int FindWords(char[][] puzzle){
int arrayRow = puzzle.length;
int arrayCol = puzzle[0].length;
int found = 0;
for(int i = 0; i < arrayRow; i++){
for(int j = 0; j < arrayCol; j++){
found += SearchChar(i,j);
}
}
return found;
}
看起来像这样:
public static int SearchChar(int row, int col){
if(row < 0 || col < 0 || row > puzzle.length || col > puzzle[0].length)//Is row or col out of bounds?
return 0;
if(IsWord(puzzle[row][col]))
return 1;
return 0;
}
从概念上讲,我觉得我需要某种递归函数来处理这个问题,但我似乎无法理解它。我什至不知道这是否是正确的方法。我一直在玩弄 StringBuilder
追加,但我仍在为此苦苦挣扎。我认为这个递归函数需要以 puzzle[0][0]
(或“C”)为例,看看它是否在字典中。接着是 puzzle[0][0] + puzzle[0][1]
(或“CA”),最后是 puzzle[0][0] + puzzle[0][1 ] + puzzle[0][2]
(或“CAT”)。然后必须垂直和对角地穿同样的衣服。我在尝试返回到 SearchChar
函数时遇到问题,将位置更改附加到原始字符,以便我可以查看它是否在 DICTIONARY
中。
抱歉,如果这有点罗嗦,但我只是想给人一种印象,我实际上正在努力解决这个问题。不仅仅是一些懒惰的程序员将一些问题复制并粘贴到这里以供其他人解决。在此先感谢您的帮助!
最佳答案
我将逐步向您展示如何解决这个问题。
要做到这一点,我们必须从拼图中的任何地方开始,向所有方向(除了前面的点
)移动,以生成所有可能的单词;
我认为Trie
是一个不错的选择,适合在这种情况下使用。
选择Trie
最重要的原因是,在搜索过程中,我们可以很容易地测试一个词是否存在于我们的字典中,或者是否有以通过拼图搜索生成的词开头的词或不。因此,我们可以决定是否继续搜索。
这将为我们节省大量时间并有助于正确生成单词。否则,我们将陷入死循环...
Tire
有多种实现,但我编写了自己的 CharTrie
:
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
/**
* @author FaNaJ
*/
public final class CharTrie {
/**
* Pointer to root Node
*/
private final Node root = new Node();
/**
* Puts the specified word in this CharTrie and increases its frequency.
*
* @param word word to put in this CharTrie
* @return the previous frequency of the specified word
*/
public int put(String word) {
if (word.isEmpty()) {
return 0;
}
Node current = root;
for (int i = 0; i < word.length(); i++) {
current = current.getChildren().computeIfAbsent(word.charAt(i), ch -> new Node());
}
return current.getAndIncreaseFrequency();
}
/**
* @param word the word whose frequency is to be returned
* @return the current frequency of the specified word or -1 if there isn't such a word in this CharTrie
*/
public int frequency(String word) {
if (word.isEmpty()) {
return 0;
}
Node current = root;
for (int i = 0; i < word.length() && current != null; i++) {
current = current.getChildren().get(word.charAt(i));
}
return current == null ? -1 : current.frequency;
}
/**
* @param word the word whose presence in this CharTrie is to be tested
* @return true if this CharTrie contains the specified word
*/
public boolean contains(String word) {
return frequency(word) > 0;
}
/**
* @return a CharTrie Iterator over the Nodes in this CharTrie, starting at the root Node.
*/
public Iterator iterator() {
return new Iterator(root);
}
/**
* Node in the CharTrie.
* frequency-children entry
*/
private static final class Node {
/**
* the number of occurrences of the character that is associated to this Node,
* at certain position in the CharTrie
*/
private volatile int frequency = 0;
private static final AtomicIntegerFieldUpdater<Node> frequencyUpdater
= AtomicIntegerFieldUpdater.newUpdater(Node.class, "frequency");
/**
* the children of this Node
*/
private Map<Character, Node> children;
public Map<Character, Node> getChildren() {
if (children == null) {
children = new ConcurrentHashMap<>();
}
return children;
}
/**
* Atomically increments by one the current value of the frequency.
*
* @return the previous frequency
*/
private int getAndIncreaseFrequency() {
return frequencyUpdater.getAndIncrement(this);
}
}
/**
* Iterator over the Nodes in the CharTrie
*/
public static final class Iterator implements Cloneable {
/**
* Pointer to current Node
*/
private Node current;
private Iterator(Node current) {
this.current = current;
}
/**
* Returns true if the current Node contains the specified character in its children,
* then moves to the child Node.
* Otherwise, the current Node will not change.
*
* @param ch the character whose presence in the current Node's children is to be tested
* @return true if the current Node's children contains the specified character
*/
public boolean next(char ch) {
Node next = current.getChildren().get(ch);
if (next == null) {
return false;
}
current = next;
return true;
}
/**
* @return the current frequency of the current Node
*/
public int frequency() {
return current.frequency;
}
/**
* @return the newly created CharTrie Iterator, starting at the current Node of this Iterator
*/
@Override
@SuppressWarnings("CloneDoesntCallSuperClone")
public Iterator clone() {
return new Iterator(current);
}
}
}
和 WordGenerator
:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
import java.util.function.BiConsumer;
/**
* @author FaNaJ
*/
public final class WordGenerator {
private WordGenerator() {
}
public static void generate(char[][] table, CharTrie.Iterator iterator, BiConsumer<String, Integer> action) {
final ForkJoinPool pool = ForkJoinPool.commonPool();
final VisitorContext ctx = new VisitorContext(table, action);
for (int y = 0; y < table.length; y++) {
for (int x = 0; x < table[y].length; x++) {
pool.invoke(new Visitor(new Point(x, y), null, "", iterator.clone(), ctx));
}
}
}
private static final class VisitorContext {
private final char[][] table;
private final BiConsumer<String, Integer> action;
private VisitorContext(char[][] table, BiConsumer<String, Integer> action) {
this.table = table;
this.action = action;
}
private boolean validate(Point point) {
Object c = null;
try {
c = table[point.getY()][point.getX()];
} catch (ArrayIndexOutOfBoundsException ignored) {
}
return c != null;
}
}
private static final class Visitor extends RecursiveAction {
private final Point current;
private final Point previous;
private final CharTrie.Iterator iterator;
private final VisitorContext ctx;
private String word;
private Visitor(Point current, Point previous, String word, CharTrie.Iterator iterator, VisitorContext ctx) {
this.current = current;
this.previous = previous;
this.word = word;
this.iterator = iterator;
this.ctx = ctx;
}
@Override
protected void compute() {
char nextChar = ctx.table[current.getY()][current.getX()];
if (iterator.next(nextChar)) {
word += nextChar;
int frequency = iterator.frequency();
if (frequency > 0) {
ctx.action.accept(word, frequency);
}
List<Visitor> tasks = new ArrayList<>();
for (Direction direction : Direction.values()) {
Point nextPoint = direction.move(current);
if (!nextPoint.equals(previous) && ctx.validate(nextPoint)) {
tasks.add(new Visitor(nextPoint, current, word, iterator.clone(), ctx));
}
}
invokeAll(tasks);
}
}
}
}
请注意,我使用了 ForkJoinPool
和 RecursiveAction
以加快搜索速度。
了解更多:
其余类(class):
解谜
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
import java.util.stream.Stream;
/**
* @author FaNaJ
*/
public final class PuzzleSolver {
private final CharTrie dictionary;
public enum OrderBy {FREQUENCY_IN_DICTIONARY, FREQUENCY_IN_PUZZLE}
public PuzzleSolver(CharTrie dictionary) {
this.dictionary = dictionary;
}
public CharTrie getDictionary() {
return dictionary;
}
public Stream<Word> solve(char[][] puzzle) {
return solve(puzzle, OrderBy.FREQUENCY_IN_DICTIONARY);
}
public Stream<Word> solve(char[][] puzzle, OrderBy orderBy) {
Stream<Word> stream = null;
switch (orderBy) {
case FREQUENCY_IN_DICTIONARY: {
final Map<String, Integer> words = new ConcurrentHashMap<>();
WordGenerator.generate(puzzle, dictionary.iterator(), words::put);
stream = words.entrySet().stream()
.map(e -> new Word(e.getKey(), e.getValue()));
break;
}
case FREQUENCY_IN_PUZZLE: {
final Map<String, AtomicInteger> words = new ConcurrentHashMap<>();
BiConsumer<String, Integer> action = (word, frequency) -> words.computeIfAbsent(word, s -> new AtomicInteger()).getAndIncrement();
WordGenerator.generate(puzzle, dictionary.iterator(), action);
stream = words.entrySet().stream()
.map(e -> new Word(e.getKey(), e.getValue().get()));
break;
}
}
return stream.sorted((a, b) -> b.compareTo(a));
}
}
点
import java.util.Objects;
/**
* @author FaNaJ
*/
public final class Point {
private final int x;
private final int y;
public Point() {
this(0, 0);
}
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
@Override
public int hashCode() {
return x * 31 + y;
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
Point that = (Point) obj;
return x == that.x && y == that.y;
}
@Override
public String toString() {
return "[" + x + ", " + y + ']';
}
}
Word
/**
* @author FaNaJ
*/
public final class Word implements Comparable<Word> {
private final String value;
private final int frequency;
public Word(String value, int frequency) {
this.value = value;
this.frequency = frequency;
}
public String getValue() {
return value;
}
public int getFrequency() {
return frequency;
}
@Override
public int hashCode() {
return value.hashCode() * 31 + frequency;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Word that = (Word) o;
return frequency == that.frequency && value.equals(that.value);
}
@Override
public String toString() {
return "{" +
"value='" + value + '\'' +
", frequency=" + frequency +
'}';
}
@Override
public int compareTo(Word o) {
return Integer.compare(frequency, o.frequency);
}
}
方向
/**
* @author FaNaJ
*/
public enum Direction {
UP(0, 1), UP_RIGHT(1, 1), UP_LEFT(-1, 1),
RIGHT(1, 0), LEFT(-1, 0),
DOWN(0, -1), DOWN_RIGHT(1, -1), DOWN_LEFT(-1, -1);
private final int x, y;
Direction(int x, int y) {
this.x = x;
this.y = y;
}
public Point move(Point point) {
return new Point(point.getX() + x, point.getY() + y);
}
}
/**
* @author FaNaJ
*/
public class Test {
public static String[] DICTIONARY = {"OX", "CAT", "TOY", "AT", "DOG", "CATAPULT", "T", "AZOYZACZOTACXY"};
public static void main(String[] args) {
CharTrie trie = new CharTrie();
for (String word : DICTIONARY) {
trie.put(word);
}
PuzzleSolver solver = new PuzzleSolver(trie);
char[][] puzzle = {
{'C', 'A', 'T'},
{'X', 'Z', 'T'},
{'Y', 'O', 'T'}
};
solver.solve(puzzle, PuzzleSolver.OrderBy.FREQUENCY_IN_PUZZLE).forEach(System.out::println);
}
}
输出:
{value='T', frequency=3}
{value='AT', frequency=2}
{value='CAT', frequency=2}
{value='TOY', frequency=2}
{value='OX', frequency=1}
{value='AZOYZACZOTACXY', frequency=1}
关于java - 在二维字符数组中搜索事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33688290/
我正在尝试将 WPF CodeBehid 事件(如 Event、Handler、EventSetter)转换为 MVVM 模式。我不允许使用 System.Windows.Controls,因为我使用
我可能误解了 Backbone 中的事件系统,但是当我尝试以下代码时什么也没有发生。当我向 Backbone.Events 扩展对象添加新属性时,它不应该触发某种更改、更新或重置事件吗?就像模型一样吗
我遇到了一个简单的问题,就是无法弄清楚为什么它不起作用。我有一个子组件“app-buttons”,其中我有一个输入字段,我想听,所以我可以根据输入值过滤列表。 如果我将输入放在我有列表的根组件中,一切
System.Timers.Timer 的 Elapsed 事件实际上与 System.Windows.Forms.Timer 的 Tick 事件相同吗? 在特定情况下使用其中一种比使用另一种有优势吗
嗨,这个 javascript 代码段是什么意思。(evt) 部分是如此令人困惑.. evt 不是 bool 值。这个怎么运作? function checkIt(evt) { evt
我正在使用jquery full calendar我试图在事件被删除时保存它。 $('calendar').fullCalendar ({
我有两个链接的鼠标事件: $('body > form').on("mousedown", function(e){ //Do stuff }).on("mouseup", function(
这是我的代码: $( '#Example' ).on( "keypress", function( keyEvent ) { if ( keyEvent.which != 44 ) {
我尝试了 dragOver 事件处理程序,但它没有正常工作。 我正在研究钢琴,我希望能够弹奏音符,即使那个键上没有发生鼠标按下。 是否有事件处理程序? 下面是我正在制作的钢琴的图片。 最佳答案 您应该
当悬停在相邻文本上时,我需要使隐藏按钮可见。这是通过 onMouseEnter 和 onMouseLeave 事件完成的。但是当点击另外的文本时,我需要使按钮完全可见并停止 onMouseLeave
我有ul标签内 div标签。我申请了mouseup事件 div标记和 click事件 ul标签。 问题 每当我点击 ul标签,然后都是 mouseup和 click事件被触发。 我想要的是当我点击 u
我是 Javascript 和 jQuery 的新手,所以我有一个非常愚蠢的疑问,请耐心等待 $(document).click(function () { alert("!"); v
我有一个邮政编码解析器,我正在使用 keyup 事件处理程序来跟踪输入长度何时达到 5,然后查询服务器以解析邮政编码。但是我想防止脚本被不必要地调用,所以我想知道是否有一种方法可以跟踪 keydown
使用事件 API,我有以下代码来发布带有事件照片的事件 $facebook = new Facebook(array( "appId" => "XXX", "se
首次加载 Microsoft Word 时,既不会触发 NewDocument 事件也不会触发 DocumentOpen 事件。当 Word 实例已打开并打开新文档或现有文档时,这些事件会正常触发。
我发现了很多相关问题(这里和其他地方),但还没有具体找到这个问题。 我正在尝试监听箭头键 (37-40) 的按键事件,但是当以特定顺序使用箭头键时,后续箭头不会生成“按键”事件。 例子: http:/
给定的 HTML: 和 JavaScript 的: var $test = $('#test'); $test.on('keydown', function(event) { if (eve
我是 Node.js 的新手,希望使用流运行程序。对于其他程序,我必须同时启动一个服务器(mongodb、redis 等),但我不知道我是否应该用这个运行一个服务器。请让我知道我哪里出了问题以及如何纠
我正在尝试使用 Swift 和 Cocoa 创建一个适用于 OS X 的应用程序。我希望应用程序能够响应关键事件,而不将焦点放在文本字段上/文本字段中。我在 Xcode 中创建了一个带有 Storyb
我有以下代码: (function(w,d,s,l,i){ w[l]=w[l]||[];w[l].push({
我是一名优秀的程序员,十分优秀!