c#Hackerrank代码因超时而终止,但无法进一步优化此代码?

时间:2016-11-21 08:42:11

标签: c# optimization timeout

我在c#中做了一个黑客等级挑战,试图将我的一些技能带到c#。现在我知道黑客级别因为超时而被杀死程序是非常愚蠢的(在这种情况下,如果持续时间超过3秒)。但老实说,我无法想到进一步优化此代码的方法。

以下是说明: https://www.hackerrank.com/challenges/ctci-array-left-rotation

基本上,挑战是在数组内向左移动一个数字数组大约x倍。

据我所知,这段代码尽可能少,但仍可按照要求进行操作。我可以考虑进一步优化这个代码的唯一方法是将约束“if(a [i]> 1000000 || a [i]< 1)”与代码末尾的writeline forloop合并,但是我尝试过,它没有用。

对我而言,这实际上是将数组移动x的最小操作次数。但由于超时,代码在测试用例7和8(满分为8)中失败。我错过了什么吗?

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
class Solution 

{

static void Main(String[] args) 

{
    int i, j;
    int temp = 0;
    string[] tokens_n = Console.ReadLine().Split(' ');
    int n = Convert.ToInt32(tokens_n[0]);
    int k = Convert.ToInt32(tokens_n[1]);
    string[] a_temp = Console.ReadLine().Split(' ');
    int[] a = Array.ConvertAll(a_temp,Int32.Parse);

    //constraints
    if(n >= 100000 || n < 1 )
        {
        System.Environment.Exit(1);
        }

    if(k > n || n < 1 )
        {
        System.Environment.Exit(1);
        }  

    for(i = 0; i< n; i++)
    {
           if(a[i] > 1000000 || a[i] < 1 )
           {
           System.Environment.Exit(1);
           }     
     } 

    //double for loop. one adjust position by one. then repeat k number of times.

    for(j = 0; j<k; j++)
        {

            for(i = 0; i< n-1; i++)
                {
                temp = a[i];
                a[i] = a[i+1];
                a[i+1] = temp;
                }
        }

    //view array
    for(i = 0; i< n; i++)
        {
    Console.Write(a[i] + " " );      
        }

}

}

4 个答案:

答案 0 :(得分:1)

一次一个地移动值非常慢。没有必要这样做。可以将旋转视为移动2个块 - 旋转点左侧的值以及旋转点的右侧和值

1  2  3  4  5  6  7  8  9

旋转3次

  1. 将1-3移至临时变量
  2. 将4-9移动到数组的开头
  3. 将1-3移至4-9结尾
  4. 编辑:添加更多细节

    我们希望将数组旋转3个位置。

    • 将1 2 3移动到临时数组

      1 2 3
      1 2 3 4 5 6 7 8 9

    • 将4-9移动到数组的开头

      1 2 3
      4 5 6 7 8 9 7 8 9

    • 将1-3移动到数组的末尾

      1 2 3
      4 5 6 7 8 9 1 2 3

    如果我们创建一个新的目标数组并将所有内容复制到它,我们可以在没有左侧块的临时数组的情况下离开。以下内容通过了问题的所有测试

     var result = new int[a.Length];
     var block2Length = a.Length - k;
     Array.Copy(a, k, result, 0, block2Length);
     Array.Copy(a, 0, result, block2Length, k);
    
     Console.WriteLine(string.Join(" ", result.Select(v => v.ToString())));
    

    其他要点

    HackerRank中的约束是问题定义的一部分 - 它们告诉我们价值可以/将要做什么,以便我们不必担心解决更普遍的问题

    e.g。
        1&lt; = a [i]&lt; 10 ^ 6

    告诉我们数字将全部在标准整数的范围内,无需使用longBigInteger。作为解决方案的一部分,我们不需要确认这些。在现实世界的情况下,不同的规则适用,但在这里我们有尽可能多的代码检查值,因为我们已经解决了这个问题。

答案 1 :(得分:1)

这已经得到了回答,但有一种不同的解决方案非常快:

