BFS模板-宽度优先搜索(Breadth First Search)

1.模板

/// <summary>
/// BFS遍历
/// </summary>
/// <param name="start">开始节点</param>
/// <param name="target">目标节点</param>
/// <returns></returns>
public int BFS(Node start, Node target)
{
//利用队列先进先出(FIFO)的特点
Queue<Node> que = new Queue<Node>();
HashSet<Node> visited = new HashSet<Node>(); //避免走回头路 int leval = 0; // 记录遍历的层数
if (start != null)
{
que.Enqueue(start); //将起点加入队列
visited.Add(start);
}
while (que.Count > 0)
{
int len = que.Count;
//当前层中的所有节点
for (int i = 0; i < len; i++)
{
Node cur = que.Dequeue();
/* 划重点:这里判断是否到达终点 */
if (cur == target)
return leval;
/* 将 cur 的下一层子节点加入队列 */
foreach (Node x in cur.childList)
{
if (!visited.Contains(x))
{
que.Enqueue(x);
visited.Add(x);
}
}
}
/* 划重点:更新步数在这里 */
leval++;
}
return leval;
}

2.推荐题目

  1. https://leetcode.cn/problems/binary-tree-level-order-traversal/
  2. https://leetcode.cn/problems/minimum-depth-of-binary-tree/
  3. https://leetcode.cn/problems/open-the-lock/

回溯模板

通用模板

List<List<T>> res = new List<List<T>>();
List<T> path = new List<T>();
public void Backtracking(入参)
{
if (满足结束条件)
{
result.add(路径);
return;
}
for (选择 in 选择列表)
{
做选择
backtrack(路径, 选择列表)
撤销选择
}
}

无论是排列、组合还是子集问题,简单说无非就是让你从序列 nums 中以给定规则取若干元素

1. 元素无重不可复选

元素无重不可复选,即 nums 中的元素都是唯一的,每个元素最多只能被使用一次,这也是最基本的形式

组合、分割、子集

//问题:输入一个无重复元素的数组 nums,其中每个元素最多使用一次,请你返回 nums 的所有子集
List<List<int>> res = new List<List<int>>();
List<int> path = new List<int>();
public List<List<int>> Subsets(int[] nums)
{
BackTrack(nums, 0);
return res;
}
public void BackTrack(int[] nums, int start)
{
res.Add(new List<int>(path));
/*从入参下标开始*/
for (int i = start; i < nums.Length; i++)
{
path.Add(nums[i]);
BackTrack(nums, i + 1);
path.RemoveAt(path.Count - 1);
}
}

排列

/* 问题:输入一组不重复的数字,返回它们的全排列 */
List<List<int>> res = new List<List<int>>();
List<int> path = new List<int>();
//去重,记录元素是否被使用
bool[] used;
public List<List<int>> Permute(int[] nums)
{
used = new bool[nums.Length];
BackTrack(nums);
return res;
}
void BackTrack(int[] nums)
{
if (path.Count == nums.Length)
{
res.Add(new List<int>(path));
return;
}
/*排列 i从0开始*/
for (int i = 0; i < nums.Length; i++)
{
if (used[i])
continue;
//选择
used[i] = true;
path.Add(nums[i]);
//递归
BackTrack(nums);
//回溯
path.RemoveAt(path.Count-1);
used[i] = false;
}
}

2. 元素可重不可复选

组合、分割、子集

/*问题:给你一个整数数组 nums,其中可能包含重复元素,请你返回该数组所有可能的子集*/
List<List<int>> res = new List<List<int>>();
List<int> path = new List<int>();
public List<List<int>> subsetsWithDup(int[] nums)
{
// 先排序,让相同的元素靠在一起
Array.Sort(nums);
backtrack(nums, 0);
return res;
}
void backtrack(int[] nums, int start)
{
// 前序位置,每个节点的值都是一个子集
res.Add(new List<int>(path));
for (int i = start; i < nums.Length; i++)
{
// 剪枝逻辑,值相同的相邻树枝,只遍历第一条
if (i > start && nums[i] == nums[i - 1])
{
continue;
}
path.Add(nums[i]);
backtrack(nums, i + 1);
path.RemoveAt(path.Count);
}
}

