目录

0. 回溯算法模板

leecode上的相关题目:

1. 组合相关

1.1 组合-77题

1.2 电话号码的字母组合-17题

1.3 组合总和-39题

2. 分割相关

2.1 分割回文串-131题

2.2 复原 IP 地址-93题

3. 子集相关

3.1 不含重复整数的集合的子集(78. 子集)

3.2 含重复整数的数组的子集 (90. 子集 II)

3.3 找出所有子集的异或总和再求和

3.4 统计按位或能得到最大值的子集数目


0. 回溯算法模板

void backtracking(参数) {if (终止条件) {存放结果;return;}for (选择:本层集合元素(树中节点孩子的数量就是集合的大小)) {处理节点;backtracking(路径,选择列表); // 递归回溯,撤销处理结果}
}
适用范围:
  • 几乎所有的搜索问题
根据具体题目可能需要改动的地方: 
  • 什么时候输出
  • 哪些情况需要跳过

leecode上的相关题目:

1. 组合相关

1.1 组合-77题

给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。

你可以按 任何顺序 返回答案。

示例 1:

输入:n = 4, k = 2
输出:
[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
]

示例 2:

输入:n = 1, k = 1
输出:[[1]]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/combinations
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

代码:

class Solution {
public:vector<vector<int>> result; //可以定义成成员变量,使函数简洁vector<vector<int>> combine(int n, int k) {int startIndex = 1;vector<int> path;backTracking(n, k, path, startIndex);return result;}void backTracking (int n, int k, vector<int> path, int startIndex) {if (k == path.size()) {  //终止条件:当子集数量到达k个时,就可以收集起来,然后返回了.result.push_back(path);return;}for (int i = startIndex; i <= n; ++i) { // 为什么用for: 如当选择1时,剩余的[2,3,4], 要依次选择一遍.path.push_back(i);  // 为什么是i = startIndex: 如选择2时, 剩余[3,4], 要从3的index开始.这样也避免了重复选择backTracking(n, k, path, i+1); //问题规模缩小一位,path.pop_back();  //回溯:是为了给其他数字机会, 像出栈一样}}
};

优化: i <= n-(k-path.size())+1

1. 已经选择的元素个数:path.size();
2. 还需要的元素个数为: k - path.size();
3. 在集合n中⾄多要从该起始位置 : n - (k - path.size()) + 1,开始遍历
为什么有个+1呢,因为包括起始位置,我们要是⼀个左闭的集合。
举个例⼦,n = 4,k = 3, ⽬前已经选取的元素为0(path.size为0),n - (k - 0) + 1 即 4 - ( 3 - 0) + 1 = 2。2开始搜索都是合理的,可以是组合[2, 3, 4]。
class Solution {
public:vector<vector<int>> result; //可以定义成成员变量,使函数简洁vector<vector<int>> combine(int n, int k) {int startIndex = 1;vector<int> path;backTracking(n, k, path, startIndex);return result;}void backTracking (int n, int k, vector<int> current, int startIndex) {if (k == path.size()) {  //终止条件:当子集数量到达k个时,就可以收集起来,然后返回了.result.push_back(path);return;}for (int i = startIndex; i <= n-(k-path.size())+1; ++i) { // 为什么用for: 如当选择1时,剩余的[2,3,4], 要依次选择一遍.path.push_back(i);  // 为什么是i = startIndex: 如选择2时, 剩余[3,4], 要从3的index开始.这样也避免了重复选择backTracking(n, k, path, i+1); //问题规模缩小一位,path.pop_back();  //回溯:是为了给其他数字机会, 像出栈一样}}
};

1.2 电话号码的字母组合-17题

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

示例 1:

输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]

示例 2:

输入:digits = ""
输出:[]

 代码及解读:

区别于77题在于, 这里深度遍历的对象虽然仍然是字符的长度,但宽度遍历的对象则是每个数字对应的字符(如2对应的"abc")

