文章目录

  • 分治模板
  • [50.Pow(x, n) ](https://leetcode-cn.com/problems/powx-n/)
  • [169. 多数元素](https://leetcode-cn.com/problems/majority-element/)
  • 78.子集
  • 17.电话号码的字母组合
  • 51.N皇后
  • 参考

方法论:

  1. 看题五分钟,不会做,看解析;
  2. 先看中文站,再看国际站;
  3. 选择最优解析;
  4. 回头再来写

面试四步走:

  1. 和面试官,探讨题目限制条件;
  2. 说说可能解,选择最优解;
  3. 码字;
  4. 跑测试用例

分治模板

C/C++
int divide_conquer(Problem *problem, int params) {// recursion terminatorif (problem == nullptr) {process_resultreturn return_result;} // process current problemsubproblems = split_problem(problem, data)subresult1 = divide_conquer(subproblem[0], p1)subresult2 = divide_conquer(subproblem[1], p1)subresult3 = divide_conquer(subproblem[2], p1)...// mergeresult = process_result(subresult1, subresult2, subresult3)// revert the current level statusreturn 0;
}

50.Pow(x, n)

题目:实现 pow(x, n) ,即计算 x 的 n 次幂函数。

可能解:

  1. O(n)暴力解
  2. O(longn)快速幂+递归
# 1.暴力解,会超出时间限制
class Solution {
public:double myPow(double x, int n) {double  res = 1;long long N = n;if (N < 0) {N = -N;x = 1/x;}for (long long i = 0; i < N; i++){res *= x;}return res;}
};
# 2. 快速幂+递归
class Solution {
public:double myPow(double x, int n) {long long N = n;if (N < 0) {N = -N;x = 1/x;}return fastPow(x, N);}private: double fastPow(double x, long long n) {// terminatorif (n == 0) return 1.0;// process current logic + drill downdouble half = fastPow(x, n/2);// restore current logic return n % 2 == 0 ? half * half : half * half * x;
}
};

169. 多数元素

题目:给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

可能解:

  1. 因为给定数组总存在多数元素,因此,可以将数组排序,然后num.size() / 2一定是多数元素;
  2. 利用hashmap记录元素个数;
  3. 随机选取数组中的值,如果该值个数超过一半,那么就是所求值;
  4. 利用分治求解;
  5. 利用Moore 投票;
# 2 hashmap求解
class Solution {
public:int majorityElement(vector<int>& nums) {unordered_map<int, int> umap;for (int num : nums){umap[num]++;if (umap[num] > nums.size() / 2)    return num;}return -1;}
};
# 3. 随机求解
class Solution {
public:int majorityElement(vector<int>& nums) {while(1){int candidate = nums[rand() % nums.size()];int count = 0;for (int num : nums){if (num == candidate)++count;}if (count > nums.size() / 2)    return candidate;}}
};
# 4.利用分治求解
class Solution {
public:int majorityElement(vector<int>& nums) {return helper(nums, 0, nums.size() - 1);}private:int helper(vector<int>& nums, int left, int right){// helper(nums, l, r),返回[l, r]中出现最多的数// terminatorif (left == right)  return nums[left];// process current problemint mid = left + ((right - left) >> 1);int lm = helper(nums, left, mid);int rm = helper(nums, mid + 1, right);// merge and revert current statusif (lm == rm)   return lm;return count(nums.begin() + left, nums.begin() + mid + 1, lm) > count(nums.begin() + mid + 1, nums.begin() + right + 1, rm) ? lm : rm;}
};
# Moore投票
class Solution {
public:int majorityElement(vector<int>& nums) {int count = 0;int major = -1;for (auto c : nums){if (count == 0){major = c;}count += (major == c) ? 1 : -1;}return major;}
};

78.子集

给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

**说明:**解集不能包含重复的子集。

思路:子集的另一种解法,在这里有中新解法,给定数组nums,对于其中的每个元素,我们可以通过选或者不选的形式来写递归;

class Solution {void generateSub(const vector<int>& nums, vector<vector<int>>& res, vector<int>& path, int start){// terminatorif (start == nums.size())   {res.push_back(path);return;}// not pick up the number at this index generateSub(nums, res, path, start+1 );// pick the number at this indexpath.push_back(nums[start]);generateSub(nums, res, path, start+1 );path.pop_back();}
public:vector<vector<int>> subsets(vector<int>& nums) {vector<vector<int>> res;vector<int> path; generateSub(nums, res, path, 0);return res;}
};

17.电话号码的字母组合

题目:给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。

可能解:

  1. 回溯解法:递归树中,每个节点可能的选择,就是手机数字上面的3或4个可选字母;
  2. 队列求解;17.电话号码字母组合,队列图解 My Java solution with FIFO queue
# 解法1
class Solution {
private:const string letterMap[10] = {"", //0"", //1"abc",  // 2"def",  //3"ghi",  //4"jkl",  //5"mno",  //6"pqrs", //7"tuv",  //8"wxyz"  //9};// 变化的是index, 和选路void findCombination(const string& digits, vector<string>& res, string& s, int start){if (start == digits.size()){res.push_back(s);return;}char c = digits[start];string letters = letterMap[c - '0'];// 选择列表for (int i = 0; i < letters.size(); i++){// 做选择s = s + letters[i];findCombination(digits, res, s, start+1);s.erase(s.end() -1);}return;}
public:vector<string> letterCombinations(string digits) {vector<string> res;if (digits == "")return res;string s = "";findCombination(digits, res, s, 0);return res;    }
};
# 解法2
class Solution {
private:const string letterMap[10] = {"", //0"", //1"abc",  // 2"def",  //3"ghi",  //4"jkl",  //5"mno",  //6"pqrs", //7"tuv",  //8"wxyz"  //9};// 变化的是index, 和选路void findCombination(const string& digits, vector<string>& res, string& s, int start){if (start == digits.size()){res.push_back(s);return;}char c = digits[start];string letters = letterMap[c - '0'];// 选择列表for (int i = 0; i < letters.size(); i++){// 做选择s = s + letters[i];findCombination(digits, res, s, start+1);s.erase(s.end() -1);}return;}
public:vector<string> letterCombinations(string digits) {deque<string> dq;if (digits.size() == 0) return {};dq.push_back("");for (int i = 0; i < digits.size(); i++) {string letters = letterMap[digits[i] - '0'];while (dq.front().size() == i) {string tmp = dq.front();dq.pop_front();for (char s : letters){dq.push_back(tmp + s);}}}vector<string> res(dq.begin(), dq.end());return res;}
};

51.N皇后

题目:n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

思路:

  1. 定义columns集合,判断当前列是否摆放皇后;
  2. 定义dia1集合,判断对角1是否有皇后,定义的规则是 横坐标 - 纵坐标 是否相等;
  3. 定义dia2集合,判断对角线2是否有皇后,定义规则是 横坐标 + 纵坐标是否相等;
  4. 其他就是回溯套路:遍历当前节点的可选项,判断是否符合要求,符合就进入下一层,不符合就continue
# 更加偏向于下面代码
class Solution {private:void putQueen(vector<vector<string>>& res, vector<int>& queen, int n, int start, unordered_set<int> columns, unordered_set<int> dia1, unordered_set<int> dia2){if (start == n){res.push_back( generateBoard(n, queen));return;}for(int i = 0; i < n ; i++){if (columns.find(i) != columns.end() || dia1.find(start - i) != dia1.end() || dia2.find(start + i) != dia2.end()){continue;}queen.push_back(i);columns.insert(i);dia1.insert(start - i);dia2.insert(start + i);putQueen(res, queen, n, start + 1, columns, dia1, dia2);columns.erase(i);dia1.erase(start - i);dia2.erase(start + i);queen.pop_back();}}vector<string> generateBoard(int n, vector<int>& queen){vector<string> board( n, string(n, '.'));for (int i = 0; i < n; i++){board[i][queen[i]] = 'Q';}return board;}
public:vector<vector<string>> solveNQueens(int n) {vector<vector<string>> res;unordered_set<int> columns;unordered_set<int> dia1;unordered_set<int> dia2; vector<int> queen;putQueen(res, queen, n, 0, columns, dia1, dia2);return res;}
};

参考

  1. 极客时间-算法训练营-覃超
  2. C++ 6 Solutions for majority-element
  3. 17.电话号码字母组合,队列图解
  4. leetcode中文站
  5. leetcode国际站 (将力扣中文链接,后面的-cn去掉,就是该题的国际站)

面试算法———回溯经典题目相关推荐

  1. 面经——嵌入式软件工程师面试遇到的经典题目

    参考:嵌入式软件工程师面试遇到的经典题目 作者:一只青木呀 发布时间: 2020-11-04 23:43:16 网址:https://blog.csdn.net/weixin_45309916/art ...

  2. Java实现搜索回溯经典题目

    文章目录 前言 搜索框架 经典问题 前言 搜索与回溯是计算机解题中常用的算法,很多问题无法根据某种确定的计算法则来求解,可以利用搜索与回溯的技术求解.回溯是搜索算法中的一种控制策略.它的基本思想是:为 ...

  3. 【九章算法】经典题目

    九章算法面试题42 构造MaxTree 增长序列: 从左到右扫描和从右到左,分别记录每个节点左边第一个比自己大的元素,右边第一个..(使用栈,小于自己的弹出) O(n). 然后把左右之间较小的那个元素 ...

  4. 华为od一面面试算法

    华为od一面面试算法 在看题目之前,谈谈对于面试时手撸算法的看法,如果在面试之前刷了几百+的leetcode,那么只要好好总结一下,我觉得面试的算法是完全可以做出来的:但是如果没有刷到那么多,我们怎么 ...

  5. Leetcode回溯算法经典题目总结

    回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就 "回溯" 返回,尝试别的路径.回溯法是一种选优搜索法,按选优条件向前搜索 ...

  6. 链表python笔试题目_python经典面试算法题1.4:如何对链表进行重新排序

    本题目摘自<Python程序员面试算法宝典>,我会每天做一道这本书上的题目,并分享出来,统一放在我博客内,收集在一个分类中. 1.4 对链表按照如下要求重新排序 [微软笔试题] 难度系数: ...

  7. 递归和回溯相关面试算法总结

    文章目录 递归面试算法总结 1. LeetCode 剑指 Offer 07 : 重建二叉树 2. LeetCode 687 : 最长同值路径 3. LeetCode 面试题 08.06 : 汉诺塔问题 ...

  8. 算法提高:贪心策略的11个经典题目

    目录 字典序最小 零钱问题 股票问题(最多持有一支,可以买卖无限次) 小船过河 任务调度器 摆动序列 最小区间 跳跃游戏 II 分糖果 通配符匹配 拼接最大数 字典序最小 题目 给定一个由字符串组成的 ...

  9. python判断数组中是否有重复元素_python经典面试算法题4.1:如何找出数组中唯一的重复元素...

    本题目摘自<Python程序员面试算法宝典>,我会每天做一道这本书上的题目,并分享出来,统一放在我博客内,收集在一个分类中. [百度面试题] 难度系数:⭐⭐⭐ 考察频率:⭐⭐⭐⭐ 题目描述 ...

最新文章

  1. 98后常春藤学霸林之秋,一作拿下CVPR最佳论文提名,首次挑战图片翻转不变性假设...
  2. Java NIO学习系列六:Java中的IO模型
  3. python循环五角星做法_python实现while循环打印星星的四种形状
  4. 原生html小游戏,原生JS实现别踩白块小游戏(一)
  5. Elastic-Job功能特性
  6. Spring Boot 多数据源(读写分离)入门
  7. Linux共享文件夹中毒,linux服务器中毒利用Find查找病毒例子
  8. 数据库流行度8月排行榜:Oracle 飙升 和 PostgreSQL 绝尘领跑第二梯队
  9. Linux下WebLogic 12c启动、部署命令行
  10. 苹果Mac批量图像格式转换软件:XnConvert
  11. 高通9008刷机大法,避坑指南,救砖前提
  12. lammps学习总结3
  13. 0x0000000指令引用”0x0000000”内存,该内存不能为written
  14. 土是独体字结构吗_独体结构的字大全
  15. 房屋租赁合同主要内容是那些
  16. CLR via C#:与WinRT组件互操作
  17. 雷军:同事格式化了我的电脑,让我走上当CEO的“不归路”
  18. asdfasdfsd阿萨德发撒的发撒的发撒的发
  19. 写给前端初学者的Vue入门教程
  20. 话说“软件测试”都是吃青春饭,可是为什么仍有那么多人转行做“软件测试”呢?

热门文章

  1. Android Menu菜单栏
  2. amd、cmd、esmodule、commonjs区别
  3. Android--CardView详解
  4. matlab中函数imresize的使用介绍
  5. RxJava之过滤操作符
  6. 带问题重读ijkPlayer
  7. JS判断用户输入是否为素数
  8. 图神经网络系列(二)图卷积神经网络
  9. NAND、NOR、FLASH、Memory
  10. Mysql登录报错:Can‘t connect to MySQL server on ‘localhost:3306‘ (10061)