排列

/*问题:给你输入一个可包含重复数字的序列 nums,请你写一个算法,返回所有可能的全排列,*/
List<List<int>> res = new List<List<int>>();
List<int> path = new List<int>();
bool[] used;
public List<List<int>> permuteUnique(int[] nums)
{
// 先排序,让相同的元素靠在一起
Array.Sort(nums);
used = new bool[nums.Length];
Backpath(nums);
return res;
} void Backpath(int[] nums)
{
if (path.Count == nums.Length)
{
res.Add(new List<int>(path));
return;
}
for (int i = 0; i < nums.Length; i++)
{
// 新添加的剪枝逻辑,固定相同的元素在排列中的相对位置
if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1])
{
continue;
}
path.Add(nums[i]);
used[i] = true;
Backpath(nums);
path.RemoveAt(path.Count);
used[i] = false;
}
}

3. 元素无重可复选

组合、分割、子集

/*问题:给你一个无重复元素的整数数组 candidates 和一个目标和 target,找出 candidates 中可以使数字和为目标数 target 的所有组合*/
List<List<int>> res = new List<List<int>>();
List<int> path = new List<int>();
int sum = 0;
public List<List<int>> CombinationSum(int[] candidates, int target)
{
if (candidates.Length == 0)
{
return res;
}
BackTrack(candidates, 0, target);
return res;
}
void BackTrack(int[] nums, int start, int target)
{
// base case,找到目标和,记录结果
if (sum == target)
{
res.Add(new List<int>(path));
return;
}
// base case,超过目标和,停止向下遍历
if (sum > target)
{
return;
}
for (int i = start; i < nums.Length; i++)
{
// 选择 nums[i]
sum += nums[i];
path.Add(nums[i]);
// 递归遍历下一层回溯树
// 同一元素可重复使用,注意参数
BackTrack(nums, i, target);
// 撤销选择 nums[i]
sum -= nums[i];
path.RemoveAt(path.Count-1);
}
}

排列

List<List<int>> res =new List<List<int>>();
List<int> path =new List<int>(); public List<List<int>> permuteRepeat(int[] nums)
{
BackTrack(nums);
return res;
}
void BackTrack(int[] nums)
{
if (path.Count == nums.Length)
{
res.Add(new List<int>(path));
return;
}
// 回溯算法标准框架
for (int i = 0; i < nums.Length; i++)
{
// 做选择
path.Add(nums[i]);
// 进入下一层回溯树
BackTrack(nums);
// 取消选择
path.RemoveAt(path.Count-1);
}
}

4. 元素可重可复选

将元素去重后,执行元素无重可复选

二叉树遍历

DFS方法,前中后、层序遍历


/// <summary>
/// 前序遍历(中左右)
/// </summary>
/// <param name="root"></param>
/// <returns></returns>
public IList<int> PreorderTraversal(TreeNode root)
{
List<int> result = new List<int>();
Preorder(result, root);
return result;
}
public void Preorder(List<int> result, TreeNode node)
{
if (node == null) return;
result.Add(node.val);//中
Preorder(result, node.left);//左
Preorder(result, node.right);//右
} /// <summary>
/// 中序遍历(左中右)
/// </summary>
/// <param name="root"></param>
/// <returns></returns>
public IList<int> InorderTraversal(TreeNode root)
{
List<int> result = new List<int>();
Inorder(result, root);
return result;
}
public void Inorder(List<int> result, TreeNode node)
{
if (node == null) return;
Inorder(result, node.left);//左
result.Add(node.val);//中
Inorder(result, node.right);//右
} /// <summary>
/// 后序遍历(左右中)
/// </summary>
/// <param name="root"></param>
/// <returns></returns>
public IList<int> PostOrderTraversal(TreeNode root)
{
List<int> result = new List<int>();
PostOrder(result, root);
return result;
}
public void PostOrder(List<int> result, TreeNode node)
{
if (node == null) return;
PostOrder(result, node.left);//左
PostOrder(result, node.right);//右
result.Add(node.val);//中
}
/// <summary>
/// 层序遍历
/// </summary>
/// <param name="root"></param>
/// <returns></returns>
IList<IList<int>> res = new List<IList<int>>();
public IList<IList<int>> LevelOrder(TreeNode root)
{
LevelDFS(root, 0);
return res;
}
public void LevelDFS(TreeNode root, int deep)
{
if (root == null) return;
deep++;
if (res.Count < deep)
{
IList<int> item = new List<int>();
res.Add(item);
}
res[deep - 1].Add(root.val);
LevelDFS(root.left, deep);
LevelDFS(root.right, deep);
}

