2010-09-03 48 views
2

我解決旋轉陣列的這個問題旋轉陣列並得到了算法和代碼工作使用LINQ語法

int[] Rotate(int[] ar,int k) 
     { 
      if (k <= 0 || k > ar.Length - 1) 
       return ar; 
      Reverse(ar, 0, k - 1); 
      Reverse(ar, k, ar.Length - 1); 
      Reverse(ar, 0, ar.Length - 1); 
      return ar;    
     } 

void Reverse(int[] ar,int start, int end) 
     { 
      while (start < end) 
      { 
       int temp = ar[start]; 
       ar[start] = ar[end]; 
       ar[end] = temp; 
       start++; 
       end--; 
      } 
     } 

現在,我想這樣做在LINQ,我得到了下面的代碼,我認爲這是可以做得好得多。

int[] Rotate(int[] ar,int k) 
    { 
     if (k <= 0 || k > ar.Length - 1) 
      return ar; 
     int[] ar1=ar.Take(k-1).Reverse().ToArray(); 
     int[] ar2=ar.Skip(k - 1).Take(ar.Length - k+1).Reverse().ToArray(); 
     int[] ar3 = ar1.Concat(ar2).Reverse().ToArray(); 
     return ar3; 
    } 

這是編程珍珠一個衆所周知的算法 - http://books.google.com/books?id=kse_7qbWbjsC&lpg=PA14&ots=DfzTzQCSar&dq=rotate%20an%20array%20programming%20pearls&pg=PA14#v=onepage&q&f=false

而在一般情況如何發展我的LINQ的技能,如果我給出一個規劃問題,現在我只是想在for循環或foreach循環,如何用linq運算符來思考。我正在閱讀C#4.0簡而言之,除了練習任何建議嗎?

+0

這是*擴展方法*語法。 LINQ語法將從'from ...'開始。 – 2010-09-03 23:18:36

+0

是的,但是使用LINQ來指代lambda/Enumerable ...我擔心這個貓已經很好用了。 :( – 2010-09-03 23:19:29

+2

@Marcelo Cantos,你指的是* query comprehension語法*。沒有「LINQ語法」這樣的東西。 – 2010-09-03 23:37:21

回答

3

與您的代碼開始:

int[] ar1=ar.Take(k-1).Reverse().ToArray(); 
int[] ar2=ar.Skip(k - 1).Take(ar.Length - k+1).Reverse().ToArray(); 
int[] ar3 = ar1.Concat(ar2).Reverse().ToArray(); 

既然你只是想獲得的所有剩餘的元素,是不是需要在第二行取。

ar1和ar2只是枚舉,所以它們不需要是數組。 ToArray調用是不需要的。只要一點創意重命名的拋出,我們有:

IEnumerable<int> revFirst = ar.Take(k-1).Reverse(); 
IEnumerable<int> revLast = ar.Skip(k-1).Reverse(); 
int[] ar3 = revFirst.Concat(revLast).Reverse().ToArray(); 

現在我們有

REV(REV(第一)+ REV(最後))

分配外轉給

REV(REV(最近))+ REV(REV(第一))

其是相同

last + first 

應用相同的操作代碼給

IEnumerable<int> first = ar.Take(k-1); 
IEnumerable<int> last = ar.Skip(k-1); 
int[] ar3 = last.Concat(first).ToArray(); 

進一步簡化到

int[] ar3 = ar.Skip(k-1).Concat(ar.Take(k-1)).ToArray(); 

,現在我們有喬恩斯基特的答案,所以我們必須做到的。

+0

我愛你,當你的答案與Jon的匹配時,你知道你已經完成了。 – RichK 2010-09-04 14:33:28

+0

精彩的解釋!謝謝你回答我的答案和喬恩的回答,並從我的出發,努力! – satyajit 2010-09-04 19:49:25

13

我不確定爲什麼你有所有的逆轉,說實話。這個怎麼樣:

int[] Rotate(int[] ar,int k) 
{ 
    if (k <= 0 || k > ar.Length - 1) 
     return ar; 
    return ar.Skip(k)   // Start with the last elements 
      .Concat(ar.Take(k)) // Then the first elements 
      .ToArray();   // Then make it an array 
} 

下面是一個簡短但完整的方案進行論證:

using System; 
using System.Linq; 

class Test 
{ 
    static int[] Rotate(int[] ar,int k) 
    { 
     if (k <= 0 || k > ar.Length - 1) 
      return ar; 
     return ar.Skip(k)   // Start with the last elements 
       .Concat(ar.Take(k)) // Then the first elements 
       .ToArray();   // Then make it an array 
    } 

    static void Main() 
    { 
     int[] values = { 1, 2, 3, 4, 5 }; 
     int[] rotated = Rotate(values, 3); 

     Console.WriteLine(string.Join(", ", rotated)); 
    } 
} 

輸出:4,5,1,2,3

編輯:我剛剛注意到我的代碼和原始代碼之間的一個主要區別是:您的代碼修改了原始數組 - 我的代碼返回新的數組,其中包含旋轉的值。你的LINQ代碼也是如此,但這意味着如果你用我們的代碼測試了一些只能看到原始數組的代碼,你就看不到旋轉。

LINQ被設計成通用這種方式 - 它有利於返回一個新的序列而不是修改現有的序列。

+0

這不是爲我旋轉數組,它只是返回原始數組。在IDE中檢查 – satyajit 2010-09-03 23:33:50

+0

@satyajit:然後你沒有正確地使用它,我將添加一個簡短但完整的程序來顯示它的工作 – 2010-09-04 08:37:34

+0

是的,我現在明白你的代碼正在返回一個新的數組。向我解釋! – satyajit 2010-09-04 19:47:41