这个想法是你使用移位的周期性。移动元素n+1次与将1时间移动到k % n的时间相同。 因此,您可以简单地创建一个新数组并移动&#34; old&#34;元素直接到正确的位置。请参阅以下示例代码:

static void Main(String[] args) {
    string[] tokens_n = Console.ReadLine().Split(' ');
    int n = Convert.ToInt32(tokens_n[0]);
    int k = Convert.ToInt32(tokens_n[1]);
    string[] a_temp = Console.ReadLine().Split(' ');
    int[] a = Array.ConvertAll(a_temp,Int32.Parse);

    // use the periodicity of the shifting creating a shift between 0 and n - 1.
    int shifts = k % n;

    // Create a new array to hold the elements at their new positions.    
    int[] newPositions = new int[a.Length];

    // You only need to iterate of the array once assigning each element its new position.
    for(int i= 0; i < a.Length; ++i)
    {
        // Here is the magic: (for clarification see table below)
        int position = (i - shifts + n)%n;
        newPositions[position] = a[i];
    }

    foreach(var element in newPositions)
        Console.Write($"{element} ");
}

一旦你把它写在纸上,这就更直观了。该表可能会打印比数组所包含的值更多的值,以显示数组中的实际位置。

-4 -3 -2 -1 | 0  1  2  3  4  (array indices)
=============================
 2  3  4  5 | 1  2  3  4  5  (array contents without shift)
 3  4  5  1 | 2  3  4  5  1  (shifted 1 time)
 4  5  1  2 | 3  4  5  1  2  (shifted 2 times)
 5  1  2  3 | 4  5  1  2  3  (shifted 3 times)
 1  2  3  4 | 5  1  2  3  4  (shifted 4 times)

formula: i - k + n
results:
i=0: 0 - 4 + 5 = 1
i=1: 1 - 4 + 5 = 2
i=2: 2 - 4 + 5 = 3
i=3: 3 - 4 + 5 = 4
i=4: 4 - 4 + 5 = 5
i=5: 5 - 4 + 5 = 6 => 0

编辑:为了简单起见,我跳过了部分检查边界。

答案 2 :(得分:1)

我使用了队列机制来实现这一点。这样你就不必进行任何数组复制,只需将字符串旋转到最后。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
class Solution {

    static int[] leftRotation(int[] arr, int rotation) {
        Queue<int> queue = new Queue<int>(arr);

        for (int i = 0; i < rotation; i++)
        {
            queue.Enqueue(queue.Dequeue());
        }

        return queue.ToArray();
    }

    static void Main(String[] args) {
        string[] tokens_n = Console.ReadLine().Split(' ');
        int n = Convert.ToInt32(tokens_n[0]);
        int d = Convert.ToInt32(tokens_n[1]);
        string[] a_temp = Console.ReadLine().Split(' ');
        int[] a = Array.ConvertAll(a_temp,Int32.Parse);
        int[] result = leftRotation(a, d);
        Console.WriteLine(String.Join(" ", result));
    }
}

答案 3 :(得分:0)

更新了答案。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
class Solution 
{

    static void Main(String[] args) 

    {
        int i, j, z;
        string[] tokens_n = Console.ReadLine().Split(' ');
        int n = Convert.ToInt32(tokens_n[0]);
        int k = Convert.ToInt32(tokens_n[1]);
        string[] a_temp = Console.ReadLine().Split(' ');
        int[] a = Array.ConvertAll(a_temp,Int32.Parse);

        int[] temparray = new int[2*n];

        //constraints
        if(n >= 100000 || n < 1 )
            {
            System.Environment.Exit(1);
            }

        if(k > n || n < 1 )
            {
            System.Environment.Exit(1);
            }  

        for(i = 0; i< n; i++)
        {
               if(a[i] > 1000000 || a[i] < 1 )
               {
               System.Environment.Exit(1);
               }     
         } 


        for(j = 0; j<n; j++)
            {
            z = (j-k) %n;

            if(z != 0)
                {
                z= (n+ z) %n;
                }

            temparray[z] = a[j];
            }

        //view array
        for(i = 0; i< n; i++)
            {
        Console.Write(temparray[i] + " " );      
            }


    }
}