BFS方法,前中后、层序遍历

/// <summary>
/// 前序遍历(中左右)
/// </summary>
/// <param name="root"></param>
/// <returns></returns>
public IList<int> PreOrderTraversal(TreeNode root)
{
IList<int> res = new List<int>();
Stack<TreeNode> st = new Stack<TreeNode>();
if (root != null) st.Push(root);
while (st.Count > 0)
{
TreeNode node = st.Pop();
if (node != null)
{
if (node.right != null) st.Push(node.right);
if (node.left != null) st.Push(node.left);
st.Push(node);
st.Push(null);
}
else
{
node = st.Pop();
res.Add(node.val);
}
}
return res;
} /// <summary>
/// 中序遍历(左中右)
/// </summary>
/// <param name="root"></param>
/// <returns></returns>
public IList<int> InorderTraversal(TreeNode root)
{
IList<int> res = new List<int>();
Stack<TreeNode> st = new Stack<TreeNode>();
if (root != null) st.Push(root);
while (st.Count > 0)
{
TreeNode node = st.Pop();
if (node != null)
{
if (node.right != null) st.Push(node.right);
st.Push(node);
st.Push(null);
if (node.left != null) st.Push(node.left);
}
else
{
node = st.Pop();
res.Add(node.val);
}
}
return res;
} /// <summary>
/// 后序遍历(左右中)
/// </summary>
/// <param name="root"></param>
/// <returns></returns>
public IList<int> PostOrderTraversal(TreeNode root)
{
IList<int> res = new List<int>();
Stack<TreeNode> st = new Stack<TreeNode>();
if (root != null) st.Push(root);
while (st.Count > 0)
{
TreeNode node = st.Pop();
if (node != null)
{
st.Push(node);
st.Push(null);
if (node.right != null) st.Push(node.right);
if (node.left != null) st.Push(node.left);
}
else
{
node = st.Pop();
res.Add(node.val);
}
}
return res;
}
/// <summary>
/// 层序遍历
/// </summary>
/// <param name="root"></param>
/// <returns></returns>
IList<IList<int>> res = new List<IList<int>>();
public IList<IList<int>> LevelOrder(TreeNode root)
{
Queue<TreeNode> que = new Queue<TreeNode>();
if (root != null) que.Enqueue(root);
while (que.Count > 0)
{
IList<int> item = new List<int>();
int len = que.Count;
while (len > 0)
{
TreeNode node = que.Dequeue();
item.Add(node.val);
if (node.left != null) que.Enqueue(node.left);
if (node.right != null) que.Enqueue(node.right);
len--;
}
res.Add(item);
}
return res;
}

排序算法

快速排序

//right=Length-1;
public void QuickSort(int[] nums, int left, int right)
{
if (left >= right) return;
/*添加随机获取下标,变成随机快排*/
int s = new Random().Next(right - left + 1) + left;
int item = nums[s];
nums[s] = nums[right];
nums[right] = item; //常规快排
int index = Sort(nums, left, right);
QuickSort(nums, left, index);
QuickSort(nums, index+1, right);
}
public int Sort(int[] nums, int left, int right)
{
int key = nums[left];//基准数
while (left < right)
{
while (left < right && nums[right] >= key) right--;
nums[left] = nums[right];
while (left < right && nums[left] <= key) left++;
nums[right] = nums[left];
}
nums[left] = key;
return right;//左开右闭 返回right
}

