如何解决我如何优化这段C#代码,使其运行时间不会太长?
任务是:
给出两个字符串数组,以确定相应的元素是否包含公共子字符串
我的代码是(给出了方法,我应该填写):
public static void commonSubstring(List<string> a,List<string> b) {
string[] listA = a.ToArray();
string[] listB = b.ToArray();
bool contains = false;
for(int i = 0; i < listA.Length; i++)
{
foreach(char c in listA[i])
{
foreach (char d in listB[i]) {
if (c == d) {
contains = true;
break;
}
}
if (contains) { break; }
}
if (contains == true) {
Console.WriteLine("YES");
contains = false;
} else {
Console.WriteLine("NO");
}
}
}
它可以通过大多数测试用例,但是在某些情况下,它表示运行时间太长(3秒以上),因此在有大量输入时。有谁知道我如何优化此代码以使其更快,以便在大输入量下花费不到3秒的时间?因此,基本上,如果a[i]
和b[i]
具有相同的字符,则打印YES,否则显示NO。
解决方法
每一个listA[i],listB[i]
都需要发生某些事情,这不是问题。但是,请仔细看一下这些嵌套循环:
foreach(char c in listA[i]) { foreach (char d in listB[i]) { if (c == d) { contains = true; break; } } if (contains) { break; } }
您已经发现我们真的只需要找到两个字符串中的字母,然后我们就有一个长度为1的公共子字符串(可能有一个更长的公共子字符串,但这与该问题无关,因为我们只需要知道它是否存在-您就应该不使用“最长公共子串”算法,这完全是过大的杀伤力)。通过比较字符的每种组合来完成。但是,还有一种选择:
使用字符串A中的字符创建一个HashSet。对于字符串B中的每个字符,检查它是否在该HashSet中。
操作数从字符串长度的 products 到字符串长度的 sum 。
,因此,基本上,如果a [i]和b [i]的字符为 常见,如果没有,则不。
您可以通过省略嵌套循环来对其进行优化
public static void commonSubstring(List<string> a,List<string> b)
{
string[] listA = a.ToArray();
string[] listB = b.ToArray();
for (int i = 0; i < listA.Length; i++)
{
if (HaveCharInCommon(listA[i],listB[i]))
{
Console.WriteLine("YES");
}
else
{
Console.WriteLine("NO");
}
}
}
private static bool HaveCharInCommon(string a,string b)
{
var set = new HashSet<char>(a);
foreach (var ch in b)
{
if (set.Contains(ch))
{
return true;
}
}
return false;
}
,
这是O(n * log n)版本,用于确定字符串是否具有共同的字符(子字符串):
Input: s1 s2 let ss1 = sort s1 (O(N log N) let ss2 = sort s2 (O(N log N) let l1 = length s1 (O(1) in C#,O(N) in C...) let l2 = length s2 let i1 = 0,i2 = 0 while (i1 < l1 and i2 < l2) { if ss1[i1] == ss2[i2] then return true if ss1[i1] < ss2[i2] then i1++,continue if ss1[i1] > ss2[i2] then i2++,continue } return false
总复杂度为O(N log N)(排序复杂度)。 我的系统上没有C#,很抱歉,我必须给您一个实现 而不是另一种语言。
(defun common-sub-string-p (s1 s2)
(let ((s1-sorted (sort s1 #'char-lessp))
(s2-sorted (sort s2 #'char-lessp))
(l1 (length s1))
(l2 (length s2)))
(labels ((compute (i1 i2)
(if (and (< i1 l1) (< i2 l2))
(let ((c1 (aref s1-sorted i1))
(c2 (aref s2-sorted i2)))
(cond
((eql c1 c2) t)
((char-lessp c1 c2) (compute (1+ i1) i2))
((char-lessp c2 c1) (compute i1 (1+ i2)))))
nil)))
(compute 0 0))))
还有很多方法可以做到这一点。例如,您可以创建2位集合,使用字符串的字符作为索引,然后为2个字符串中的每一个设置1位,测试它们是否具有公共子集。
如果将字符串限制为ascii编码(0..127),则这些位集可以是16个字节(或2个uint64)的数组,其中字节中的每个位都表示存在相应的字符。>
有了这一点,您必须遍历字符串(O(N))中的每个字符,然后对2个结果位集进行按位运算,如果不为零,则它们具有公共子字符串。
因此,对于ascii字符串,您可以获得的最佳结果可能是O(N)。
#include <stdio.h>
#include <stdint.h>
#include <string.h>
int common_chars(const char* s1,const char *s2) {
uint64_t bitset1[2] = {0,0};
uint64_t bitset2[2] = {0,0};
size_t l1,l2;
l1 = strlen(s1);
l2 = strlen(s2);
for(size_t i = 0; i < l1; ++i) {
char c = s1[i];
if (c < 64) {
bitset1[0] |= 1 << c;
} else {
bitset1[1] |= 1 << (c-64);
}
}
for(size_t i = 0; i < l2; ++i) {
char c = s2[i];
if (c < 64) {
bitset2[0] |= 1 << c;
} else {
bitset2[1] |= 1 << (c-64);
}
}
if ( ((bitset1[0] & bitset2[0]) == 0)
&& ((bitset1[1] & bitset2[1]) == 0)) {
return 0;
}
return 1;
}
int main(int argc,const char* argv[]) {
if (argc >= 3) {
printf ("%s <-> %s : %s\n",argv[1],argv[2],(common_chars(argv[1],argv[2])? "true" : "false"));
} else {
puts("you need to give 2 strings as command line arguments.");
}
return 0;
}
,
我不是C#的专业人士。但是主要的问题是嵌套循环。 O(n ^ 3) 的三级嵌套循环的时间复杂度。
public class Program{
public static void Main()
{
string[] listA = {"apple","banana","orange","test"};
string[] listB = {"NOD","train","warship"};
bool contains = false;
//For preventing Array out of bound
int length = (listA.Length > listB.Length) ? listA.Length : listB.Length;
for(int i = 0; i < length; i++){
string longer = "";
string shorter = "";
//Find the shorter string for minimizing the looping time.
if(listA[i].Length > listB[i].Length) {
longer = listA[i];
shorter = listB[i];
} else {
shorter = listA[i];
longer = listB[i];
}
foreach(char a in shorter){
if(longer.Contains(a.ToString())) {
contains = true;
break;
}
}
if (contains) {
Console.WriteLine("YES");
} else {
Console.WriteLine("NO");
}
contains = false;
}
}}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。