在数组中查找特定字符串的所有索引的更快方法

Posted

技术标签:

【中文标题】在数组中查找特定字符串的所有索引的更快方法【英文标题】:Faster way of finding all indices of specific string in an array 【发布时间】:2018-12-23 05:30:28 【问题描述】:

下面的代码用于查找字符串的所有索引,这些索引可能在数组中只出现一次,但代码不是很快。有人知道在数组中查找唯一字符串的更快更有效的方法吗?

using System;
using System.Collections.Generic;
using System.Linq;

public static class EM

    // Extension method, using Linq to find indices.
    public static int[] FindAllIndicesOf<T>(this IEnumerable<T> values, T val)
    
        return values.Select((b,i) => Equals(b, val) ? i : -1).Where(i => i != -1).ToArray();
    



public class Program

    public static string FindFirstUniqueName(string[] names)
    
        var results = new List<string>();
        for (var i = 0; i < names.Length; i++)
        
            var matchedIndices = names.FindAllIndicesOf(names[i]);
            if (matchedIndices.Length == 1)
            
                results.Add(names[matchedIndices[0]]);
                break;
            
        
        return results.Count > 0 ? results[0] : null;
    


    public static void Main(string[] args)
    
        Console.WriteLine("Found: " + FindFirstUniqueName(new[]
            
                "James",
                "Bill",
                "Helen",
                "Bill",
                "Helen",
                "Giles",
                "James",
            
        ));
    

【问题讨论】:

这个 O(n^2)。为什么不将每个名称插入 Hashmap (name->numOfRecurrence) 然后返回映射到 1 的所有名称 - 这将是 O(n) 你可以试试names.GroupBy(x =&gt; x).Where(grp =&gt; grp.Count() == 1).Select(grp =&gt; grp.First()).ToList() @DavidWinder 听起来不错,但是如何创建一个以名称为键、重复为值的 HashMap(字典),最好没有循环?例如。类似于var dictionary = sequence.ToDictionary(item =&gt; item.Key, item =&gt; item.Value) @BadmintonCat 不管你做什么,你能得到的都是O(n),所以即使你使用Linq,在幕后它也会使用一个循环。 【参考方案1】:

您的解决方案具有 O(n^2) 复杂度。您可以使用 Hash-Map 将其改进为 O(n)。

考虑一个哈希映射,其中每个名称在原始列表中都有重复次数。现在您所要做的就是检查字典中的所有键(又名哈希映射)并返回所有等于 1 的值。请注意,检查此字典中的所有键小于 o(n),因为它不能容纳大于 n名字。

要在 C# 中实现此字典,请执行以下操作:

List<string> stuff = new List<string>();
var groups = stuff.GroupBy(s => s).Select(
    s => new  Stuff = s.Key, Count = s.Count() );
var dictionary = groups.ToDictionary(g => g.Stuff, g => g.Count);

Taken from here 或按照juharr 的建议

O(n) 是最低要求,因为您必须至少检查所有名称一次。

【讨论】:

感谢您的见解!这很有帮助。 这没有意义,函数在代码中是独立的,它们可能应该保持独立 什么意思?能详细点吗?

以上是关于在数组中查找特定字符串的所有索引的更快方法的主要内容,如果未能解决你的问题,请参考以下文章

Java语言中,怎么样查找一个特定的字符串,并返回它的索引位置

如何在JavaScript中查找一个字符串中所有出现的索引?

数据库索引

Pymongo 使用数组索引查找查询失败,因为键只能是字符串

不改变原数组的方法

所有数据类型的内置方法