归并排序

int[] temp;
public int[] SortArray(int[] nums)
{
if (nums == null || nums.Length == 0) return nums;
temp = new int[nums.Length];
MergeSort(nums, 0, nums.Length - 1);
return nums;
}
public void MergeSort(int[] nums, int left, int right)
{
if (left == right) return;
int mid = left + (right - left) / 2;//中间节点
//类似二叉树后序遍历
MergeSort(nums, left, mid);
MergeSort(nums, mid + 1, right);
Merge(nums, left, mid, right);
}
//以mid为中间点合并[left..mid]和[mid+1..right]
public void Merge(int[] nums, int left, int mid, int right)
{
//nums [3,5,2,6]
//[left..mid]=[3,5]
//[mid+1..right]=[2,6]
for (int i = left; i <= right; i++)
{
temp[i] = nums[i];
}
//temp [3,5,6,2]
int rl = left;
int rr = mid+1;
for (int i = left; i <= right; i++)
{
if (rl == mid+1)//左指针到头
nums[i] = temp[rr++];
else if (rr == right+1)//右指针到头
nums[i] = temp[rl++];
else if (temp[rl] > temp[rr])//左大于右
nums[i] = temp[rr++];
else
nums[i] = temp[rl++];
}
}

堆排序

//对于大顶堆:arr[i] >= arr[2i + 1] && arr[i] >= arr[2i + 2]
//对于小顶堆:arr[i] <= arr[2i + 1] && arr[i] <= arr[2i + 2]
//1、将无序序列构建成一个大顶堆。
//2.将堆顶元素和最后一个元素交换,然后将剩下的节点重新构造成一个大顶堆;
//3.重复步骤2,如此反复,从第一次构建大顶堆开始,每一次构建,我们都能获得一个序列的最大值,然后把它放到大顶堆的尾部。最后,就得到一个有序的序列了
//3, 2, 3, 1, 2, 4, 5, 5, 6
public int[] HeapSort(int[] nums)
{
//这里元素的索引是从0开始的,所以最后一个非叶子结点array.length/2 - 1
for (int i = nums.Length / 2 - 1; i >= 0; i--)
{
adjustHeap(nums, i, nums.Length); //调整堆
}
// 上述逻辑,建堆结束
// 下面,开始排序逻辑
for (int j = nums.Length - 1; j > 0; j--)
{
// 元素交换,作用是去掉大顶堆
// 把大顶堆的根元素,放到数组的最后;换句话说,就是每一次的堆调整之后,都会有一个元素到达自己的最终位置
swap(nums, 0, j);
// 元素交换之后,毫无疑问,最后一个元素无需再考虑排序问题了。
// 接下来我们需要排序的,就是已经去掉了部分元素的堆了,这也是为什么此方法放在循环里的原因
// 而这里,实质上是自上而下,自左向右进行调整的
adjustHeap(nums, 0, j);
}
return nums;
}
public static void adjustHeap(int[] array, int i, int length)
{
// 先把当前元素取出来,因为当前元素可能要一直移动
int temp = array[i];
for (int k = 2 * i + 1; k < length; k = 2 * k + 1)
{ //2*i+1为左子树i的左子树(因为i是从0开始的),2*k+1为k的左子树
// 让k先指向子节点中最大的节点
if (k + 1 < length && array[k] < array[k + 1])
{ //如果有右子树,并且右子树大于左子树
k++;
}
//如果发现结点(左右子结点)大于根结点,则进行值的交换
if (array[k] > temp)
{
swap(array, i, k);
// 如果子节点更换了,那么,以子节点为根的子树会受到影响,所以,循环对子节点所在的树继续进行判断
i = k;
}
else
{ //不用交换,直接终止循环
break;
}
}
}
public static void swap(int[] arr, int a, int b)
{
int temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}

滑动窗口

