我正在编写代码片段以获取给定字符串中的所有子字符串。
以下是我使用的代码
var stringList = new List<string>();
for (int length = 1; length < mainString.Length; length++)
{
for (int start = 0; start <= mainString.Length - length; start++)
{
var substring = mainString.Substring(start, length);
stringList.Add(substring);
}
}
对我而言看起来并不那么好,有两个for循环。有没有其他方法可以通过更好的时间复杂度实现这一目标。
我坚持认为,为了获得子串,我肯定需要两个循环。还有其他方法可以研究吗?
答案 0 :(得分:6)
字符串中的子串数是O(n^2)
,因此在另一个中的一个循环是您可以做的最好的。你的代码结构是正确的。
以下是我将如何表达您的代码:
void Main()
{
var stringList = new List<string>();
string s = "1234";
for (int i=0; i <s.Length; i++)
for (int j=i; j < s.Length; j++)
stringList.Add(s.Substring(i,j-i+1));
}
答案 1 :(得分:2)
在某些情况下,您可以通过减少对象分配来显着提高执行速度。在这种情况下,使用单个char[]
和ArraySegment<of char>
来处理子字符串。这也将导致使用更少的地址空间并减少垃圾收集器负载。
Microsoft Docs上Using the StringBuilder Class in .NET页面的相关摘录:
String对象是不可变的。每次使用System.String类中的一个方法时,都会在内存中创建一个新的字符串对象,这需要为该新对象分配新的空间。在需要对字符串执行重复修改的情况下,与创建新String对象相关的开销可能会很昂贵。
示例实施:
static List<ArraySegment<char>> SubstringsOf(char[] value)
{
var substrings = new List<ArraySegment<char>>(capacity: value.Length * (value.Length + 1) / 2 - 1);
for (int length = 1; length < value.Length; length++)
for (int start = 0; start <= value.Length - length; start++)
substrings.Add(new ArraySegment<char>(value, start, length));
return substrings;
}
有关详情,请查看Microsoft文档上的Fundamentals of Garbage Collection页面,关于StackOverflow的what is the use of ArraySegment class?讨论,MSDN上的ArraySegment<T> Structure页面和MSDN上的List<T>.Capacity页面。
答案 2 :(得分:1)
您确实需要2个String mName = "",mAdd="",mPhn="",mSal="",mLea="";
if (getIntent().hasExtra("name")) {
mName = getIntent().getExtras().getString("name");
mAdd = getIntent().getExtras().getString("add");
mPhn = getIntent().getExtras().getString("phn");
mSal = getIntent().getExtras().getString("sal");
mLea = getIntent().getExtras().getString("lea");
}
name.setText(mName);
address.setText(mAdd);
contact.setText(mPhn);
salary.setText(mSal);
leaves.setText(mLea);
循环
for
更新
您无法改进迭代。
但是,您可以使用var input = "asd sdf dfg";
var stringList = new List<string>();
for (int i = 0; i < input.Length; i++)
{
for (int j = i; j < input.Length; j++)
{
var substring = input.Substring(i, j-i+1);
stringList.Add(substring);
}
}
foreach(var item in stringList)
{
Console.WriteLine(item);
}
数组和指针
答案 3 :(得分:0)
好吧,O(n**2)
时间复杂性是不可避免的,但是你可以尝试推动 space 消费。在许多情况下,您不希望所有子字符串具体化,例如List<string>
:
public static IEnumerable<string> AllSubstrings(string value) {
if (value == null)
yield break; // Or throw ArgumentNullException
for (int length = 1; length < value.Length; ++length)
for (int start = 0; start <= value.Length - length; ++start)
yield return value.Substring(start, length);
}
例如,让我们计算"abracadabra"
中从a
开始且长于3
个字符的所有子字符串。请注意,我们所要做的就是循环 over susbstrings ,不用将它们保存到列表中:
int count = AllSubstrings("abracadabra")
.Count(item => item.StartsWith("a") && item.Length > 3);
如果出于任何原因需要List<string>
,只需添加.ToList()
:
var stringList = AllSubstrings(mainString).ToList();