Css實現瀏覽滾動條效果 前言 也是有大半個月沒有更新文章了,大部分時間都在玩,然後就是入職的事。今天就更新一個小知識,刷抖音的時候看到的,感覺還不錯。 屬性介紹 關鍵屬性animation-timeline:動畫名稱; 用於控制動畫的時間軸。它可以讓你在一個元素上同時播放多個動畫,控制它們的開始時 ...
在國慶假期的一個傍晚,小悅正在家中享受火鍋美食。她嘴裡咀嚼著鮮嫩的牛肉,臉上洋溢著滿足的微笑。突然,手機鈴聲響起,打破了這溫馨的氛圍。她拿起手機一看,是公司打來的電話。
“小悅,有個緊急的項目需要處理,你能來公司加一下班嗎?”電話那頭傳來領導焦急的聲音。
小悅頓時嘟起嘴,不太情願地離開了火鍋桌,踏上前往公司的路程。
一到公司,小悅就開始研究領導交給她的任務:處理一個關於小視頻螺旋排序演算法的問題。這個問題讓她感到有些棘手,但她知道沒有退縮的餘地。於是,她深吸了一口氣,開始認真地研究問題。
在圖像處理中,螺旋排序演算法是一個非常有用的工具。通過將圖像按照螺旋順序排列,可以更方便地對圖像進行處理和分析。例如,可以將圖像分成多個小塊進行特征提取、圖像壓縮等操作。小悅明白,要解決這個問題,首先需要理解螺旋排序演算法的原理。
她開始在紙上畫出圖像的分塊示意圖,嘗試尋找規律。經過一番推導和實踐,她逐漸掌握了螺旋排序演算法的核心思想。接著,她開始編寫代碼來實現這個演算法。
時間在悄然流逝,窗外的夜幕漸漸降臨。儘管勞累了一天,但小悅的心情卻漸漸變得愉悅起來。她在解決問題的過程中感受到了挑戰的樂趣和收穫的喜悅。當她最終完成代碼併成功運行出結果時,她的心中充滿了成就感。
“終於解決了!”小悅長出一口氣,臉上露出了滿意的微笑。她收拾好東西,準備離開公司。走出辦公室的那一刻,她抬頭看到夜空中繁星點點,心中不禁感慨萬分。這個國慶假期,或許沒有如願以償地休息和放鬆,但她卻在工作中取得了寶貴的進步。
回到家中,小悅繼續享受火鍋美食。她夾起一塊牛肉放進嘴裡,細細品味著它的鮮美。這個國慶假期,雖然沒有游山玩水的快樂,但她卻收穫了成長和充實。
小悅面臨的問題如下:給定一個n乘n二維數組,按照從最外層元素到中間元素的順序,排序,順時針移動,返回排序後的一維數組。
示例:
array = [[1,2,3],
[4,5,6],
[7,8,9]]
snail(array) #=> [1,2,3,6,9,8,7,4,5]
圖解:
演算法實現1:
1 public static int[] Snail(int[][] array) 2 { 3 // 獲取數組的長度 4 int l = array[0].Length; 5 // 創建一個用於存儲排序後元素的數組 6 int[] sorted = new int[l * l]; 7 // 遞歸調用 Snail 方法進行螺旋排序 8 Snail(array, -1, 0, 1, 0, l, 0, sorted); 9 // 返回排序後的數組 10 return sorted; 11 } 12 13 public static void Snail(int[][] array, int x, int y, int dx, int dy, int l, int i, int[] sorted) 14 { 15 // 如果數組長度為 0,則直接返回 16 if (l == 0) 17 return; 18 // 迴圈遍歷當前層的元素 19 for (int j = 0; j < l; j++) 20 { 21 // 更新當前元素的坐標,並將其存儲到排序數組中 22 x += dx; 23 y += dy; 24 sorted[i++] = array[y][x]; 25 } 26 // 遞歸調用 Snail 方法進行下一層的螺旋排序 27 Snail(array, x, y, -dy, dx, dy == 0 ? l - 1 : l, i, sorted); 28 }
假設我們有一個二維數組array
,其中包含了3行3列的整數。數組的內容如下:
1 2 3
4 5 6
7 8 9
我們希望通過螺旋排序演算法將這個二維數組按照螺旋順序排列,並得到一個結果數組r
,其中包含按照螺旋順序排列的元素。結果數組的內容如下:
1 2 3 6 9 8 7 4 5
我們將調用Test
方法來測試螺旋排序演算法。在Test
方法中,首先將二維數組array
轉換為字元串,並將結果與預期的結果數組r
進行比較。如果轉換後的字元串與預期結果字元串相等,則測試通過;否則,測試失敗。
接下來,讓我們詳細解釋一下螺旋排序演算法的運行過程:
-
首先,演算法會初始化一個空的結果數組
snail
,用於存儲按照螺旋順序排列的元素。 -
然後,演算法會定義四個變數:
top
、bottom
、left
和right
,分別表示當前螺旋排序的上邊界、下邊界、左邊界和右邊界。初始時,top
為0,bottom
為2,left
為0,right
為2。 -
接著,演算法會進入一個迴圈,直到上邊界大於下邊界或左邊界大於右邊界為止。
-
在每一次迴圈中,演算法會按照螺旋順序遍曆數組的四條邊,並將遍歷到的元素添加到結果數組
snail
中。 -
首先,演算法會從左到右遍歷上邊界,並將遍歷到的元素添加到結果數組
snail
中。在這個測試用例中,遍歷到的元素為1 2 3
。 -
然後,演算法會將上邊界下移一行,即
top++
,此時上邊界變為1。 -
接著,演算法會從上到下遍歷右邊界,並將遍歷到的元素添加到結果數組
snail
中。在這個測試用例中,遍歷到的元素為6 9
。 -
然後,演算法會將右邊界左移一列,即
right--
,此時右邊界變為1。 -
接著,演算法會從右到左遍歷下邊界,並將遍歷到的元素添加到結果數組
snail
中。在這個測試用例中,遍歷到的元素為8 7
。 -
然後,演算法會將下邊界上移一行,即
bottom--
,此時下邊界變為1。 -
接著,演算法會從下到上遍歷左邊界,並將遍歷到的元素添加到結果數組
snail
中。在這個測試用例中,遍歷到的元素為4
。 -
最後,在這個測試用例中,演算法會發現左邊界大於右邊界,因此跳出迴圈。
-
最後,演算法會返回結果數組
snail
,其中包含按照螺旋順序排列的元素。在這個測試用例中,返回的結果數組為1 2 3 6 9 8 7 4 5
。 -
在
Test
方法中,我們將轉換後的結果數組與預期的結果數組進行比較。如果它們相等,則測試通過;否則,測試失敗。
演算法實現2:
1 public static int[] Snail(int[][] grid) 2 { 3 var result = new List<int>(); 4 5 //通過grid.SelectMany(row => row).Any()判斷二維數組grid是否為空。如果為空,則直接返回空的結果數組。 6 if (!grid.SelectMany(row => row).Any()) 7 return result.ToArray(); 8 9 //將二維數組的第一行添加到結果數組中 10 result.AddRange(grid.First()); 11 12 //將二維數組的最右一列(除去第一行)添加到結果數組中 13 result.AddRange(grid.Skip(1).Select(row => row.Last())); 14 15 //將二維數組的最後一行(除去第一行和最後一個元素)逆序添加到結果數組中 16 result.AddRange(grid.Last().Reverse().Skip(1)); 17 18 //將二維數組的最左一列(除去第一行、最後一行和第一個元素)逆序添加到結果數組中 19 result.AddRange(grid.Skip(1).SkipLast(1).Select(row => row.First()).Reverse()); 20 21 var newGrid = grid 22 .Skip(1) 23 .SkipLast(1) 24 .Select(row => row 25 .Skip(1) 26 .SkipLast(1) 27 .ToArray()) 28 .ToArray(); 29 30 //通過遞歸調用Snail方法,將去掉了二維數組的第一行、最後一行、第一列和最後一列後的新二維數組傳入,並將返回的結果數組添加到當前的結果數組中 31 result.AddRange(Snail(newGrid)); 32 33 return result.ToArray(); 34 }
這段代碼的邏輯與演算法1的功能相同,只是在創建新二維數組newGrid
時,使用了鏈式調用的方式來去掉邊界元素。
AddRange 是一個常用在 LINQ 中的方法,通常在 List<T> 或 Dictionary<TKey, TValue> 等集合類型中使用。這個方法用於將另一個集合中的元素添加到當前集合中。
首先,代碼通過Skip(1)
去掉了第一行,然後通過SkipLast(1)
去掉了最後一行,接著通過Select(row => row.Skip(1).SkipLast(1).ToArray())
去掉了每一行的第一個元素和最後一個元素,最後通過ToArray()
將結果轉換為新的二維數組。這樣,遞歸調用Snail
方法時傳入的新二維數組就是去掉了邊界的數組。
假設我們有一個100x100像素的圖像,我們想要將其分成10x10個小塊進行特征提取或圖像壓縮。在沒有使用螺旋排序演算法之前,我們可以按照圖像的行優先順序將像素按順序分成小塊。這意味著我們首先將圖像的第一行的前10個像素作為第一個小塊,然後是第一行的下一個10個像素作為第二個小塊,依此類推,直到圖像的第10行。然後,我們繼續將圖像的第11行的前10個像素作為第11個小塊,以此類推,直到圖像的最後一行。
這種方法的問題是,它沒有考慮到圖像的局部結構。相鄰的像素在圖像中可能是相關的,而按行順序分塊可能會將相關的像素分散在不同的塊中。這可能導致特征提取或圖像壓縮的結果不夠準確或失真。
現在,如果我們使用螺旋排序演算法來分塊圖像,我們可以更好地保留圖像的局部結構。螺旋排序演算法按照螺旋順序遍歷圖像的像素,並將它們分成小塊。這意味著我們首先將圖像的中心像素作為第一個小塊,然後按照螺旋順序將相鄰的像素添加到下一個小塊,直到所有像素都被分到小塊中。
通過使用螺旋排序演算法,我們可以更好地保留圖像的局部結構,因為相鄰的像素通常在空間上也是相鄰的。這有助於提高特征提取或圖像壓縮的準確性和質量。
所以螺旋排序演算法在各個領域都有一定的應用價值,可以幫助提高數據處理和分析的效率,優化系統設計和佈局,以及改善數據的可視化效果:
-
圖像處理:在圖像處理中,螺旋排序演算法可以用於對圖像進行分塊處理。通過將圖像按照螺旋順序排列,可以更方便地對圖像進行處理和分析。例如,可以將圖像分成多個小塊進行特征提取、圖像壓縮等操作。
-
數據存儲和檢索:螺旋排序演算法可以用於對二維數組或矩陣進行存儲和檢索。通過按照螺旋順序對數據進行排序,可以提高數據的訪問效率。例如,在二維地圖導航系統中,可以將地圖數據按照螺旋順序進行存儲,以便快速檢索和顯示地圖信息。
-
數據可視化:螺旋排序演算法可以用於數據可視化,特別是對於二維數據的可視化。通過按照螺旋順序對數據進行排序,可以將數據按照一定的規律展示出來,更直觀地觀察數據的分佈和變化。例如,在熱力圖中,可以按照螺旋順序對溫度數據進行排序,以便更清晰地顯示溫度的變化趨勢。
-
電路佈局:在電路設計中,螺旋排序演算法可以用於電路佈局的優化。通過按照螺旋順序對電路元件進行排序,可以減少電路佈線的長度和複雜度,提高電路的性能和可靠性。
測試用例:
1 using NUnit.Framework; 2 using System; 3 using System.Linq; 4 public class SnailTest 5 { 6 7 private int[] Tsnail(int[][] array) 8 { 9 int[] sorted = new int[array.Length * array.Length]; 10 Tsnail(array, -1, 0, 1, 0, array.Length, 0, sorted); 11 return sorted; 12 } 13 14 private void Tsnail(int[][] array, int x, int y, int dx, int dy, int l, int i, int[] sorted) 15 { 16 if (l == 0) 17 return; 18 for (int j = 0; j < l; j++) 19 { 20 x += dx; 21 y += dy; 22 sorted[i++] = array[y][x]; 23 } 24 Tsnail(array, x, y, -dy, dx, dy == 0 ? l - 1 : l, i, sorted); 25 26 } 27 28 public string Int2dToString(int[][] a) 29 { 30 return $"[{string.Join("\n", a.Select(row => $"[{string.Join(",", row)}]"))}]"; 31 } 32 33 public void Test(int[][] array, int[] result) 34 { 35 var text = $"{Int2dToString(array)}\nshould be sorted to\n[{string.Join(",", result)}]\n"; 36 Console.WriteLine(text); 37 Assert.AreEqual(result, SnailSolution.Snail(array)); 38 } 39 40 [Test] 41 public void SnailTest1() 42 { 43 int[][] array = 44 { 45 new []{1, 2, 3}, 46 new []{4, 5, 6}, 47 new []{7, 8, 9} 48 }; 49 var r = new[] { 1, 2, 3, 6, 9, 8, 7, 4, 5 }; 50 Test(array, r); 51 } 52 53 [Test] 54 public void SnailTest2() 55 { 56 int[][] array = 57 { 58 new []{1, 2, 3, 9}, 59 new []{4, 5, 6, 4}, 60 new []{7, 8, 9, 1}, 61 new []{1, 2, 3, 4} 62 }; 63 var r = new[] { 1, 2, 3, 9, 4, 1, 4, 3, 2, 1, 7, 4, 5, 6, 9, 8 }; 64 Test(array, r); 65 } 66 67 [Test] 68 public void SnailTest2Empty() 69 { 70 int[][] a = { new int[] { } }; 71 Test(a, new int[0]); 72 } 73 74 [Test] 75 public void SnailTestOne() 76 { 77 int[][] a = { new[] { 1 } }; 78 Test(a, new[] { 1 }); 79 } 80 81 82 [Test] 83 public void SnailRandomTest() 84 { 85 Console.WriteLine("Random Tests"); 86 Random rand = new Random(); 87 for (int n = 0; n < 100; n++) 88 { 89 var l = rand.Next(1, 31); 90 var array = new int[l][]; 91 for (int i = 0; i < l; i++) 92 { 93 array[i] = new int[l]; 94 for (int j = 0; j < l; j++) 95 array[i][j] = rand.Next(1, 1001); 96 } 97 Test(array, Tsnail(array)); 98 } 99 } 100 }