算法方法快速回顾

(待修改)

目录

  • 1. 双指针
  • 2. 滑动窗口
    • 理论基础
  • 3. 二分查找
  • 3. 二分查找
    • 理论基础
  • 4. KMP
  • 5. 回溯算法
  • 6. 贪心算法
  • 7. 动态规划
    • 7.1. 01背包
    • 7.2. 完全背包
    • 7.3. 多重背包
  • 8. 单调栈
  • 9. 并查集
  • 10. 图论
    • 10.1. 广度优先搜索(BFS)
    • 10.2. 深度优先搜索(DFS)
    • 10.3. Dijkstra 算法
    • 10.4. Floyd-Warshall 算法
  • 11. 哈希算法
  • 12. 排序算法
    • 12.1. 冒泡排序
    • 12.2. 选择排序
    • 12.3. 插入排序
    • 12.4. 希尔排序
    • 12.5. 归并排序
    • 12.6. 快速排序
    • 12.7. 堆排序
    • 12.8. 计数排序
    • 12.9. 桶排序
    • 12.10. 基数排序
  • 13. 位运算算法

1. 双指针

双指针是一种常用的算法思想,在解决各类编程问题中应用广泛。按照指向序列的不同,可分为指向同一序列和指向不同序列这两类双指针,部分类型还具有可扩展性:

  1. 指向同一序列的双指针
    • 快慢指针:两个指针在同一序列中,快指针每次移动的步长大于慢指针,常用于解决链表相关问题,如判断链表是否成环(如141.环形链表)、寻找链表的中点(如143.重排链表)等。在判断链表是否成环时,快指针每次移动两步,慢指针每次移动一步,如果快指针和慢指针相遇,则说明链表有环。这种方式可以在不使用额外数据结构的情况下高效解决问题,具有较好的扩展性,比如在142.环形链表II中,通过快慢指针相遇后的进一步操作,能找到链表开始入环的第一个节点 。
    • 首尾指针:一个指针指向序列头部,另一个指针指向序列尾部,然后向中间移动,常用于数组相关问题。像11.盛最多水的容器,通过首尾指针不断调整柱子位置来计算最大盛水量;15.三数之和中,排序后用首尾指针在数组中查找满足条件的三元组,这种类型在处理有序数组的组合问题时经常使用,通过移动指针可以减少不必要的计算,提高算法效率,也可扩展到四数之和(18.四数之和 )等问题,增加一层循环,在固定两个数的情况下,利用首尾指针查找另外两个数。
    • 固定间距指针:两个指针在序列中保持固定的间距移动,例如在26.删除有序数组中的重复项中,快慢指针间距为1,用于原地删除重复元素,记录不重复元素的位置。这种指针类型在处理有序数组的去重或特殊元素筛选问题时很有效,在一些需要对数组元素进行特殊处理且元素相对顺序固定的场景下,可通过调整间距来满足需求,具有一定的扩展性 。
  2. 指向不同序列的双指针:主要用于合并或比较不同序列,如归并排序。在88.合并两个有序数组中,两个指针分别指向两个有序数组,从后往前进行归并,将较大的数依次放在nums1的后面。这种类型在处理多个有序序列的合并问题时非常高效,并且可以扩展到多个有序序列的合并,通过增加指针数量和相应的比较逻辑来实现 。
using System;class DoublePointerExample
{static void Main(){int[] nums = { 1, 2, 3, 4, 5 };int target = 7;for (int i = 0, j = nums.Length - 1; i < j;){int sum = nums[i] + nums[j];if (sum == target){Console.WriteLine($"找到满足条件的元素对: {nums[i]}, {nums[j]}");break;}else if (sum < target){i++;}else{j--;}}}
}

2. 滑动窗口

滑动窗口是一种在数组或字符串上常用的算法技巧,通过动态调整窗口的起始和结束位置,来解决一系列与子串、子数组相关的问题。它可以将时间复杂度从暴力解法的 O ( n 2 ) O(n^2) O(n2)降低到 O ( n ) O(n) O(n),提高算法效率。下面为你详细介绍滑动窗口的相关内容:

理论基础

滑动窗口本质上是一个连续的子数组(或子串),在数组或字符串上滑动。通过调整窗口的左右边界,可以在遍历过程中动态地获取不同的子数组(或子串),并对其进行处理。其关键在于如何根据具体问题,确定窗口的扩展和收缩条件,从而高效地找到满足条件的子数组(或子串)。

using System;class SlidingWindowExample
{static void Main(){int[] nums = { 1, 3, -1, -3, 5, 3, 6, 7 };int k = 3;for (int i = 0; i <= nums.Length - k; i++){int sum = 0;for (int j = i; j < i + k; j++){sum += nums[j];}Console.WriteLine($"窗口 [{i}, {i + k - 1}] 的和: {sum}");}}
}

