根据索引交换字符串中的 2 个字符

swap 2 characters in the string based on their indices

给定一个字符串,我想根据它们的索引交换字符串中的 2 个字符。

Input : str = "Hello" index1 = 1 index2 = 4

Output : str = "Holle"

但是当我直接尝试更新字符串字符时:

str[1] = //Assign something 

它给出错误 ->

Property or indexer 'string.this[int]' cannot be assigned to -- it is read only

所以我写了一个函数,在执行交换操作之前将字符串转换为字符数组。

static string SwapChars(String str, int index1, int index2)
{
    char[] strChar = str.ToCharArray();
    char temp = strChar[index1];
    strChar[index1] = strChar[index2];
    strChar[index2] = temp;
    
    return new String(strChar);
}

它工作正常,但我想知道该函数的时间复杂度是多少。我认为它是 O(n),因为 char 数组和字符串被构造为新的,其中 n 是传递的字符串的长度。还有其他一些方法可以让我以更好的性能执行此操作。

根据 this link,替换字符串中字符的一种方法是在 c# 中使用 StringBuilder class,

var str = "Hello";
var strBuilder = new StringBuilder(str);
strBuilder[4] = 'e';

str = strBuilder.ToString();
// the result will be same 

this link 比较 c# String 函数和 StringBuilder,如果你愿意,你可以比较这两个函数。

编辑说明:

我测试了 StringBuilder 和 ToCharArray 方法,结果表明使用 ToCharArray 并替换 char 确实比使用 StringBuilder 函数更好,这是我测试过的代码(至少在我的机器上):

var str = new String('a' , 100000000);

var stopwatch = new Stopwatch();

stopwatch.Start();
var strBuilder = new StringBuilder(str);
strBuilder[4] = 'e';

str = strBuilder.ToString();
stopwatch.Stop();
Console.WriteLine("Elapsed time using StringBuilder: {0} ms", stopwatch.Elapsed.Milliseconds);

stopwatch.Reset();
stopwatch.Start();
char[] strChar = str.ToCharArray();
char temp = strChar[1];
strChar[1] = strChar[4];
strChar[4] = temp;

stopwatch.Stop();
Console.WriteLine("Elapsed time using ToCharArray: {0} ms", stopwatch.Elapsed.Milliseconds);


/*
  results: 
    Elapsed time using StringBuilder: 179 ms
    Elapsed time using ToCharArray: 94 ms
*/

字符串无法通过索引器分配值,因为不允许这样做。当你查看 string 的定义时,找到 this[int index] 你会知道它只允许 get

交换它们的最佳方法是根据您的方法,但没有临时值。

static string SwapChars(String str, int index1, int index2)
{
    char[] strChar = str.ToCharArray();
    strChar[index1] = str[index2];
    strChar[index2] = str[index1];
    
    return new String(strChar);
}

另一种选择是使用 InsertRemove

static string SwapChars(String str, int index1, int index2)
{
    return str.Remove(index1, 1).Insert(index1, str[index2].ToString())
            .Remove(index2, 1).Insert(index2, str[index1].ToString());
}

老实说,我更喜欢第一个,因为它很清楚。

您可以使用指针,分配最少

public unsafe void SwapChars(ref string str, int index1, int index2)
{
   fixed (char* p = str)
   {
      var temp = p[index1];
      p[index1] = p[index2];
      p[index2] = temp;
   }
}

注意上面的内容相当危险,因为它会弄乱未转换的字符串

这样会更安全

public static unsafe string SwapChars(string str, int index1, int index2)
{
   if (str == null) throw new ArgumentNullException(nameof(str));
   if (index1 < 0 || index1 >= str.Length) throw new ArgumentOutOfRangeException(nameof(index1));
   if (index2 < 0 || index2 >= str.Length) throw new ArgumentOutOfRangeException(nameof(index1));

   var result = new string(str);

   fixed (char* p = result)
   {
      var temp = p[index1];
      p[index1] = p[index2];
      p[index2] = temp;
   }
   return result;
}

I want to know what is the time complexity for the function

如果 n 是“将一个字符从一个内存位置复制到另一个内存位置”那么它是 O(2n+3)

你的字符串字符被复制到一个字符数组,你交换它们,字符被复制到另一个字符串