/* 滑动窗口算法框架 */
void SlidingWindow(string s)
{
Dictionary<char, int> window=new Dictionary<char, int>();
int left = 0, right = 0;
while (right < s.Length)
{
// c 是将移入窗口的字符
char c = s[right];
// 增大窗口
right++;
// 进行窗口内数据的一系列更新
/*
* ...
*/
/*** debug 输出的位置 ***/
// 注意在最终的解法代码中不要 print
// 因为 IO 操作很耗时,可能导致超时
Console.WriteLine("window: [%d, %d)\n", left, right);
/********************/ // 判断左侧窗口是否要收缩
while (window needs shrink) {
// d 是将移出窗口的字符
char d = s[left];
// 缩小窗口
left++;
// 进行窗口内数据的一系列更新
/*
* ...
*/
}
}
}

并查集模板

class UF
{
// 连通分量个数
private int count;
// 存储每个节点的父节点
private int[] parent; // n 为图中节点的个数
public UF(int n)
{
count = n;
parent = new int[n];
for (int i = 0; i < n; i++)
{
parent[i] = i;
}
} // 将节点 p 和节点 q 连通
public void Union(int p, int q)
{
int rootP = Find(p);
int rootQ = Find(q); if (rootP == rootQ)
return; parent[rootQ] = rootP;
// 两个连通分量合并成一个连通分量
count--;
} // 判断节点 p 和节点 q 是否连通
public bool Connected(int p, int q)
{
int rootP = Find(p);
int rootQ = Find(q);
return rootP == rootQ;
} public int Find(int x)
{
if (parent[x] != x)
{
parent[x] = Find(parent[x]);
}
return parent[x];
} // 返回图中的连通分量个数
public int Count()
{
return count;
}
}

前缀和,差分数组模板

前缀和模板

/// <summary>
/// 前缀和模板
/// </summary>
class NumArray
{
// 前缀和数组
private int[] preSum; /* 输入一个数组,构造前缀和 */
public NumArray(int[] nums)
{
// preSum[0] = 0,便于计算累加和
preSum = new int[nums.Length + 1];
// 计算 nums 的累加和
for (int i = 1; i < preSum.Length; i++)
{
preSum[i] = preSum[i - 1] + nums[i - 1];
}
} /* 查询闭区间 [left, right] 的累加和 */
public int SumRange(int left, int right)
{
return preSum[right + 1] - preSum[left];
}
}

查分数组模板

/// <summary>
/// 查分数组模板
/// </summary>
class Difference
{
// 差分数组
private int[] diff; /* 输入一个初始数组,区间操作将在这个数组上进行 */
public Difference(int[] nums)
{
diff = new int[nums.Length];
// 根据初始数组构造差分数组
diff[0] = nums[0];
for (int i = 1; i < nums.Length; i++)
{
diff[i] = nums[i] - nums[i - 1];
}
} /* 给闭区间 [i, j] 增加 val(可以是负数)*/
public void Increment(int i, int j, int val)
{
diff[i] += val;
if (j + 1 < diff.Length)
{
diff[j + 1] -= val;
}
} /* 返回结果数组 */
public int[] Result()
{
int[] res = new int[diff.Length];
// 根据差分数组构造结果数组
res[0] = diff[0];
for (int i = 1; i < diff.Length; i++)
{
res[i] = res[i - 1] + diff[i];
}
return res;
}
}

动态规划模板

基础问题

//不同的二叉搜索树
public int NumTrees(int n)
{
//初始化 dp 数组
int[] dp = new int[n + 1];
//初始化0个节点和1个节点的情况
dp[0] = 1;
dp[1] = 1;
for (int i = 2; i <= n; i++)
{
for (int j = 1; j <= i; j++)
{
//对于第i个节点,需要考虑1作为根节点直到i作为根节点的情况,所以需要累加
//一共i个节点,对于根节点j时,左子树的节点个数为j-1,右子树的节点个数为i-j
dp[i] += dp[j - 1] * dp[i - j];
}
}
return dp[n];
}

背包问题

01背包