class Solution {
public:vector<string> res;string path;//疑问:定义成 unordered_map<int, string> 取值使用 phoneMap.at(digits[pos])不通过??? whyunordered_map<char, string> phoneMap = { {'2', "abc"},{'3', "def"},{'4', "ghi"},{'5', "jkl"},{'6', "mno"},{'7', "pqrs"},{'8', "tuv"},{'9', "wxyz"}};vector<string> letterCombinations(string digits) {backTracking(digits, 0);return res;}void backTracking(const string & digits, int pos) {if(pos == digits.length()) {res.push_back(path);return;}string str = phoneMap.at(digits[pos]); //注意:这里取map中对应的值for (int i = 0; i < str.length(); ++i) {//注意:这里遍历的宽度是每个数字对应的字符数量,如"pqrs"是4path.push_back(str[i]);backTracking(digits, pos+1); //常规操作: 这里遍历的深度是digits的长度,如[2,3,4],深度是3,对应pos+1path.pop_back();}}
};

1.3 组合总和-39题

给定一个无重复元素的正整数数组 candidates 和一个正整数 target ,找出 candidates 中所有可以使数字和为目标数 target 的唯一组合。

candidates 中的数字可以无限制重复被选取。如果至少一个所选数字数量不同,则两种组合是唯一的。

对于给定的输入,保证和为 target 的唯一组合数少于 150 个。

示例 1:

输入: candidates = [2,3,6,7], target = 7
输出: [[7],[2,2,3]]

示例 2:

输入: candidates = [2,3,5], target = 8
输出: [[2,2,2,2],[2,3,3],[3,5]]

代码:

区别与77题, 可以重复选择元素(意味着树的层数没有限制), 所以递归时, 在for循环中, 传入当前index即可,使用for循环自然地遍历到下一个节点.

图示如下:

class Solution {
public:vector<vector<int>> res;vector<vector<int>> combinationSum(vector<int>& candidates, int target) {vector<int> path;backTracking(candidates, target, path, 0);return res;}void backTracking(vector<int>& candidates, int target, vector<int> path, int pos) {if (target == 0) {res.push_back(path);return;}if(target < 0 || pos == candidates.size()) { //注意:这里的返回条件勿少! //无pos==..也可测试通过, 有第二个条件有所过滤,加速了些return;}for (int i = pos; i < candidates.size(); i++) {path.push_back(candidates[i]);backTracking(candidates, target-candidates[i], path, i); //注意:这里递归可选择重复元素,所以传入的是i.path.pop_back();}}
};

 优化:

若当前的和已经大于target时,那么对于排序的数组,选择后面的值加入,肯定更加大于target,所以,可以使用先排序candidates,然后剪枝的方法进行优化.

class Solution {
public:vector<vector<int>> res;vector<vector<int>> combinationSum(vector<int>& candidates, int target) {vector<int> path;sort(candidates.begin(), candidates.end()); //优化:先从小到大排序backTracking(candidates, target, path, 0);return res;}void backTracking(vector<int>& candidates, int target, vector<int> path, int pos) {if (target == 0) {res.push_back(path);return;}if(target < 0 || pos == candidates.size()) {return;}for (int i = pos; i < candidates.size(); i++) {if (target-candidates[i] < 0) { //选择当前值加入都大于目标值,对于排序候选数组,则后面的值就不用加入了.return; //这里等价于break}path.push_back(candidates[i]);backTracking(candidates, target-candidates[i], path, i);path.pop_back();}}
};

2. 分割相关

2.1 分割回文串-131题

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。

回文串 是正着读和反着读都一样的字符串。

示例 1:

输入:s = "aab"
输出:[["a","a","b"],["aa","b"]]

示例 2:

输入:s = "a"
输出:[["a"]]

代码:

class Solution {
public:vector<vector<string>> res;vector<vector<string>> partition(string s) {vector<string> path;backTracking(s, path, 0);return res;}void backTracking(const string &s, vector<string> path, int pos) {if (pos == s.length()) {res.push_back(path);return;}for(int i = pos; i < s.length(); ++i) {string currentStr = s.substr(pos, i-pos+1); //注意:[pos, i]之间就是分割的子串if(!isPalindrome(currentStr)) { //注意: 不是回文子串,直接跳出该子树continue; //注意:这里不是return或者break(break此处等价于return, 跳过了后面所有分支,此处是不合理的), 因为对于aba, ab不是回文,continue过滤掉本分支中其他分割即可,但是下一个分支中aba是回文}path.push_back(currentStr);backTracking(s, path, i+1);path.pop_back();}}bool isPalindrome (const string &s) {if (s.empty()) return false;int start = 0;int end = s.length()-1;for (int i = start, j = end; i < j; ++i, --j) {if (s[start] != s[end])return false;}return true;}
};

图示:

2.2 复原 IP 地址-93题

给定一个只包含数字的字符串,用以表示一个 IP 地址,返回所有可能从 s 获得的 有效 IP 地址 。你可以按任何顺序返回答案。

有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。

例如:"0.1.2.201" 和 "192.168.1.1" 是 有效 IP 地址,但是 "0.011.255.245"、"192.168.1.312" 和 "192.168@1.1" 是 无效 IP 地址。

示例 1:

输入:s = "25525511135"
输出:["255.255.11.135","255.255.111.35"]

示例 2:

输入:s = "0000"
输出:["0.0.0.0"]

代码及解读:

本题于上题分割回文串很类似, 都属于分割问题, 区别于上题的点在于分割的字符串的有效性的判断,以及分割段数是有限制的(只有4段, 意味着深度遍历只需要4层). 其他的还是上述模板.

class Solution {
public:vector<string> res;vector<string> path;vector<string> restoreIpAddresses(string s) {int segNum = 0;backTracking(s, 0, 0);return res;}void backTracking(string s, int pos, int segNum) {if (pos == s.length() && segNum == 4) { //注意: 返回条件, 多了一个segment numuberres.push_back(vector2string(path));return;}for(int i = pos; i < s.length(); ++i) {if(segNum == 4) { //加速措施: 只深度遍历4层即可 //该if不加也能得到正确结果string seg4 = s.substr(pos,s.length()-pos); //注意: 到第4段时,直接取剩下所有的数字,看是否满足有效性if (!isValid(seg4)) {return;}}else{string seg = s.substr(pos, i-pos+1);if (!isValid(seg)) {return; //注意:这里不是contiue, 即该分支无效,在后面再加一位数字更加无效,所有,跳过后面所有的分支, 如 2561111, 256无效, 其后面的分支, 如2561更加无效.}path.push_back(seg);backTracking(s, i+1, segNum+1);path.pop_back();}}}bool isValid(const string &s) {if (s.empty())return false;int num = atoi(s.c_str()); //这里默认为输入的字符串是可以被分割成有效的ip的,不含@这样的特殊字符if (s[0] == '0') { //注意:分两种情况: 第一位是0还是非0if(s.size() == 1)return true;else    return false;}else{if( num >=0 && num <=255) {return true;}elsereturn false;}}// 拼出一个正确的(含.的)ip出来string vector2string(vector<string> path) {if (path.size() == 0) return string("");string ipStr("");for (int i = 0; i < path.size(); ++i) {ipStr += path[i];if (i < path.size()-1) {ipStr += ".";}}return ipStr;}
};

其他解法: 参考「代码随想录」带你学透回溯算法!93. 复原 IP 地址

3. 子集相关

3.1 不含重复整数的集合的子集(78. 子集)

给定一个含不同整数的集合,返回其所有的子集。

示例 1:

输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

示例 2:

输入:nums = [0]
输出:[[],[0]]代码及解读

class Solution {
public:// 面试点: 中等题, 看候选人是否会使用递归解决问题// 知识点关键词: 深度优先遍历, 回溯vector<vector<int>> subsets(vector<int> &nums) {vector<vector<int>> results;vector<int> curNums;sort(nums.begin(), nums.end()); //注意: 也可以不sortsubSetsCore(results, nums, curNums, 0);return results;}void subSetsCore(vector<vector<int>> & results, const vector<int> &nums, //注意results和curNums是引用传递vector<int> &curNums, int pos) {results.push_back(curNums);                     //注意:这里空的也算子集的一部分for (int i=pos; i<nums.size(); ++i) {           //特别注意: 搜索开始的位置 i=poscurNums.push_back(nums[i]);                 // => 相当于放入[1,]subSetsCore(results, nums, curNums, i+1);   //注意 i+1 // => 相当于放入[1,2],[1,3]curNums.pop_back();                         // => 回溯,从树根向上遍历删除}}
};

本题还有一种方法:对于nums中的每一位,都有两种可能,选择 或者 不选择。所以就采用二进制的方法。设 总共有 n 个数字,则 总共就有 2^n 种可能(1 << n)。对于每一种可能i, 其二进制对应的位置为1时,我们认为当前要选择,否则认为当前不选择。因此代码如下。特别注意这里的判断条件 和 运算符优先级:if ( (i & (1 << j)) != 0 )  。

class Solution {
public:vector<vector<int>> subsets(vector<int> &nums) {vector<vector<int>> results;int n = nums.size();if (n == 0) { // 可能省略return results;}for (int i = 0; i < (1 << n); i++) { // 总共有 2^n种可能(n个数, 每个数有两种可能,选择or不选择)//注意是 1<<nvector<int> result;for (int j = 0; j < n; j++) {if ( (i & (1 << j)) != 0) { //依次遍历nums中的3个数, 选择 i 中 二进制中为1的位数,对应的数字,比如 i=0(001) 选择 nums[0]; i=3(011), 选择 nums[0] 和nums[1] //注意 运算符优先级 不等于!= 要优先与 按位与&,要加括号!result.push_back(nums[j]);}}results.push_back(result);}return results;    }
};

3.2 含重复整数的数组的子集 (90. 子集 II)

和上面的代码基本一致, 只需要添加一句代码: 在判断重复添加到数组时跳过即可.

描述: 给定一个可能具有重复数字的列表,返回其所有可能的子集。

示例 1:

输入:nums = [1,2,2]
输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]

示例 2:

输入:nums = [0]
输出:[[],[0]]代码及解读

代码

注意重复数字的过滤条件:if ( i != pos && nums[i] == nums[i-1] ) ,不要写错了。当前循环索引不是第一个,且当前数字等于前一个时,就跳过。

class Solution {
public:// 面试点: 中等题, 看候选人是否会使用递归解决问题// 知识点关键词: 深度优先遍历, 回溯vector<vector<int>> subsetsWithDup(vector<int> &nums) {vector<vector<int>> results;vector<int> curNums;sort(nums.begin(), nums.end()); //注意: 这里需要sortsubsetsWithDupCore(results, nums, curNums, 0);return results;}void subsetsWithDupCore(vector<vector<int>> & results, const vector<int> &nums, //注意results和curNums是引用传递vector<int> &curNums, int pos) {results.push_back(curNums);                     //注意:这里空的也算子集的一部分for (int i=pos; i<nums.size(); ++i) {           //特别注意: 搜索开始的位置 i=posif (i!=pos && nums[i]==nums[i-1]) {         //特殊处理部分: 跳过重复的数字,不添加到候选子集中continue;}curNums.push_back(nums[i]);                 // => 相当于放入[1,]subsetsWithDupCore(results, nums, curNums, i+1);   //注意 i+1 // => 相当于放入[1,2],[1,3]curNums.pop_back();                         // => 回溯,从树根向上遍历删除}}
};

3.3 找出所有子集的异或总和再求和

描述:

一个数组的 异或总和 定义为数组中所有元素按位 XOR 的结果;如果数组为 空 ,则异或总和为 0 。

例如,数组 [2,5,6] 的 异或总和 为 2 XOR 5 XOR 6 = 1 。
给你一个数组 nums ,请你求出 nums 中每个 子集 的 异或总和 ,计算并返回这些值相加之 和 。

注意:在本题中,元素 相同 的不同子集应 多次 计数。

数组 a 是数组 b 的一个 子集 的前提条件是:从 b 删除几个(也可能不删除)元素能够得到 a 。

示例 1:

输入:nums = [1,3]
输出:6
解释:[1,3] 共有 4 个子集:
- 空子集的异或总和是 0 。
- [1] 的异或总和为 1 。
- [3] 的异或总和为 3 。
- [1,3] 的异或总和为 1 XOR 3 = 2 。
0 + 1 + 3 + 2 = 6

示例 2:

输入:nums = [5,1,6]
输出:28
解释:[5,1,6] 共有 8 个子集:
- 空子集的异或总和是 0 。
- [5] 的异或总和为 5 。
- [1] 的异或总和为 1 。
- [6] 的异或总和为 6 。
- [5,1] 的异或总和为 5 XOR 1 = 4 。
- [5,6] 的异或总和为 5 XOR 6 = 3 。
- [1,6] 的异或总和为 1 XOR 6 = 7 。
- [5,1,6] 的异或总和为 5 XOR 1 XOR 6 = 2 。
0 + 5 + 1 + 6 + 4 + 3 + 7 + 2 = 28

代码及解读:

参考:力扣

class Solution {
public:int subsetXORSum(vector<int>& nums) { // 比如 nums=[5,1,3]int result = 0;// 方式1: ok// for (int i=0; i<nums.size(); ++i) {         //注意: for循环在递归外,首先加入第1位元素是:[5,...] [1,...] [3,...]//     subsetXORSumCore(result, nums, nums[i], i+1); //注意: 这里第3个参数, 第4个参数,从第2位(i+1)开始// }// 方式2: oksubsetXORSumCore(result, nums, 0, 0);return result;}//pos表示当前要取的nums中的元素的索引void subsetXORSumCore(int &result, const vector<int> &nums, int curResult, int pos) { if (pos==nums.size()) {             //做处理,输出result += curResult;}else {subsetXORSumCore(result, nums, curResult^nums[pos], pos+1); //添加一个元素, 比如 [5,1,3]进行异或subsetXORSumCore(result, nums, curResult, pos+1);           //略过一个元素, 这里 [5,1]进行异或}}
};

图示:

3.4 统计按位或能得到最大值的子集数目

给你一个整数数组 nums ,请你找出 nums 子集 按位或 可能得到的 最大值 ,并返回按位或能得到最大值的 不同非空子集的数目 。

如果数组 a 可以由数组 b 删除一些元素(或不删除)得到,则认为数组 a 是数组 b 的一个 子集 。如果选中的元素下标位置不一样,则认为两个子集 不同 。

对数组 a 执行 按位或 ,结果等于 a[0] OR a[1] OR ... OR a[a.length - 1](下标从 0 开始)。

示例 1:

输入:nums = [3,1]
输出:2
解释:子集按位或能得到的最大值是 3 。有 2 个子集按位或可以得到 3 :
- [3]
- [3,1]

示例 2:

输入:nums = [2,2,2]
输出:7
解释:[2,2,2] 的所有非空子集的按位或都可以得到 2 。总共有 23 - 1 = 7 个子集。

示例 3:

输入:nums = [3,2,1,5]
输出:6
解释:子集按位或可能的最大值是 7 。有 6 个子集按位或可以得到 7 :
- [3,5]
- [3,1,5]
- [3,2,5]
- [3,2,1,5]
- [2,5]
- [2,1,5]

代码及解读:

class Solution {
public:int count;int max;int countMaxOrSubsets(vector<int>& nums) {count = 0;max = 0;for (int i = 0; i<nums.size(); ++i) {max |= nums[i]; //注意1:一个数组子集中按位或的最大值,等于所有元素的按位或的结果!}int curResult = 0;countMaxOrSubsetsCore(nums, curResult, 0, false); //注意4: 默认chosed状态return count;}void countMaxOrSubsetsCore(const vector<int>& nums, int curResult,int pos, bool chosed) {if (curResult == max && chosed) { // 注意2: 统计条件:因为当前轮未选中当前元素的状态,等于上一次选中上一个元素的状态,++count;                     // 所以只统计选中状态时的子集是否满足条件!}if (pos == nums.size()) {  //注意3: 返回条件!return;}countMaxOrSubsetsCore(nums, curResult | nums[pos], pos + 1, true); //选中状态才进行按位或countMaxOrSubsetsCore(nums, curResult, pos + 1, false);}
};

图示:

算法笔记_面试题_15.回溯算法模板及示例相关推荐

  1. 【算法笔记】极客时间 算法面试通关40讲 笔记  覃超

    [算法笔记]极客时间 算法面试通关40讲 覃超 [算法笔记]极客时间 算法面试通关40讲 覃超 相关链接 在leetcode 上的题号 数组.链表: (堆)栈stack.队列queue 优先队列 哈希 ...

  2. >算法笔记-动态规划-最短路径迪杰斯特拉算法

    算法笔记-动态规划-最短路径迪杰斯特拉算法 作者:星河滚烫兮 前言   图的最短路径问题在现实生活中有很广阔的应用,最短路径又分为单源最短路径与多源最短路径,前者求出固定起点到其他节点的最短路径,后者 ...

  3. 【算法设计技巧】贪婪算法与回溯算法

    贪婪算法 在前面的文章中已经见到了3个贪婪算法(greedy algorithm):Dijkstra 算法.Prim 算法和 Kruskal 算法.贪婪算法分阶段地工作.在每个阶段,可以认为所作决定是 ...

  4. 跑胡子胡牌算法(带赖子、基于回溯算法)

    跑胡子规则 跑胡子,小写"一"到"十"各4张共40张,大写"壹"到"拾"各4张共40张. 砌牌:跑胡子为3人同玩,庄家砌 ...

  5. 回溯 皇后 算法笔记_回溯算法:N皇后问题

    给「代码随想录」一个星标吧! ❝ 通知:我将公众号文章和学习相关的资料整理到了Github :https://github.com/youngyangyang04/leetcode-master,方便 ...

  6. 回溯 皇后 算法笔记_什么叫回溯算法,一看就会,一写就废

    什么叫回溯算法 对于回溯算法的定义,百度百科上是这样描述的:回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就"回溯"返回, ...

  7. 高效 遍历 算法_一文学会回溯算法解题技巧

    (给算法爱好者加星标,修炼编程内功) 来源:码海 前言 上文我们学习了深度优先搜索和广度优先搜索,相信大家对这两者的算法有了比较清楚的认识,值得一提的,深度优先算法用到了回溯的算法思想,这个算法虽然相 ...

  8. 算法笔记(0002) - 【贪心算法】活动安排问题

    贪心算法 原理 在对问题求解时,总是做出在当前看来是最好的选择.也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解.贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许 ...

  9. 算法笔记(11)逻辑回归算法及Python代码实现

    逻辑回归算法是一种被广泛使用的分类算法,通过训练数据中的正负样本,学习样本特征到样本标签之间的假设函数.逻辑回归假设因变量 y 服从伯努利分布,而线性回归假设因变量 y 服从高斯分布. 因此与线性回归 ...

  10. 算法学习(九):回溯算法

    目录 一.leetcode 17. 电话号码的字母组合 二.剑指offer 64.矩阵中的路径 三.剑指offer 65.机器人的运动范围 一.基本概念 一个函数在进行递归调用时,总是从一个入口进去, ...

最新文章

  1. Linux下task_struct详解
  2. python 1 2 3怎么拼接所有可能的数_6000字长文,带你用Python完成 “Excel合并(拆分)” 的各种操作!...
  3. 【动态规划】城市交通
  4. 从static变量导出问题解析 __declspec(dllexport) 和 __declspec(dllimport)的作用
  5. mysql死锁无法查询_MySQL死锁导致无法查询
  6. gateway网关_SpringCloud技术指南系列(十二)API网关之Gateway使用
  7. PHP实现调用淘宝SDK开放接口返回天猫或淘宝商品详情
  8. Spark之RDD实战篇3
  9. linux ubuntu 安装odb,玩玩Linux云主机-Ubuntu安装nginx
  10. 在线翻译_英汉互译,支持繁体,韩语,日语 - 微信小程序在线翻译,单词句子翻译
  11. 已知鸡兔共35只c语言,行测数量关系技巧:巧解鸡兔同笼问题
  12. 使用htps进行,Get请求和post请求
  13. 用arduinoUNO做温度计
  14. m180n 如何设置网络打印_不难!简单几步教你搞定网络打印机添加设置
  15. 《SEM长尾搜索营销策略解密》一一1.4 潜藏在海平线下的长尾世界
  16. pvr.ccz 与 png 格式 互转的解决方案
  17. win10、win7 脚本导证书到系统中
  18. 【树莓派】系统刷机教程
  19. libuv 原理_理解libuv的基本原理
  20. pythonk库函数minidom,wx

热门文章

  1. 绝对定位元素、浮动元素会生成一个块级框
  2. 软件测试基本功 系列教程
  3. 几种常用 css3 选择器解释
  4. git 合并指定目录到master
  5. session用户账号认证(一个用户登陆,踢出前一个用户)
  6. lua-获取当前时间
  7. orcad中的PSpice仿真加入厂商模型
  8. 网页编辑器粘贴word格式的处理
  9. An Add-in Bookmark for visual studio 2005
  10. 对FreeMarker技术的思考