3. 二分查找

3. 二分查找

二分查找,也被称为折半查找,是一种高效的查找算法,专门用于在有序数组中快速定位目标元素。它的核心思想是利用数组的有序性,每次将查找范围缩小一半,从而显著提高查找效率。相较于顺序查找平均 O ( n ) O(n) O(n)的时间复杂度,二分查找的时间复杂度为 O ( log ⁡ n ) O(\log n) O(logn) ,在处理大规模数据时优势明显。

理论基础

二分查找的前提是数组必须有序。在查找过程中,首先设定两个指针,通常命名为leftright,分别指向数组的开头和结尾。接着计算中间位置mid,通过比较目标元素与中间位置元素的大小关系来决定下一步的查找方向。如果目标元素等于中间元素,则查找成功;若目标元素小于中间元素,说明目标元素可能在左半部分,于是将right指针移动到mid - 1位置,继续在左半部分查找;反之,若目标元素大于中间元素,则将left指针移动到mid + 1位置,在右半部分继续查找。不断重复上述步骤,直到找到目标元素或者left超过right(表示未找到目标元素)为止。

using System;class Program
{static int BinarySearchFirst(int[] arr, int target, int left, int right){if (left > right) return -1;int mid = left + (right - left) / 2;if (arr[mid] == target){int prev = BinarySearchFirst(arr, target, left, mid - 1);return prev != -1 ? prev : mid;}else if (arr[mid] < target){return BinarySearchFirst(arr, target, mid + 1, right);}return BinarySearchFirst(arr, target, left, mid - 1);}static void Main(){int[] arr = { 1, 2, 2, 2, 3, 4, 5 };int target = 2;int result = BinarySearchFirst(arr, target, 0, arr.Length - 1);Console.WriteLine(result != -1 ? $"首个 {target} 的索引是 {result}" : $"未找到 {target}");}
}    

4. KMP

KMP 算法用于在主字符串中查找模式字符串,通过预处理模式字符串来减少不必要的比较。

using System;class KMPExample
{static int[] ComputeLPSArray(string pattern){int[] lps = new int[pattern.Length];int len = 0;lps[0] = 0;int i = 1;while (i < pattern.Length){if (pattern[i] == pattern[len]){len++;lps[i] = len;i++;}else{if (len != 0){len = lps[len - 1];}else{lps[i] = 0;i++;}}}return lps;}static int KMPSearch(string text, string pattern){int[] lps = ComputeLPSArray(pattern);int i = 0;int j = 0;while (i < text.Length){if (pattern[j] == text[i]){i++;j++;}if (j == pattern.Length){return i - j;}else if (i < text.Length && pattern[j] != text[i]){if (j != 0){j = lps[j - 1];}else{i++;}}}return -1;}static void Main(){string text = "ABABDABACDABABCABAB";string pattern = "ABABCABAB";int result = KMPSearch(text, pattern);if (result != -1){Console.WriteLine($"模式字符串在主字符串中的起始索引是: {result}");}else{Console.WriteLine($"未找到模式字符串");}}
}

5. 回溯算法

回溯算法用于解决组合、排列等问题,通过深度优先搜索并在不满足条件时回溯来找到所有可能的解。

using System;
using System.Collections.Generic;class BacktrackingExample
{static void Backtrack(int[] nums, int index, List<List<int>> result, List<int> currentList){result.Add(new List<int>(currentList));for (int i = index; i < nums.Length; i++){currentList.Add(nums[i]);Backtrack(nums, i + 1, result, currentList);currentList.RemoveAt(currentList.Count - 1);}}static List<List<int>> Subsets(int[] nums){List<List<int>> result = new List<List<int>>();Backtrack(nums, 0, result, new List<int>());return result;}static void Main(){int[] nums = { 1, 2, 3 };List<List<int>> subsets = Subsets(nums);foreach (var subset in subsets){Console.Write("[ ");foreach (var num in subset){Console.Write(num + " ");}Console.WriteLine("]");}}
}

6. 贪心算法

贪心算法在每一步选择中都采取当前状态下最优的选择,从而希望得到全局最优解。

using System;class GreedyExample
{static int CoinChange(int[] coins, int amount){int count = 0;Array.Sort(coins);for (int i = coins.Length - 1; i >= 0; i--){while (amount >= coins[i]){amount -= coins[i];count++;}}return amount == 0? count : -1;}static void Main(){int[] coins = { 1, 2, 5 };int amount = 11;int result = CoinChange(coins, amount);Console.WriteLine($"最少需要 {result} 枚硬币");}
}

7. 动态规划

动态规划通过将问题分解为子问题,并保存子问题的解来避免重复计算。

7.1. 01背包

01 背包问题是在给定容量的背包中选择物品,使总价值最大,每个物品只能选择一次。

