【LeetCode】每日一题 面试题 17.17. 多次搜索

69 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第11天,点击查看活动详情

[面试题 17.17. 多次搜索](leetcode.cn/problems/th…)

给定一个较长字符串big和一个包含较短字符串的数组smalls,设计一个方法,根据smalls中的每一个较短字符串,对big进行搜索。输出smalls中的字符串在big里出现的所有位置positions,其中positions[i]为smalls[i]出现的所有位置。

「示例1:」
输入:
big = "mississippi"
smalls = ["is","ppi","hi","sis","i","ssippi"]
输出: [[1,4],[8],[],[3],[1,4,7,10],[5]]
「提示:」
0 <= len(big) <= 1000
0 <= len(smalls[i]) <= 1000
smalls的总字符数不会超过 100000。
你可以认为smalls中没有重复字符串。
所有出现的字符均为英文小写字母。

解题思路

1.对smalls所有字符串建立Trie,在节点中保存是否是字符串尾部isword,以及在smalls数组中的位置index
2.遍历big字符串,如果查找到节点为为字符串尾部isword,则根据索引index 添加到result数组中

代码实现

    /*
    * trie 节点
   */
   function TreeNode(val) {
     this.children = {};
     this.isword = false; //标记是否是字符串结尾
     this.index =-1;   //标记单词在数组中的位置
   }
​
   var Trie = function () {
     this.root = new  TreeNode();
     this.count = 0; //记录字符串的个数,用来给字符串节点标记次序
   }
   /**
    * Trie 树的插入
    * */
   Trie.prototype.insert= function (word) {
     if (!word) return;
     let  node = this.root;
     for (let  i=0 ;i <word.length;i++){
       if (!node.children[word[i]]){
         node.children[word[i]] = new TreeNode();
       }
       node = node.children[word[i]];
     }
     node.index = this.count;
     node.isword = true;
     this.count++;
   }
   /**
    * Trie 树的字符串搜索
    * */
   Trie.prototype.search=function (word) {
     if (!word) return false;
     let  node = this.root;
     for (let  i=0;i<word.length;i++){
       if (!node.children[word[i]]){
         node = node.children[word[i]];
       }else
       {
         return  false;
       }
     }
     return  node.isword;
   }
   /**
    * Trie 查找是否有已prefix开头的字符串
    * */
   Trie.prototype.startsWith = function(prefix) {
     if (!prefix)return  false;
     let node = this.root;
     for (let  i =0;i <prefix.length;i++){
       if (node.children[prefix[i]]){
         node = node.children[prefix[i]];
       }else
       {
         return  false;
       }
     }
     return true;
   };
   /**
    * @param {string} big
    * @param {string[]} smalls
    * @return {number[][]}
    */
   var multiSearch = function(big, smalls) {
     let  result = Array(smalls.length).fill(0).map(()=>[]); //预生成数组
     let maxLength = Math.max(...smalls.map(small=> small.length)); //计算smalls中字符串的最大长度
     let trie = new Trie(); //预建trie树
     //将smalls 字符串插入树中
     for (let i=0;i< smalls.length;i++){
       trie.insert(smalls[i]);
     }
​
     for (let i=0;i<big.length;i++){
       if(!trie.startsWith(big[i])) continue; //查找是否以 big[i] 开头的字符串,没有则跳过本次执行
       let str = big.slice(i,i+maxLength); 
       let  node = trie.root;
       for (let j=0;j<str.length;j++)
       {
         let  jchar = str[j];
         if (!node.children[jchar]){
           break;
         }
         node = node.children[jchar];
         if (node.isword){
           result[node.index].push(i);
         }
       }
     }
     return  result;
   };

如果你对这道题目还有疑问的话,可以在评论区进行留言;