You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于链表的词建议程序如何降低执行耗时?

词建议程序性能优化方案(针对链表查找瓶颈)

核心问题分析

当前程序处理3MB文本耗时12分钟,主要瓶颈在于contains方法遍历整个链表查找词对,时间复杂度为O(n),随着词库规模增长,查找耗时会急剧增加。此外代码中存在语法错误,会导致大量无效插入,进一步拖慢性能。


优化步骤

1. 修复致命语法错误

原代码中if(myList.contains(prevWord, currWord));末尾多了分号,导致else分支永远执行,大量重复词对被插入链表,直接加剧性能问题。修正后代码:

if(myList.contains(prevWord, currWord)) {
    // contains方法已处理order自增,无需额外操作
} else {
    myList.insertTail(prevWord, currWord);
}

2. 优化停用词查找

如果停用词使用ArrayList存储,contains方法是O(n)复杂度,改为HashSet可将其降为O(1):

Set<String> stopWord = new HashSet<>();
while(stopScan.hasNext()) {
    // 提前转小写,避免后续重复转换
    stopWord.add(stopScan.next().toLowerCase());
}

3. 预编译正则表达式减少开销

文本清理时的replaceAll会重复编译正则表达式,预编译后可节省大量CPU时间:

import java.util.regex.Pattern;

// 预编译正则
Pattern cleanPattern = Pattern.compile("[^a-z ]");

// 替换原文本处理逻辑
prevWord = cleanPattern.matcher(textScan.next().toLowerCase()).replaceAll("");
currWord = cleanPattern.matcher(textScan.next().toLowerCase()).replaceAll("");

4. 引入哈希表加速词对查找(核心优化)

由于必须使用自定义链表,我们可以用HashMap缓存词对与对应节点的映射,将contains方法的O(n)遍历改为O(1)查找:

修改链表类实现:
import java.util.HashMap;
import java.util.Objects;

// 自定义词对类,用于哈希表的键
class WordPair<T> {
    private final T first;
    private final T second;

    public WordPair(T first, T second) {
        this.first = first;
        this.second = second;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        WordPair<?> pair = (WordPair<?>) o;
        return Objects.equals(first, pair.first) && Objects.equals(second, pair.second);
    }

    @Override
    public int hashCode() {
        return Objects.hash(first, second);
    }
}

class CustomLinkedList<T> {
    private Node<T> head;
    private Node<T> tail;
    // 新增哈希表缓存词对与节点的映射
    private HashMap<WordPair<T>, Node<T>> pairNodeMap;

    public CustomLinkedList() {
        this.pairNodeMap = new HashMap<>();
    }

    // 优化后的contains方法
    boolean contains(T wordOne, T wordTwo) {
        WordPair<T> pair = new WordPair<>(wordOne, wordTwo);
        Node<T> targetNode = pairNodeMap.get(pair);
        if (targetNode != null) {
            targetNode.order++;
            return true;
        }
        return false;
    }

    // 同步维护哈希表的插入方法
    void insertTail(T wordOne, T wordTwo) {
        WordPair<T> pair = new WordPair<>(wordOne, wordTwo);
        // 双重校验避免重复插入
        if (pairNodeMap.containsKey(pair)) {
            pairNodeMap.get(pair).order++;
            return;
        }

        Node<T> newNode = new Node<>(wordOne, wordTwo);
        if (tail == null) {
            head = newNode;
            tail = newNode;
        } else {
            newNode.prev = tail;
            tail.next = newNode;
            tail = newNode;
        }
        pairNodeMap.put(pair, newNode);
    }

    // 排序方法中同步更新哈希表映射
    void sort() {
        Node<T> temp = head;
        while(temp != null) {
            if(temp.prev != null && temp.order > temp.prev.order) {
                swap(temp, temp.prev);
                temp = temp.prev;
            } else {
                temp = temp.next;
            }
        }
    }

    // 交换节点内容并同步更新哈希表
    private void swap(Node<T> a, Node<T> b) {
        // 交换节点的词对与计数
        T tempWordOne = a.wordOne;
        T tempWordTwo = a.wordTwo;
        int tempOrder = a.order;

        a.wordOne = b.wordOne;
        a.wordTwo = b.wordTwo;
        a.order = b.order;

        b.wordOne = tempWordOne;
        b.wordTwo = tempWordTwo;
        b.order = tempOrder;

        // 更新哈希表中的映射
        WordPair<T> pairA = new WordPair<>(a.wordOne, a.wordTwo);
        WordPair<T> pairB = new WordPair<>(b.wordOne, b.wordTwo);
        pairNodeMap.put(pairA, a);
        pairNodeMap.put(pairB, b);
    }

    static class Node<T> {
        T wordOne;
        T wordTwo;
        int order = 1;
        Node<T> prev;
        Node<T> next;

        public Node(T wordOne, T wordTwo) {
            this.wordOne = wordOne;
            this.wordTwo = wordTwo;
        }
    }
}

优化效果说明

通过上述改动:

  • 停用词查找、词对查找的时间复杂度均从O(n)降至O(1)
  • 避免了无效的重复节点插入
  • 减少了正则表达式重复编译的开销
    处理3MB文本的耗时会大幅降低,可远低于当前的12分钟。

内容的提问来源于stack exchange,提问作者blurpex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 02:51:06