class Solution
{
public static void Main(String[] args)
{
int[] weight = { 1, 3, 4 };
int[] value = { 15, 20, 30 };
int bagWight = 4;
TestWeightBagProblem(weight, value, bagWight);
} public static void TestWeightBagProblem(int[] weight, int[] value, int bagWeight)
{
int wLen = weight.Length;
//定义dp数组:dp[j]表示背包容量为j时,能获得的最大价值
int[] dp = new int[bagWeight + 1];
//遍历顺序:先遍历物品,再遍历背包容量
for (int i = 0; i < wLen; i++)
{
for (int j = bagWeight; j >= weight[i]; j--)
{
dp[j] = Math.Max(dp[j], dp[j - weight[i]] + value[i]);
}
}
//打印dp数组
for (int j = 0; j <= bagWeight; j++)
{
Console.WriteLine(dp[j] + " ");
}
}
}

完全背包

private static void TestCompletePack()
{
int[] weight = { 1, 3, 4 };
int[] value = { 15, 20, 30 };
int bagWeight = 4;
int[] dp = new int[bagWeight + 1];
for (int i = 0; i < weight.Length; i++)
{ // 遍历物品
for (int j = weight[i]; j <= bagWeight; j++)
{ // 遍历背包容量
dp[j] = Math.Max(dp[j], dp[j - weight[i]] + value[i]);
}
}
}

打家劫舍

打家劫舍1

public int Rob(int[] nums)
{
if (nums == null || nums.Length == 0) return 0;
if (nums.Length == 1) return nums[0]; int[] dp = new int[nums.Length];
dp[0] = nums[0];
dp[1] = Math.Max(dp[0], nums[1]);
for (int i = 2; i < nums.Length; i++)
{
dp[i] = Math.Max(dp[i - 1], dp[i - 2] + nums[i]);
} return dp[nums.Length - 1];
}

打家劫舍II

public int Rob(int[] nums)
{
if (nums == null || nums.Length == 0)
return 0;
int len = nums.Length;
if (len == 1)
return nums[0];
return Math.Max(RobAction(nums, 0, len - 1), RobAction(nums, 1, len));
} int RobAction(int[] nums, int start, int end)
{
int x = 0, y = 0, z = 0;
for (int i = start; i < end; i++)
{
y = z;
z = Math.Max(y, x + nums[i]);
x = y;
}
return z;
}

打家劫舍 III

public int Rob3(TreeNode root)
{
int[] res = RobAction1(root);
return Math.Max(res[0], res[1]);
} int[] RobAction1(TreeNode root)
{
int[] res = new int[2];
if (root == null)
return res; int[] left = RobAction1(root.left);
int[] right = RobAction1(root.right); res[0] = Math.Max(left[0], left[1]) + Math.Max(right[0], right[1]);
res[1] = root.val + left[0] + right[0];
return res;
}

股票问题

子序列问题

单调栈模板

int[] NextGreaterElement(int[] nums)
{
int n = nums.Length;
// 存放答案的数组
int[] res = new int[n];
Stack<int> s = new Stack<int>();
// 倒着往栈里放
for (int i = n - 1; i >= 0; i--)
{
// 判定个子高矮
while (s.Count>0 && s.Peek() <= nums[i])
{
// 矮个起开,反正也被挡着了。。。
s.Pop();
}
// nums[i] 身后的更大元素
res[i] = s.Count>0 ? -1 : s.Peek();
s.Push(nums[i]);
}
return res;
}

图遍历框架

// 记录被遍历过的节点
bool[] visited;
// 记录从起点到当前节点的路径
bool[] onPath; /* 图遍历框架 */
void Traverse(Graph graph, int s)
{
if (visited[s]) return;
// 经过节点 s,标记为已遍历
visited[s] = true;
// 做选择:标记节点 s 在路径上
onPath[s] = true;
for (int neighbor : graph.neighbors(s))
{
bool(graph, neighbor);
}
// 撤销选择:节点 s 离开路径
onPath[s] = false;
}

常用的位运算

几个有趣的位操作

1. 利用或操作 | 和空格将英文字符转换为小写

('a' | ' ') = 'a'
('A' | ' ') = 'a'

2. 利用与操作 & 和下划线将英文字符转换为大写