using System;class Knapsack01Example
{static int Knapsack01(int[] weights, int[] values, int capacity){int n = weights.Length;int[,] dp = new int[n + 1, capacity + 1];for (int i = 0; i <= n; i++){for (int w = 0; w <= capacity; w++){if (i == 0 || w == 0){dp[i, w] = 0;}else if (weights[i - 1] <= w){dp[i, w] = Math.Max(values[i - 1] + dp[i - 1, w - weights[i - 1]], dp[i - 1, w]);}else{dp[i, w] = dp[i - 1, w];}}}return dp[n, capacity];}static void Main(){int[] weights = { 2, 3, 4, 5 };int[] values = { 3, 4, 5, 6 };int capacity = 8;int result = Knapsack01(weights, values, capacity);Console.WriteLine($"01 背包的最大价值是: {result}");}
}

7.2. 完全背包

完全背包问题与 01 背包类似,但每个物品可以选择多次。

using System;class KnapsackCompleteExample
{static int KnapsackComplete(int[] weights, int[] values, int capacity){int n = weights.Length;int[] dp = new int[capacity + 1];for (int i = 0; i < n; i++){for (int w = weights[i]; w <= capacity; w++){dp[w] = Math.Max(dp[w], dp[w - weights[i]] + values[i]);}}return dp[capacity];}static void Main(){int[] weights = { 2, 3, 4, 5 };int[] values = { 3, 4, 5, 6 };int capacity = 8;int result = KnapsackComplete(weights, values, capacity);Console.WriteLine($"完全背包的最大价值是: {result}");}
}

7.3. 多重背包

多重背包问题中每个物品有一定的数量限制。

using System;class KnapsackMultipleExample
{static int KnapsackMultiple(int[] weights, int[] values, int[] amounts, int capacity){int n = weights.Length;int[,] dp = new int[n + 1, capacity + 1];for (int i = 0; i <= n; i++){for (int w = 0; w <= capacity; w++){if (i == 0 || w == 0){dp[i, w] = 0;}else{for (int k = 0; k <= amounts[i - 1] && k * weights[i - 1] <= w; k++){dp[i, w] = Math.Max(dp[i, w], dp[i - 1, w - k * weights[i - 1]] + k * values[i - 1]);}}}}return dp[n, capacity];}static void Main(){int[] weights = { 2, 3, 4, 5 };int[] values = { 3, 4, 5, 6 };int[] amounts = { 2, 3, 1, 2 };int capacity = 8;int result = KnapsackMultiple(weights, values, amounts, capacity);Console.WriteLine($"多重背包的最大价值是: {result}");}
}

8. 单调栈

单调栈用于解决下一个更大元素、下一个更小元素等问题,栈内元素保持单调递增或单调递减。

using System;
using System.Collections.Generic;class MonotonicStackExample
{static int[] NextGreaterElement(int[] nums){int[] result = new int[nums.Length];Stack<int> stack = new Stack<int>();for (int i = nums.Length - 1; i >= 0; i--){while (stack.Count > 0 && stack.Peek() <= nums[i]){stack.Pop();}result[i] = stack.Count == 0? -1 : stack.Peek();stack.Push(nums[i]);}return result;}static void Main(){int[] nums = { 4, 5, 2, 10, 8 };int[] result = NextGreaterElement(nums);foreach (var num in result){Console.Write(num + " ");}}
}

9. 并查集

并查集用于处理不相交集合的合并与查询问题。

using System;class UnionFindExample
{private int[] parent;private int[] rank;public UnionFindExample(int n){parent = new int[n];rank = new int[n];for (int i = 0; i < n; i++){parent[i] = i;rank[i] = 1;}}public int Find(int x){if (parent[x] != x){parent[x] = Find(parent[x]);}return parent[x];}public void Union(int x, int y){int rootX = Find(x);int rootY = Find(y);if (rootX != rootY){if (rank[rootX] < rank[rootY]){parent[rootX] = rootY;}else if (rank[rootX] > rank[rootY]){parent[rootY] = rootX;}else{parent[rootY] = rootX;rank[rootX]++;}}}static void Main(){UnionFindExample uf = new UnionFindExample(5);uf.Union(0, 1);uf.Union(2, 3);Console.WriteLine($"0 和 1 是否在同一集合: {uf.Find(0) == uf.Find(1)}");Console.WriteLine($"0 和 2 是否在同一集合: {uf.Find(0) == uf.Find(2)}");}
}

10. 图论

图论是研究图的性质和算法的领域,包括广度优先搜索、深度优先搜索等算法。

10.1. 广度优先搜索(BFS)

广度优先搜索用于遍历图,从起点开始逐层访问相邻节点。

