【算法设计作业】week14
来源:互联网 发布:美团大数据招聘 编辑:程序博客网 时间:2024/05/16 01:34
【算法设计作业】week14
给出了第33、34,35、36、38、39、41、45题的解析
33. Search in Rotated Sorted Array
题目来源:https://leetcode.com/problems/search-in-rotated-sorted-array/description/
题意
给出一个初始升序序列,经过一个(注:一个)“rotation”之后的序列。例如0 1 2 4 5 6 7
经过一次”rotation”可以变成4 5 6 7 0 1 2
。
要求在这个rotation过的序列中寻找给定元素target的index。
思路
经过rotation后,必定只有一半是升序的,而另一半是降序的。判断出要哪一半后,就可以对这一半进行二分搜索。
参考代码
http://www.cnblogs.com/grandyang/p/4325648.html
34. Search for a Range
题目来源https://leetcode.com/problems/search-for-a-range/description/
题意
给出一个有序数列,求出给定target的范围,用左闭右闭区间表示。如果不存在,则返回[-1, -1]
。
思路
实现两个函数,分别是upper_bound
求上界,lower_bound
求下界,调用这两个函数,即得出结果。
1.lower_bound
首先看int lower_bound(vector<int>& nums, int x, int y, int v)
,在这个函数中,nums
是有序数列,搜索范围是[x, y)
(注!左闭右开区间!但返回区间是左闭右闭区间,因为可能返回最后一个元素的后一个位置,这就是待插入位置),v
是所求的搜索目标。
这个函数是这样的:
int lower_bound(vector<int>& nums, int x, int y, int v) { int m; while(x < y) { m = x + (y - x) / 2; if(nums[m] >= v) y = m; else x = m + 1; } return x; }
我们用二分搜索的思想,首先求出x
和y
的中值,m
。
记住我们此时求的是下界,并且搜索区间是左闭右开的,返回区间是左闭右闭的,然后有下面这三种情况:
nums[m]=v
至少已经找到一个了,左边可能还有,因而区间变为[x,m]
nums[m]>v
,所求位置不可能在m
后面,但有可能在m上,区间变为[x,m]
nums[m]<v
,m
和前面的都不可行,区间变为[m+1, y]
而头两种情况可以合并。
2.upper_bound
与lower_bound
原理类似。
参考代码
class Solution {public: vector<int> searchRange(vector<int>& nums, int target) { vector<int> ans; int low = lower_bound(nums, 0, nums.size(), target); int high = upper_bound(nums, 0, nums.size(), target)-1; if (low > high) { ans.push_back(-1); ans.push_back(-1); } else { ans.push_back(low); ans.push_back(high); } return ans; } int lower_bound(vector<int>& nums, int x, int y, int v) { int m; while(x < y) { m = x + (y - x) / 2; if(nums[m] >= v) y = m; else x = m + 1; } return x; } int upper_bound(vector<int>& nums, int x, int y, int v) { int m; while(x < y) { m = x + (y - x) / 2; if(nums[m] <= v) x = m+1; else y = m; } return x; }};
35. Search Insert Position
来源:https://leetcode.com/problems/search-insert-position/description/
题意
给出一个序列,返回target的位置。如果不存在,则返回target应插入的位置。
思路
和第34题的upper_bound一摸一样
参考代码
class Solution {public: int searchInsert(vector<int>& nums, int target) { int x = 0, y = nums.size(); int m; while(x < y){ m = x + (y-x)/2; if(nums[m] >= target) y = m; else x = m + 1; } return x; }};
36. Valid Sudoku
来源https://leetcode.com/problems/valid-sudoku/description/
题意
给出一个部分的数独,问已经填的数字是否符合数独规则。
思路
很简单,只要分别判断每一行,每一列,每个九宫格是否出现重复数字即可。
参考代码
class Solution {public: bool isValidSudoku(vector<vector<char>>& board) { for(int i = 0; i < 9; i++) { if (!(isColValid(board, i) && isRowValid(board, i) && isSquareValid(board, i/3, i%3))) { return false; } } return true; } bool isColValid(vector<vector<char>>& board, int col) { bool seen[10]; for(int i = 0; i < 10; i++) seen[i] = false; for(int i = 0; i < 9; i++) { if(board[i][col] != '.') { int num = board[i][col] - '0'; if(seen[num] == false) { seen[num] = true; } else { return false; } } } return true; } bool isRowValid(vector<vector<char>>& board, int row) { bool seen[10]; for(int i = 0; i < 10; i++) seen[i] = false; for(int i = 0; i < 9; i++) { if(board[row][i] != '.') { int num = board[row][i] - '0'; if(seen[num] == false) { seen[num] = true; } else { return false; } } } return true; } bool isSquareValid(vector<vector<char>>& board, int x, int y) { x = x * 3; y = y * 3; bool seen[10]; for(int i = 0; i < 10; i++) seen[i] = false; for(int i = 0; i < 3; i++) { for(int j = 0; j < 3; j++) { if(board[x+i][y+j] != '.') { int num = board[x+i][y+j] - '0'; if(seen[num] == false) { seen[num] = true; } else { return false; } } } } return true; }};
38. Count and Say
题目来源:https://leetcode.com/problems/count-and-say/description/
题意
给出序列,如下:
1. 12. 113. 214. 12115. 111221
要求返回第n条序列。第n条序列是对第n-1条序列的读法,如n=2的序列就是对n=1序列的读,“1个1”,即11。11读作“2个1”,因而n=3是“21”.
思路
很简单,按照题意递归就是了。
代码
class Solution {public: string countAndSay( int n) { static string strs[] ={"", "1", "11", "21", "1211", "111221"}; if (n <= 5) return strs[n]; else { string str = countAndSay(n-1); string ans; for(int i = 0; i < str.length();) { int j = i+1; while(j < str.length() && str[j] == str[i]) { j++; } ans+=(char(j-i+'0')); ans+=(str[i]); i = j; } return ans; } }};
39.Combination Sum
题目来源:https://leetcode.com/problems/combination-sum/description/
题意
大概就是可重复选取的背包问题。
思路
采用递归的思想,如果lackOfNum比当前位置数字大,则选取当前数字,然后递归下去。如果到了某一个数字,lackOfNum==0,说明刚好满足条件,将当前选取的数列加入答案ans中。
参考代码
class Solution {public: vector<vector<int>> combinationSum(vector<int>& candidates, int target) { sort(candidates.begin(), candidates.end()); vector<vector<int>> ans; vector<int> currentNum; recurse(ans, candidates, currentNum, 0, target); return ans; } void recurse(vector<vector<int>>& ans, vector<int>& candidates, vector<int>& currentNum, int currentPos, int lackOfNum) { if (0 == lackOfNum) { ans.push_back(currentNum); return; } if(currentPos < candidates.size() && lackOfNum >= candidates[currentPos]) { for(int i = currentPos; i != candidates.size() && candidates[i] <= lackOfNum ; i++) { currentNum.push_back(candidates[i]); recurse(ans, candidates, currentNum, i, lackOfNum-candidates[i]); currentNum.pop_back(); } } }};
41. First Missing Positive
题目来源:https://leetcode.com/problems/first-missing-positive/discuss/
题意
给出一个无序数列,要求找到第一个未出现的正数。要求时间复杂度为O(n),空间复杂度为O(constant)。
思路
这是参考别人的代码,大概意思是将正数i放到第i个位置,即下标为i-1的位置。然后遍历这个数组,看哪个位置的元素不对,就知道哪个正数缺失。
参考代码
class Solution {public: int firstMissingPositive(vector<int>& nums) { int n = nums.size(), tmp = 0; for(int i = 0; i < n; i++) { while(nums[i] > 0 && nums[i] <= n && nums[nums[i]-1] != nums[i]) { tmp = nums[nums[i]-1]; nums[nums[i]-1] = nums[i]; nums[i] = tmp; } } for(int i = 0; i < n; i++) { if(nums[i] != i+1) return i+1; } return n+1; }};
45. Jump Game II
题目来源:https://leetcode.com/problems/jump-game-ii/description/
题意
给出一个数列nums
,第i个元素就是从该点最多往前跳的步数nums[i]
。问i=0最少要经过多少跳能到i=nums.size()-1。
本题应该要求的是O(n),因为我写递推加记忆化搜索,O(n^2)是超时的。
思路
参考了discussion里的答案,用的是BFS,但不是传统的BFS,因为不需要用到一个队列实例。
思想是极其精妙的:将数列划分为各个level,第i层就是从起点经过i跳可以到达的点。代码只保存了当前层最远的点(最远的都跳到,进的肯定能到),然后遍历这层的点,寻找到下一层能到的最远的点。然后进入下一层,继续这个过程。直到发现终点在某个level,这就是所需的最大跳数。
简洁!高效!美丽!
参考代码
class Solution {public: int jump(vector<int>& nums) { int n = nums.size(); if(n < 2) return 0; int level = 0, curMax = 0, i = 0, nextMax = 0; while(true) { level++; for(;i <= curMax; i++) { nextMax = max(nextMax, nums[i]+i); if(nextMax >= n-1) return level; } curMax = nextMax; } return 0; }};
- 【算法设计作业】week14
- 算法设计Week14 LeetCode Algorithms Problem #91 Decode Ways
- 算法设计作业;贪心;
- 算法设计作业1
- 算法设计作业2
- 算法设计作业3
- 算法设计作业4
- 算法设计作业5
- 算法设计作业6
- 算法设计作业7
- 算法设计作业8
- 算法设计作业9
- 算法设计作业10
- 算法设计作业11
- 算法设计作业12
- 算法设计作业13
- 算法设计作业14
- 算法设计作业15
- 【工业物联网】“哑设备”和“铁疙瘩”才是工业物联网平台的救命稻草!
- 【智能驾驶】如何制作一辆真正的无人驾驶汽车
- Linux服务器如何搭建vpn?
- 【智能零售】“未来零售”的九大思维,经营的你都需要知道
- CCF CSP 201604-2 俄罗斯方块
- 【算法设计作业】week14
- 【区块链】区块链技术在商业领域的应用案例
- 【深度学习】深度学习入门指北——从硬件到软件
- 机器学习高斯混合模型(后篇):GMM求解完整代码实现
- Unity 清单文件
- github中导入的项目报红(报错)或者引用的类是变成灰色,但是可以运行的解决方法
- 如何控制Excel统计图数据的实际显示范围
- 一期 商城项目 十天(上)
- 单元化架构,为什么要用以及我们如何做到