('b' & '_') = 'B'
('B' & '_') = 'B'

3. 利用异或操作 ^ 和空格进行英文字符大小写互换

('d' ^ ' ') = 'D'
('D' ^ ' ') = 'd'

4. 判断两个数是否异号

int x = -1, y = 2;
bool f = ((x ^ y) < 0); // true int x = 3, y = 2;
bool f = ((x ^ y) < 0); // false

5. 不用临时变量交换两个数

int a = 1, b = 2;
a ^= b;
b ^= a;
a ^= b;
// 现在 a = 2, b = 1

6. 加一

int n = 1;
n = -~n;
// 现在 n = 2

7. 减一

int n = 2;
n = ~-n;
// 现在 n = 1

n & (n-1) 的运用

n & (n-1) 这个操作是算法中常见的,作用是消除数字 n 的二进制表示中的最后一个 1。

1. 计算汉明权重(Hamming Weight)

int HammingWeight(int n) {
int res = 0;
while (n != 0) {
n = n & (n - 1);
res++;
}
return res;
}

2. 判断一个数是不是 2 的指数

//一个数如果是 2 的指数,那么它的二进制表示一定只含有一个 1:
bool IsPowerOfTwo(int n) {
if (n <= 0) return false;
return (n & (n - 1)) == 0;
}

a ^ a = 0的运用

1. 查找只出现一次的元素

int SingleNumber(int[] nums) {
int res = 0;
for (int n : nums) {
res ^= n;
}
return res;
}

求素数模板

//O(N * loglogN)
int CountPrimes(int n)
{
bool[] isPrime = new bool[n];
Array.Fill(isPrime, true);
for (int i = 2; i * i < n; i++)
if (isPrime[i])
for (int j = i * i; j < n; j += i)
isPrime[j] = false; int count = 0;
for (int i = 2; i < n; i++)
if (isPrime[i]) count++; return count;
}

最大公约数,最小公倍数

//获取最大公约数
static int GetLargestCommonDivisor(int n1, int n2)
{
int max = n1 > n2 ? n1 : n2;
int min = n1 < n2 ? n1 : n2;
int remainder;
while (min != 0)
{
remainder = max % min;
max = min;
min = remainder;
}
return max;
} //获取最小公约数
static int GetLeastCommonMutiple(int n1, int n2)
{
return n1 * n2 / GetLargestCommonDivisor(n1, n2);
}

最新文章

  1. TSql 巧用Alt 键
  2. Android 编译使用高版本的Java
  3. VBS学习:流程控制语句判断结构
  4. cocos2dx中加载图片资源的方法,和从内存中获取已经加载的图片资源的方法
  5. Android layout_gravity失效的问题
  6. 线程池读取List&lt;T&gt;实例
  7. 集合ArrayList双色球练一练(自己的方法,太麻烦)
  8. php 内置的 webserver 研究。
  9. Javascript面对对象. 第三篇
  10. Android开发之AChartEngine的使用
  11. Windows多线程学习随笔
  12. Ecelipse上添加Server
  13. Qt5应用改变窗口大小时出现黑影
  14. React文档(十四)深入JSX
  15. Python全栈之路----函数进阶----生成器
  16. SNF快速开发平台MVC-单据状态水印
  17. 如何做实时监控?—— 参考 Spring Boot 实现(转)
  18. flume中HdfsSink参数说明
  19. 1z0-052 q209_10
  20. Effective C++ —— 实现(五)

热门文章

  1. 第五十六篇:webpack的loader(四) -打包js中的高级语法
  2. Linux 破解mysql密码(详细步骤)
  3. rh358 004 bind反向,转发,主从,各种资源记录 unbound ansible部署bind unbound
  4. Ubuntu系统apt添加第三方PPA源
  5. Lua 支持虚函数的解决方案
  6. Java注解系统学习与实战
  7. js之页面列表加载常用方法总结
  8. 如何使用Arthas定位问题
  9. HBuilder X之uniapp最适合的代码补全模板
  10. Linux恢复误删除的文件或者目录