using System;
using System.Collections.Generic;class Graph
{private Dictionary<int, List<int>> adjList;public Graph(){adjList = new Dictionary<int, List<int>>();}public void AddEdge(int u, int v){if (!adjList.ContainsKey(u)){adjList[u] = new List<int>();}if (!adjList.ContainsKey(v)){adjList[v] = new List<int>();}adjList[u].Add(v);adjList[v].Add(u);}public void BFS(int start){bool[] visited = new bool[adjList.Count];Queue<int> queue = new Queue<int>();visited[start] = true;queue.Enqueue(start);while (queue.Count > 0){int current = queue.Dequeue();Console.Write(current + " ");foreach (int neighbor in adjList[current]){if (!visited[neighbor]){visited[neighbor] = true;queue.Enqueue(neighbor);}}}}
}class BFSExample
{static void Main(){Graph graph = new Graph();graph.AddEdge(0, 1);graph.AddEdge(0, 2);graph.AddEdge(1, 2);graph.AddEdge(2, 3);graph.AddEdge(3, 3);Console.WriteLine("广度优先搜索结果:");graph.BFS(0);}
}

10.2. 深度优先搜索(DFS)

深度优先搜索从起点开始尽可能深地访问节点,直到无法继续再回溯。

using System;
using System.Collections.Generic;class Graph
{private Dictionary<int, List<int>> adjList;public Graph(){adjList = new Dictionary<int, List<int>>();}public void AddEdge(int u, int v){if (!adjList.ContainsKey(u)){adjList[u] = new List<int>();}if (!adjList.ContainsKey(v)){adjList[v] = new List<int>();}adjList[u].Add(v);adjList[v].Add(u);}private void DFSUtil(int vertex, bool[] visited){visited[vertex] = true;Console.Write(vertex + " ");if (adjList.ContainsKey(vertex)){foreach (int neighbor in adjList[vertex]){if (!visited[neighbor]){DFSUtil(neighbor, visited);}}}}public void DFS(int start){bool[] visited = new bool[adjList.Count];DFSUtil(start, visited);}
}class DFSExample
{static void Main(){Graph graph = new Graph();graph.AddEdge(0, 1);graph.AddEdge(0, 2);graph.AddEdge(1, 2);graph.AddEdge(2, 3);graph.AddEdge(3, 4);Console.WriteLine("深度优先搜索结果:");graph.DFS(0);}
}

10.3. Dijkstra 算法

Dijkstra 算法用于在带权有向图中找到从一个源点到其他所有节点的最短路径。

using System;
using System.Collections.Generic;class DijkstraExample
{private const int Infinity = int.MaxValue;static int MinDistance(int[] dist, bool[] sptSet, int n){int min = Infinity, minIndex = -1;for (int v = 0; v < n; v++){if (!sptSet[v] && dist[v] <= min){min = dist[v];minIndex = v;}}return minIndex;}static void PrintSolution(int[] dist, int n){Console.WriteLine("Vertex \t Distance from Source");for (int i = 0; i < n; i++){Console.WriteLine(i + " \t\t " + dist[i]);}}static void Dijkstra(int[,] graph, int src, int n){int[] dist = new int[n];bool[] sptSet = new bool[n];for (int i = 0; i < n; i++){dist[i] = Infinity;sptSet[i] = false;}dist[src] = 0;for (int count = 0; count < n - 1; count++){int u = MinDistance(dist, sptSet, n);sptSet[u] = true;for (int v = 0; v < n; v++){if (!sptSet[v] && graph[u, v] != 0 && dist[u] != Infinity && dist[u] + graph[u, v] < dist[v]){dist[v] = dist[u] + graph[u, v];}}}PrintSolution(dist, n);}static void Main(){int n = 5;int[,] graph = {{ 0, 4, 0, 0, 0 },{ 4, 0, 8, 0, 0 },{ 0, 8, 0, 7, 4 },{ 0, 0, 7, 0, 9 },{ 0, 0, 4, 9, 0 }};Console.WriteLine("Shortest distances from source vertex 0:");Dijkstra(graph, 0, n);}
}

10.4. Floyd-Warshall 算法

Floyd-Warshall 算法用于在带权图中找到所有顶点对之间的最短路径。

using System;class FloydWarshallExample
{static void FloydWarshall(int[,] graph, int n){int[,] dist = (int[,])graph.Clone();for (int k = 0; k < n; k++){for (int i = 0; i < n; i++){for (int j = 0; j < n; j++){if (dist[i, k] != int.MaxValue && dist[k, j] != int.MaxValue &&dist[i, k] + dist[k, j] < dist[i, j]){dist[i, j] = dist[i, k] + dist[k, j];}}}}Console.WriteLine("All Pairs Shortest Paths:");for (int i = 0; i < n; i++){for (int j = 0; j < n; j++){if (dist[i, j] == int.MaxValue){Console.Write("INF\t");}else{Console.Write(dist[i, j] + "\t");}}Console.WriteLine();}}static void Main(){int n = 4;int[,] graph = {{ 0, 5, int.MaxValue, 10 },{ int.MaxValue, 0, 3, int.MaxValue },{ int.MaxValue, int.MaxValue, 0, 1 },{ int.MaxValue, int.MaxValue, int.MaxValue, 0 }};FloydWarshall(graph, n);}
}

