- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在为填字游戏编写一个解算器,它读取字典文件并给定一个模式,返回符合该模式的所有单词的列表。我的功能可以正常工作,但我需要它才能更快地工作。我创建了一个 HashMap,其中单词的长度作为键,单词的 ArrayList 作为值。有什么方法可以更快地读取 ArrayList 还是有更好的数据结构可供使用?
import java.util.*;
public class CWSolution {
//create the data structure that will store the dictionary
private HashMap<Integer,ArrayList<String>> db;
public CWSolution(List<String> allWords)
{
//construct the background structure
//Create hashmap
db = new HashMap<Integer,ArrayList<String>>();
//go through each word
for(String item : allWords ){
//if the db does not contain a listing for this word length, create one
if(!db.containsKey(item.length())){
ArrayList<String> temp = new ArrayList<String>();
temp.add(item);
db.put(item.length(), temp);
}
//if it does contain a listing for this word length, add this word to it
else{
ArrayList<String> temp = db.get(item.length());
temp.add(item);
db.put(item.length(), temp);
}
}
}
public List<String> solutions(String pattern, int maxRequired)
{
//actually look for each pattern
//create the structures we need
List<String> answer = new ArrayList<String>();
//get the relevant array list
ArrayList<String> temp = db.get(pattern.length());
//go through the array list word by word
for(String item : temp ){
//see if the pattern matches the word, if it does add it to the list, otherwise skip it
if(matchPattern(pattern, item)){
answer.add(item);
}
//if we reach the required size return it, otherwise keep going
if(answer.size() == maxRequired){
return answer;
}
}
return answer;
}
private boolean matchPattern(String pattern, String word){
//TODO implement this function
//check the word against the pattern
char star = "*".charAt(0);
for(int i=0;i<pattern.length();i++){
if(pattern.charAt(i) != star){
if(pattern.charAt(i) != word.charAt(i)){
return false;
}
}
}
return true;
}
}
编辑:添加更多信息以使其更清楚。
一些评论对此进行了辩论,所以我想澄清一下,我是数据结构类(class)的学生,所以我知道的只有这么多,但我们快到学期末了,所以我有一个基本数据结构的好主意。
此外,我并不关心优化 CWSolution() 方法,而是关心优化 solutions() 方法。速度测试如下,我真正关心的是Time2。这是找到匹配词所花费的时间,而不是创建结构所花费的时间。
import java.util.Date;
import java.util.List;
public class CWSpeedTest {
public static void main(String[] args){
try{
FileParser fp = new FileParser("TWL06.txt");
List<String> solutions = null;
//Change this to change the pattern
String pattern = "*S**";
//Change this to change the max solutions
int maxSolns = 2000;
List<String> dict = fp.getAllWords();
Date d1 = new Date();
CWSolution c = new CWSolution(dict);
Date d2 = new Date();
for (int i = 0; i < 1000; i++)
solutions = c.solutions(pattern,maxSolns);
Date d3 = new Date();
System.out.println("Time 1: " + (d2.getTime() - d1.getTime()));
System.out.println("Time 2: " + (d3.getTime() - d2.getTime()));
System.out.println("For the pattern: " + pattern);
System.out.println("With max solutions: " + maxSolns);
System.out.println(solutions);
}catch (Exception e){
e.printStackTrace();
}
}
}
最佳答案
这里是对所有位置和字符使用索引的算法的完全重写。首先,该算法在模式中的指定位置找到具有指定字符的单词的最短列表。然后它计算所有其他单词列表的横截面(模式中每个非星号字符一个列表)。
import java.util.*;
public class CWSolution {
class FixLengthDB {
// Index -> Letter -> All word with the Letter at Index
HashMap<Integer, HashMap<Character, Set<String>>> indexLetterDb = new HashMap<>();
public void storeWord(String word) {
int l = word.length();
for (int i = 0; i < l; i++) {
HashMap<Character, Set<String>> letterDb = indexLetterDb.get(i);
if (letterDb == null) {
letterDb = new HashMap<>();
indexLetterDb.put(i, letterDb);
}
Set<String> list = letterDb.get(word.charAt(i));
if (list == null) {
list = new HashSet<>();
letterDb.put(word.charAt(i), list);
}
list.add(word);
}
}
public Set<String> getList(int i, char c) {
HashMap<Character, Set<String>> letterDb = indexLetterDb.get(i);
if (letterDb == null) {
return null;
}
return letterDb.get(c);
}
}
//create the data structure that will store the dictionary
private HashMap<Integer,FixLengthDB> db = new HashMap<>();
private List<String> allWords;
public CWSolution(List<String> allWords)
{
//construct the background structure
this.allWords = allWords;
//go through each word
for(String item : allWords) {
FixLengthDB fixLengthDB = db.get(item.length());
if (fixLengthDB == null) {
fixLengthDB = new FixLengthDB();
db.put(item.length(), fixLengthDB);
}
fixLengthDB.storeWord(item);
}
}
public List<String> solutions(String pattern, int maxRequired)
{
FixLengthDB fixLengthDB = db.get(pattern.length());
if (fixLengthDB == null) {
return new ArrayList<>();
}
Set<String> shortList = null;
int shortListIndex = 0;
int l = pattern.length();
for (int i = 0; i < l; i++) {
if (pattern.charAt(i) == '*') {
continue;
}
Set<String> set = fixLengthDB.getList(i, pattern.charAt(i));
if (set == null) {
return new ArrayList<>();
}
if (shortList == null || shortList.size() > set.size()) {
shortList = set;
shortListIndex = i;
}
}
if (shortList == null) {
return allWords;
}
HashSet<String> result = new HashSet<>(shortList);
for (int i = 0; i < l; i++) {
if (i == shortListIndex || pattern.charAt(i) == '*') {
continue;
}
Set<String> set = fixLengthDB.getList(i, pattern.charAt(i));
result.retainAll(set);
}
// TODO truncate result list according to 'maxRequired' parameter
return new ArrayList<>(result);
}
}
解释:该算法分两步进行
solutions(...)
)构建索引:索引为每个word-length/character-index/character维护字符串集。
这是我们如何将单词添加到索引中
Add word: fun
|||
||\--- (length: 3, position 3, character 'n') -> set{"fun"})
|\---- (length: 3, position 2, character 'u') -> set{"fun"})
\----- (length: 3, position 1, character 'f') -> set{"fun"})
Add word: run
|||
||\--- (length: 3, position 3, character 'n') -> set{"fun, run"})
|\---- (length: 3, position 2, character 'u') -> set{"fun, run"})
\----- (length: 3, position 1, character 'r') -> set{"run"})
Add word: raw
|||
||\--- (length: 3, position 3, character 'w') -> set{"raw"})
|\---- (length: 3, position 2, character 'a') -> set{"raw"})
\----- (length: 3, position 1, character 'r') -> set{"run, raw"})
Add word: rar
|||
||\--- (length: 3, position 3, character 'r') -> set{"rar"})
|\---- (length: 3, position 2, character 'a') -> set{"raw, rar"})
\----- (length: 3, position 1, character 'r') -> set{"run, raw, rar"})
添加四个词(fun、run、raw、rar)后的数据库是
(length: 3, position 1, character 'f') -> set{"fun"})
(length: 3, position 1, character 'r') -> set{"run, raw, rar"})
(length: 3, position 2, character 'u') -> set{"fun, run"})
(length: 3, position 2, character 'a') -> set{"raw, rar"})
(length: 3, position 3, character 'w') -> set{"raw"})
(length: 3, position 3, character 'r') -> set{"rar"})
(length: 3, position 3, character 'n') -> set{"fun, run"})
使用索引:让我们如何匹配模式 ru*
首先让我们在索引中找到匹配的最小集合。我们只有 2 个非明星角色,所以我们只检查两组
1: (length: 3, position 1, character 'r') -> set{"run, raw, rar"})
2: (length: 3, position 2, character 'u') -> set{"fun, run"})
最小的集合是#2 {"fun, run"}
。现在我们遍历所有其他匹配集(在我们的例子中是集#1)并计算交集:
{"fun, run"} cross {"run, raw, rar"} => {"run"}
结果是{"run"}
。
关于java - 更快地读取 ArrayList,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20505596/
好吧,我知道这个问题已经被问了无数次了。但是,对于我在谷歌搜索中似乎无法找到的问题,我还有一个小补充。 我当然不是 FFMPEG 的专家……我一直在使用 FFMPEG 的标准加速/减速模板,我正在使用
考虑这三个文档... [ { _id: "...", _rev: "...", title: "Foo", body: "...
我想知道访问我的全局变量的最快方法...它们只会在 Beta 测试阶段发生变化。在我们上线之前。从那时起,它们将永远不会改变。 我认为从 web.config 中获取内容会产生开销,而且编写 App.
这个问题在这里已经有了答案: 11 年前关闭。 Possible Duplicate: Is there a performance difference between BETWEEN and IN
我很想知道对通常作为查询目标的数字列进行分区是否有性能优势。目前我有一个包含约 5000 万条记录的物化 View 。当使用常规 b 树索引并按此数字列搜索时,我得到的成本为 7,查询结果大约需要 0
我需要编写一个库,它执行许多远程 HTTP 调用来获取内容。我可以按照描述做here ,但是有没有更好的方法(在性能方面)如何做到这一点?如果我按照示例中所述进行操作,我总是会创建一个 URL 对象,
该代码非常不言自明。只是有很多我需要独立随机化的范围。例如,范围('W1:W4')不应与范围('W5:W8')混淆,因此我不能只是随机化范围('W1:W80')。任何帮助或建议都会很棒!多谢。目前,代
我正在使用 ADT 模拟器。我在我的模拟器中使用默认的 Android 虚拟设备。我创建了一个版本 4.0.3。 问题 太慢了。有时我在尝试更改 fragment 时会收到加载点击。 我使用的代码是有
我正在尝试获取一个包含三个表中的信息的数组。结果应该是一个数组,我可以在其中循环遍历第一个表、第二个表中的相关行以及第三个表到第二个表中的相关行。目前,我有三个独立的 SQL 查询,然后将它们重组为一
我已经学会了两种在服务器上上传图像的方法(可能还有更多..)。 1) 创建 NSData 并将其添加到请求正文中 2)创建字节数组并像简单数组一样以json形式发送 1) 创建 NSData 并将其添
我有一个 UItextview,我可以在里面写入数据类,我可以在我的 View 中的任何地方提供数据,在 ViewDidAppear 函数中我传递了我的数据,但它有点慢。文本在 0.2-0.3 秒后出
如何为 discoverAllContactUserInfosWithCompletionHandler 创建优先级高于默认值的 CKOperation? 我找不到不使用 [[CKContainer
我在 unix 模块下编写了一个内核级函数,用于对系统负载进行采样。我在 clock.c 下的 clock() 中调用示例函数,以在每个时钟(例如,我的系统上每 10 毫秒)拍摄系统负载的快照。有没有
我正在制作一个应用程序,该应用程序将根据变量的值使用鼠标/键盘(宏)模拟操作。 这里有我制作的 de 扫描代码: void ReadMemory(int value){ DWORD p
我想知道在计算上调用嵌套在对象中的函数的最快方法是什么,所以我做了一个快速的 jsPerf.com 基准测试,其中我考虑了三种可能性——从数组中调用函数,从“核心”中调用函数对象和函数对象: var
我用 php 做了一个图像缩放器。调整图像大小时,它会缓存一个具有新尺寸的新 jpg 文件。下次您调用确切的 img.php?file=hello.jpg&size=400 时,它会检查是否已经创建了
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Which is best for data store Struct/Classes? 考虑我有一个 Em
我正在尝试为多组列自动计算每行的平均分数。例如。一组列可以代表不同比例的项目。这些列也被系统地命名 (scale_itemnumber)。 例如,下面的虚拟数据框包含来自三个不同比例的项目。(可能会出
所以我知道散列图使用桶和散列码等等。根据我的经验,Java 哈希码并不小,但通常很大,所以我假设它没有在内部建立索引。除非哈希码质量很差导致桶长度和桶数量大致相等,否则 HashMap 比名称-> 值
假设我有一个非常缓慢和大的 for 循环。 如何将其拆分为多个线程以使其运行速度更快? for (int a = 0; a { slowMet
我是一名优秀的程序员,十分优秀!