11. 哈希算法

哈希算法用于将数据映射到固定大小的哈希值,常用于快速查找、数据去重等。

using System;
using System.Collections.Generic;class HashExample
{static void Main(){Dictionary<int, string> hashTable = new Dictionary<int, string>();hashTable[1] = "apple";hashTable[2] = "banana";hashTable[3] = "cherry";if (hashTable.ContainsKey(2)){Console.WriteLine($"Key 2 的值是: {hashTable[2]}");}hashTable[2] = "orange";Console.WriteLine($"更新后 Key 2 的值是: {hashTable[2]}");hashTable.Remove(3);Console.WriteLine("移除 Key 3 后哈希表:");foreach (var pair in hashTable){Console.WriteLine($"Key: {pair.Key}, Value: {pair.Value}");}}
}

12. 排序算法

12.1. 冒泡排序

冒泡排序通过多次比较相邻元素并交换位置,将最大(或最小)的元素逐步“冒泡”到数组末尾。

using System;class BubbleSortExample
{static void BubbleSort(int[] arr){int n = arr.Length;for (int i = 0; i < n - 1; i++){for (int j = 0; j < n - i - 1; j++){if (arr[j] > arr[j + 1]){int temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}}static void Main(){int[] nums = { 64, 34, 25, 12, 22, 11, 90 };BubbleSort(nums);Console.Write("排序后的数组: ");foreach (int num in nums){Console.Write(num + " ");}}
}

12.2. 选择排序

选择排序每次从未排序的元素中找到最小(或最大)的元素,将其放到已排序序列的末尾。

using System;class SelectionSortExample
{static void SelectionSort(int[] arr){int n = arr.Length;for (int i = 0; i < n - 1; i++){int minIndex = i;for (int j = i + 1; j < n; j++){if (arr[j] < arr[minIndex]){minIndex = j;}}int temp = arr[minIndex];arr[minIndex] = arr[i];arr[i] = temp;}}static void Main(){int[] nums = { 64, 34, 25, 12, 22, 11, 90 };SelectionSort(nums);Console.Write("排序后的数组: ");foreach (int num in nums){Console.Write(num + " ");}}
}

12.3. 插入排序

插入排序将一个数据插入到已经排好序的数组中的适当位置,直到整个数组有序。

using System;class InsertionSortExample
{static void InsertionSort(int[] arr){int n = arr.Length;for (int i = 1; i < n; i++){int key = arr[i];int j = i - 1;while (j >= 0 && arr[j] > key){arr[j + 1] = arr[j];j = j - 1;}arr[j + 1] = key;}}static void Main(){int[] nums = { 64, 34, 25, 12, 22, 11, 90 };InsertionSort(nums);Console.Write("排序后的数组: ");foreach (int num in nums){Console.Write(num + " ");}}
}

12.4. 希尔排序

希尔排序是对插入排序的改进,通过将数组分成若干个子序列,对每个子序列进行插入排序,逐步缩小间隔,最终使整个数组有序。

using System;class ShellSortExample
{static void ShellSort(int[] arr){int n = arr.Length;for (int gap = n / 2; gap > 0; gap /= 2){for (int i = gap; i < n; i++){int temp = arr[i];int j;for (j = i; j >= gap && arr[j - gap] > temp; j -= gap){arr[j] = arr[j - gap];}arr[j] = temp;}}}static void Main(){int[] nums = { 64, 34, 25, 12, 22, 11, 90 };ShellSort(nums);Console.Write("排序后的数组: ");foreach (int num in nums){Console.Write(num + " ");}}
}

12.5. 归并排序

归并排序是一种分治算法,将数组分成两个子数组,分别排序后再合并成一个有序数组。

using System;class MergeSortExample
{static void Merge(int[] arr, int left, int mid, int right){int n1 = mid - left + 1;int n2 = right - mid;int[] L = new int[n1];int[] R = new int[n2];for (int i = 0; i < n1; i++){L[i] = arr[left + i];}for (int j = 0; j < n2; j++){R[j] = arr[mid + 1 + j];}int i = 0, j = 0, k = left;while (i < n1 && j < n2){if (L[i] <= R[j]){arr[k] = L[i];i++;}else{arr[k] = R[j];j++;}k++;}while (i < n1){arr[k] = L[i];i++;k++;}while (j < n2){arr[k] = R[j];j++;k++;}}static void MergeSort(int[] arr, int left, int right){if (left < right){int mid = left + (right - left) / 2;MergeSort(arr, left, mid);MergeSort(arr, mid + 1, right);Merge(arr, left, mid, right);}}static void Main(){int[] nums = { 64, 34, 25, 12, 22, 11, 90 };MergeSort(nums, 0, nums.Length - 1);Console.Write("排序后的数组: ");foreach (int num in nums){Console.Write(num + " ");}}
}

12.6. 快速排序

快速排序也是一种分治算法,选择一个基准元素,将数组分为两部分,使得左边部分的元素都小于基准,右边部分的元素都大于基准,然后分别对两部分递归排序。

using System;class QuickSortExample
{static int Partition(int[] arr, int low, int high){int pivot = arr[high];int i = low - 1;for (int j = low; j < high; j++){if (arr[j] < pivot){i++;int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}int temp1 = arr[i + 1];arr[i + 1] = arr[high];arr[high] = temp1;return i + 1;}static void QuickSort(int[] arr, int low, int high){if (low < high){int pi = Partition(arr, low, high);QuickSort(arr, low, pi - 1);QuickSort(arr, pi + 1, high);}}static void Main(){int[] nums = { 64, 34, 25, 12, 22, 11, 90 };QuickSort(nums, 0, nums.Length - 1);Console.Write("排序后的数组: ");foreach (int num in nums){Console.Write(num + " ");}}
}

以下是继续完成堆排序以及后面排序算法示例的内容:

12.7. 堆排序

堆排序利用堆这种数据结构来实现排序,将数组构建成一个最大堆(或最小堆),然后依次取出堆顶元素并调整堆,最终得到有序数组。

using System;class HeapSortExample
{static void Heapify(int[] arr, int n, int i){int largest = i;int left = 2 * i + 1;int right = 2 * i + 2;if (left < n && arr[left] > arr[largest]){largest = left;}if (right < n && arr[right] > arr[largest]){largest = right;}if (largest != i){int temp = arr[i];arr[i] = arr[largest];arr[largest] = temp;Heapify(arr, n, largest);}}static void HeapSort(int[] arr){int n = arr.Length;for (int i = n / 2 - 1; i >= 0; i--){Heapify(arr, n, i);}for (int i = n - 1; i > 0; i--){int temp = arr[0];arr[0] = arr[i];arr[i] = temp;Heapify(arr, i, 0);}}static void Main(){int[] nums = { 64, 34, 25, 12, 22, 11, 90 };HeapSort(nums);Console.Write("排序后的数组: ");foreach (int num in nums){Console.Write(num + " ");}}
}

12.8. 计数排序

计数排序适用于一定范围内的整数排序,通过统计每个值出现的次数,再根据统计结果将元素依次放回数组中。

using System;class CountingSortExample
{static void CountingSort(int[] arr){int max = arr[0];foreach (int num in arr){if (num > max){max = num;}}int[] count = new int[max + 1];foreach (int num in arr){count[num]++;}int index = 0;for (int i = 0; i < count.Length; i++){while (count[i] > 0){arr[index++] = i;count[i]--;}}}static void Main(){int[] nums = { 4, 2, 2, 8, 3, 3, 1 };CountingSort(nums);Console.Write("排序后的数组: ");foreach (int num in nums){Console.Write(num + " ");}}
}

12.9. 桶排序

桶排序将数据分到有限数量的桶中,每个桶再分别进行排序(可以使用其他排序算法),最后将各个桶中的元素合并起来得到有序数组。

using System;
using System.Collections.Generic;class BucketSortExample
{static void BucketSort(double[] arr){int numBuckets = 10;List<double>[] buckets = new List<double>[numBuckets];for (int i = 0; i < numBuckets; i++){buckets[i] = new List<double>();}foreach (double num in arr){int bucketIndex = (int)(num * numBuckets);buckets[bucketIndex].Add(num);}int index = 0;for (int i = 0; i < numBuckets; i++){buckets[i].Sort();foreach (double num in buckets[i]){arr[index++] = num;}}}static void Main(){double[] nums = { 0.42, 0.32, 0.33, 0.52, 0.37, 0.47, 0.51 };BucketSort(nums);Console.Write("排序后的数组: ");foreach (double num in nums){Console.Write(num + " ");}}
}

12.10. 基数排序

基数排序从低位到高位依次对数字的每一位进行排序,根据该位的值将数字分配到不同的桶中,再依次收集起来,最终得到有序数组。

using System;class RadixSortExample
{static int GetMax(int[] arr){int max = arr[0];for (int i = 1; i < arr.Length; i++){if (arr[i] > max){max = arr[i];}}return max;}static void CountingSortByDigit(int[] arr, int exp){int[] output = new int[arr.Length];int[] count = new int[10];for (int i = 0; i < arr.Length; i++){count[(arr[i] / exp) % 10]++;}for (int i = 1; i < 10; i++){count[i] += count[i - 1];}for (int i = arr.Length - 1; i >= 0; i--){output[count[(arr[i] / exp) % 10] - 1] = arr[i];count[(arr[i] / exp) % 10]--;}for (int i = 0; i < arr.Length; i++){arr[i] = output[i];}}static void RadixSort(int[] arr){int max = GetMax(arr);for (int exp = 1; max / exp > 0; exp *= 10){CountingSortByDigit(arr, exp);}}static void Main(){int[] nums = { 170, 45, 75, 90, 802, 24, 2, 66 };RadixSort(nums);Console.Write("排序后的数组: ");foreach (int num in nums){Console.Write(num + " ");}}
}

13. 位运算算法

位运算算法是直接对整数在二进制表示上进行操作的算法,常用于高效地处理数据。例如判断一个数是否为 2 的幂次方:

using System;class BitwiseOperationExample
{static bool IsPowerOfTwo(int num){return (num > 0) && ((num & (num - 1)) == 0);}static void Main(){int number = 8;bool result = IsPowerOfTwo(number);if (result){Console.WriteLine($"{number} 是 2 的幂次方");}else{Console.WriteLine($"{number} 不是 2 的幂次方");}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/74295.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度学习:让机器学会“思考”的魔法

文章目录 引言&#xff1a;从“鹦鹉学舌”到“举一反三”一、深度学习是什么&#xff1f;1. 定义&#xff1a;机器的“大脑”2. 核心思想&#xff1a;从数据中“悟”出规律 二、深度学习的“大脑”结构&#xff1a;神经网络1. 神经元&#xff1a;深度学习的基本单元2. 神经网络…

电动自行车/电动工具锂电池PCM方案--SH367003、SH367004、SH79F329

在消费电子系统中&#xff0c;如手机电池包&#xff0c;笔记本电脑电池包等&#xff0c;带有控制IC、功率MOSFETFE管以及其他电子元件的电路系统称为电池充放电保护板Protection Circuit Module &#xff08;PCM&#xff09;&#xff0c;而对于动力电池的电池管理系统&#xff…

补码详细分析

补码引入 举一个生活化的例子 假设由一个挂钟&#xff0c;它只能顺时钟调时间&#xff0c;那么它调时间就分成了一下两种情况 正好顺时针调就能调好 如&#xff1a;时针从5调到9需要逆时针调才能调好 如&#xff1a;时针从10调到7 在上面的情况中1是不用处理的&#xff0c;2…

计算机网络入门:物理层与数据链路层详解

&#x1f310; &#xff08;专业解析 中学生也能懂&#xff01;&#xff09; &#x1f4d6; 前言 计算机网络就像数字世界的“高速公路系统”&#xff0c;而物理层和数据链路层是这条公路的基石。本文用 专业视角 和 生活化比喻 &#xff0c;带你轻松理解这两层的核心原理&a…

哪些视频格式在webview2中播放可以设置成透明的?

在WebView2中&#xff0c;能够播放并设置成透明背景的视频格式主要取决于其支持的编解码器以及视频是否包含alpha通道&#xff08;透明度信息&#xff09;。以下是支持透明背景的视频格式&#xff1a; 支持透明背景的视频格式 1. WebM&#xff08;使用VP9编解码器&#xff09; …

【基于ROS的A*算法实现路径规划】A* | ROS | 路径规划 | Python

### 记录一下使用Python实现ROS平台A*算法路径规划 ### 代码可自取 &#xff1a;Xz/little_projecthttps://gitee.com/Xz_zh/little_project.git 目录 一、思路分析 二、算法实现 三、路径规划实现 一、思路分析 要求使用A*算法实现路径规划&#xff0c;可以将该任务分为三…

2025-03-23 吴恩达机器学习3——多维特征

文章目录 1 多元引入2 矢量化2.1 示例2.2 非矢量化实现2.3 矢量化实现2.4 应用 3 特征缩放3.1 举例3.2 必要性3.3 方法3.3.1 最大最小值缩放&#xff08;Min-Max Scaling&#xff09;3.3.2 均值归一化&#xff08;Mean Normalization&#xff09;3.3.3 Z 分数归一化&#xff08…

正点原子内存管理学习和修改

由于项目需要用到内存管理进行动态申请和释放&#xff0c;今天又重新学习了一下正点原子的内存管理实验&#xff0c;温习了一下内存管理的实质。首先先上正点原子内存管理的源代码&#xff1a; malloc.c文件&#xff1a; #include "./MALLOC/malloc.h"#if !(__ARMC…

时空观测者:俯身拾贝

目录 中华文明时空贝壳集&#xff08;按时间排序&#xff09;1. 良渚玉琮&#xff08;约公元前3300-2300年&#xff09;2. 三星堆青铜神树&#xff08;公元前1200年&#xff09;3. 殷墟甲骨文&#xff08;约公元前14世纪&#xff09;4. 京杭大运河&#xff08;公元前486年始建&…

护网期间监测工作全解析:内容与应对策略

护网期间监测工作全解析&#xff1a;内容与应对策略 一、引言 在数字化浪潮中&#xff0c;网络安全的重要性愈发凸显&#xff0c;护网行动作为保障关键信息基础设施安全的关键举措&#xff0c;备受瞩目。护网期间&#xff0c;监测工作是发现潜在威胁、防范攻击的重要防线。全…

【Centos7搭建Zabbix4.x监控HCL模拟网络设备:zabbix-server搭建及监控基础05

兰生幽谷&#xff0c;不为莫服而不芳&#xff1b; 君子行义&#xff0c;不为莫知而止休。 5.zabbix监控HCL模拟网络设备 在保证zabbix-server与HCL网络相通的情况下进行如下操作。 5.1创建主机群 配置-主机群-创建主机群 图 19 取名&#xff0c;添加。 图 20 5.2 创建监控…

趣味极简品牌海报艺术贴纸设计圆润边缘无衬线粗体装饰字体 Chunko Bold - Sans Serif Font

Chunko Bold 是一种功能强大的显示字体&#xff0c;体现了大胆极简主义的原则 – 当代设计的主流趋势。这种自信的字体将粗犷的几何形状与现代的趣味性相结合&#xff0c;具有圆润的边缘和强烈的存在感&#xff0c;与当今的极简主义设计方法完美契合。无论是用于鲜明的构图还是…

Spring Boot(十七):集成和使用Redis

Redis(Remote Dictionary Server,远程字典服务器)是一个开源的、基于内存的数据结构存储系统,它可以用作数据库、缓存和消息中间件。Spring Boot 中集成和使用Redis主要涉及以下几个步骤: 添加依赖 在项目的pom.xml文件中添加Redis的依赖。Spring Boot提供了对Redis的集…

2025-03-21 Unity 序列化 —— 自定义2进制序列化

文章目录 前言1 项目结构1.1 整体1.2 代码 2 实现2.1 Processor2.1.1 BaseType2.1.2 CollectionType2.1.3 CustomType 2.2 ByteFormatter2.3 ByteHelper 3 使用 前言 ​ BinaryFormatter 类可以将 C# 类对象快速转换为字节数组数据。 ​ 在网络开发时&#xff0c;不会使用 Bi…

为WordPress自定义一个留言板

要在WordPress中创建一个留言反馈表单&#xff0c;并实现后台管理功能&#xff0c;您可以按照以下步骤进行操作&#xff1a; 1. 创建留言反馈表单 首先&#xff0c;您需要使用一个表单插件来创建表单。推荐使用 Contact Form 7 或 WPForms。以下是使用 Contact Form 7 的示例…

嵌入式项目:利用心知天气获取天气数据实验方案

【实验目的】 1、利用心知天气服务器获取指定位置天气数据 2、将天气数据解析并可视化显示到OLED屏幕 【实验原理】 【实验步骤】 官网注册

go-zero学习笔记

内容不多&#xff0c;只有部分笔记&#xff0c;剩下的没有继续学下去&#xff0c;包括路由与处理器、日志中间件、请求上下文 文章目录 1、go-zero核心库1.1 路由与处理器1.2 日志中间件1.3 请求上下文 1、go-zero核心库 1.1 路由与处理器 package mainimport ("github…

【Go】Go语言继承-多态模拟

继承&#xff08;结构体嵌入&#xff09;多态&#xff08;接口实现和空接口&#xff09; 1. 继承&#xff08;结构体嵌入&#xff09; Go 语言没有传统的面向对象的继承机制&#xff0c;但可以通过“结构体嵌入”实现类似继承的效果。 结构体嵌入&#xff1a;在结构体中嵌入另…

kotlin知识体系(四) : inline、noinline、crossinline 关键字对应编译后的代码是怎样的 ?

kotlin中inline、noinline、crossinline 关键字的作用 在 Kotlin 里&#xff0c;inline、noinline 和 crossinline 这几个关键字和高阶函数紧密相关&#xff0c;它们能够对高阶函数的行为进行优化和控制。下面为你详细阐述它们的作用和原理。 inline 关键字 inline 关键字用…

LabVIEW FPGA与Windows平台数据滤波处理对比

LabVIEW在FPGA和Windows平台均可实现数据滤波处理&#xff0c;但两者的底层架构、资源限制、实时性及应用场景差异显著。FPGA侧重硬件级并行处理&#xff0c;适用于高实时性场景&#xff1b;Windows依赖软件算法&#xff0c;适合复杂数据处理与可视化。本文结合具体案例&#x…