LeetCode 69. Sqrt(x)
实现 int sqrt(int x) 函数。
计算并返回 x 的平方根,其中 x 是非负整数。
由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。
示例 1:
输入: 4
输出: 2
示例 2:
输入: 8
输出: 2
说明: 8 的平方根是 2.82842…,
由于返回类型是整数,小数部分将被舍去。
class Solution {
public:
int mySqrt(int x) {
int l = 0, r = x;
while(l < r)
{
long long mid = l + 1ll + r >> 1;
if(mid * mid <= x) l = mid;
else r = mid - 1;
}
return l;
}
};
LeetCode 34. Find First and Last Position of Element in Sorted Array
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
你的算法时间复杂度必须是 O(log n) 级别。
如果数组中不存在目标值,返回 [-1, -1]。
示例 1:
输入: nums = [5,7,7,8,8,10], target = 8
输出: [3,4]
示例 2:
输入: nums = [5,7,7,8,8,10], target = 6
输出: [-1,-1]
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int l = 0, r = nums.size() - 1; //二分下界,左边
while(l < r)
{
int mid = l + r >> 1;
if(nums[mid] >= target) r = mid;
else l = mid + 1;
}
if(nums.empty() || nums[r] != target)
{
vector<int> res;
res.push_back(-1), res.push_back(-1);
return res;
}
vector<int> res;
res.push_back(l);
l = 0, r = nums.size() - 1;//二分上界,右边
while(l < r)
{
int mid = l + r + 1 >> 1;
if(nums[mid] <= target) l = mid;
else r = mid - 1;
}
res.push_back(l);
return res;
}
};
LeetCode 74. Search a 2D Matrix
编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:
每行中的整数从左到右按升序排列。
每行的第一个整数大于前一行的最后一个整数。
示例 1:
输入:
matrix = [
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
target = 3
输出: true
示例 2:
输入:
matrix = [
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
target = 13
输出: false
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
if(matrix.empty() || matrix[0].empty()) return false;
int n = matrix.size(), m = matrix[0].size();
int l = 0, r = n * m - 1;
while(l < r)
{
int mid = l + r >> 1;
if(matrix[mid / m][mid % m] >= target) r = mid;
else l = mid + 1;
}
return matrix[r / m][r % m] == target;
}
};
LeetCode 240. Search a 2D Matrix II
编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target。该矩阵具有以下特性:
每行的元素从左到右升序排列。
每列的元素从上到下升序排列。
示例:
现有矩阵 matrix 如下:
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
给定 target = 5,返回 true。
给定 target = 20,返回 false。
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
if(matrix.empty() || matrix[0].empty()) return false;
int i = 0, j = matrix[0].size() - 1;
while(i < matrix.size() && j >= 0)
{
int t = matrix[i][j];
if(t == target) return true;
if(t > target) j--;
else i++;
}
return false;
}
};
LeetCode 153. Find Minimum in Rotated Sorted Array
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
请找出其中最小的元素。
你可以假设数组中不存在重复元素。
示例 1:
输入: [3,4,5,1,2]
输出: 1
示例 2:
输入: [4,5,6,7,0,1,2]
输出: 0
class Solution {
public:
int findMin(vector<int>& nums) {
if(nums[0] < nums.back()) return nums[0];
int l = 0, r = nums.size() - 1;
while(l < r)
{
int mid = l + r >> 1;
if(nums[mid] >= nums[0]) l = mid + 1;
else r = mid;
}
cout << l << ' ' << r << endl;
return nums[l];
}
};
LeetCode 162. Find Peak Element
峰值元素是指其值大于左右相邻值的元素。
给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引。
数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位置即可。
你可以假设 nums[-1] = nums[n] = -∞。
示例 1:
输入: nums = [1,2,3,1]
输出: 2
解释: 3 是峰值元素,你的函数应该返回其索引 2。
示例 2:
输入: nums = [1,2,1,3,5,6,4]
输出: 1 或 5
解释: 你的函数可以返回索引 1,其峰值元素为 2;
或者返回索引 5, 其峰值元素为 6。
说明:
你的解法应该是 O(logN) 时间复杂度的。
class Solution {
public:
int findPeakElement(vector<int>& nums) {
int l = 0, r = nums.size() - 1;
while(l < r)
{
int mid = l + r + 1 >> 1;
if(nums[mid] > nums[mid - 1]) l = mid;
else r = mid - 1;
}
// cout << l << ' ' << r << endl;
return l;
}
};
LeetCode 155. Min Stack
设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) – 将元素 x 推入栈中。
pop() – 删除栈顶的元素。
top() – 获取栈顶元素。
getMin() – 检索栈中的最小元素。
示例:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.getMin(); --> 返回 -2.
class MinStack {
public:
/** initialize your data structure here. */
stack<int> stackValue;
stack<int> stackMin;
MinStack() {
}
void push(int x) {
stackValue.push(x);
if(stackMin.empty() || x <= stackMin.top())
stackMin.push(x);
}
void pop() {
int x = stackValue.top();
stackValue.pop();
if(stackMin.top() == x) stackMin.pop();
}
int top() {
return stackValue.top();
}
int getMin() {
return stackMin.top();
}
};
/**
* Your MinStack object will be instantiated and called as such:
* MinStack* obj = new MinStack();
* obj->push(x);
* obj->pop();
* int param_3 = obj->top();
* int param_4 = obj->getMin();
*/
LeetCode 496. Next Greater Element I
给定两个没有重复元素的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。找到 nums1 中每个元素在 nums2 中的下一个比其大的值。
nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出-1。
示例 1:
输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: [-1,3,-1]
解释:
对于num1中的数字4,你无法在第二个数组中找到下一个更大的数字,因此输出 -1。
对于num1中的数字1,第二个数组中数字1右边的下一个较大数字是 3。
对于num1中的数字2,第二个数组中没有下一个更大的数字,因此输出 -1。
示例 2:
输入: nums1 = [2,4], nums2 = [1,2,3,4].
输出: [3,-1]
解释:
对于num1中的数字2,第二个数组中的下一个较大数字是3。
对于num1中的数字4,第二个数组中没有下一个更大的数字,因此输出 -1。
注意:
nums1和nums2中所有元素是唯一的。
nums1和nums2 的数组大小都不超过1000。
class Solution {
public:
vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
stack<int> stk;//单调队列
unordered_map<int, int>hash;//值 下标
for(int i = nums2.size() - 1; ~i; i--) //~i 等价于i >=0 i 等价于 i > 0
{
int t = nums2[i];
while(stk.size() && stk.top() <= t) stk.pop();//大到小排列
hash[t] = stk.size() ? stk.top() : -1;
stk.push(t);
}
vector<int> res;
for(auto x : nums1) res.push_back(hash[x]);
return res;
}
};
LeetCode 84. Largest Rectangle in Histogram
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]。
图中阴影部分为所能勾勒出的最大矩形面积,其面积为 10 个单位。
示例:
输入: [2,1,5,6,2,3]
输出: 10
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int n = heights.size(), ans = 0;
heights.push_back(-1);//数组末尾添加高度 -1 可以使得所有数字最后出栈
stack<int> stk;
for(int i = 0; i <= n; i ++)
{
while(!stk.empty() && heights[i] < heights[stk.top()])//当前元素小于 栈顶元素
{
/*
出栈后,cur右边第一个比它低的柱形条就是i,左边第一个比它低的柱形条是当前栈中的top。
不断出栈直到栈为空或者柱形条i不再比top低。
*/
int cur = stk.top();
stk.pop();
if(stk.empty()) //单调队列为空
ans = max(ans, heights[cur] * i);
else //单调队列不为空
ans = max(ans, heights[cur] * (i - stk.top() - 1));
}
stk.push(i);
}
return ans;
}
};
LeetCode 42. Trapping Rain Water
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Marcos 贡献此图。
示例:
输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6
class Solution {
public:
int trap(vector<int>& height) {
int n = height.size(), ans = 0;
stack<int> stk;
for(int i = 0; i < n; i ++)
{
while(!stk.empty() && height[i] > height[stk.top()])
{
int top = stk.top();
stk.pop();
if(stk.empty()) break;
ans += (i - stk.top() - 1) * (min (height[stk.top()], height[i]) - height[top]);
}
stk.push(i);
}
return ans;
}
};
LeetCode 475. Heaters
冬季已经来临。 你的任务是设计一个有固定加热半径的供暖器向所有房屋供暖。
现在,给出位于一条水平线上的房屋和供暖器的位置,找到可以覆盖所有房屋的最小加热半径。
所以,你的输入将会是房屋和供暖器的位置。你将输出供暖器的最小加热半径。
说明:
给出的房屋和供暖器的数目是非负数且不会超过 25000。
给出的房屋和供暖器的位置均是非负数且不会超过10^9。
只要房屋位于供暖器的半径内(包括在边缘上),它就可以得到供暖。
所有供暖器都遵循你的半径标准,加热的半径也一样。
示例 1:
输入: [1,2,3],[2]
输出: 1
解释: 仅在位置2上有一个供暖器。如果我们将加热半径设为1,那么所有房屋就都能得到供暖。
示例 2:
输入: [1,2,3,4],[1,4]
输出: 1
解释: 在位置1, 4上有两个供暖器。我们需要将加热半径设为1,这样所有房屋就都能得到供暖。
class Solution {
public:
int findRadius(vector<int>& houses, vector<int>& heaters) {
heaters.push_back(INT_MIN), heaters.push_back(INT_MAX);//哨兵 边界
sort(heaters.begin(), heaters.end());
int res = 0;
for(auto &x : houses) //枚举每个房屋求最小半径
{
int l = 0, r = heaters.size() - 1;
while(l < r)
{
int mid = l + r >> 1;
if(heaters[mid] >= x) r = mid;
else l = mid + 1;
}
// 房屋与左边 和右边的 最小值
res = max(res, (int)min(x - 0ll - heaters[r - 1], heaters[r] - 0ll - x));
}
return res;
}
};
LeetCode 239. Sliding Window Maximum
给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口 k 内的数字。滑动窗口每次只向右移动一位。
返回滑动窗口最大值。
示例:
输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值
--------------- -----
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
注意:
你可以假设 k 总是有效的,1 ≤ k ≤ 输入数组的大小,且输入数组不为空。
进阶:
你能在线性时间复杂度内解决此题吗?
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
deque<int> dq;//队尾队头 都要插入删除 所以用双向队列
vector<int> res;
for(int i = 0, j = 0; i < nums.size(); i ++)
{
while(!dq.empty() && nums[i] >= nums[dq.front()]) dq.pop_front();
dq.push_front(i);//在头插入新元素 队尾是最大
if(i - j + 1 > k) //判断队头是否出列
{
if(j >= dq.back()) dq.pop_back();
j ++;
}
if(i - j + 1 == k)
res.push_back(nums[dq.back()]);
}
return res;
}
};
LeetCode 456. 132 Pattern
给定一个整数序列:a1, a2, …, an,一个132模式的子序列 ai, aj, ak 被定义为:当 i < j < k 时,ai < ak < aj。设计一个算法,当给定有 n 个数字的序列时,验证这个序列中是否含有132模式的子序列。
注意:n 的值小于15000。
示例1:
输入: [1, 2, 3, 4]
输出: False
解释: 序列中不存在132模式的子序列。
示例 2:
输入: [3, 1, 4, 2]
输出: True
解释: 序列中有 1 个132模式的子序列: [1, 4, 2].
示例 3:
输入: [-1, 3, 2, 0]
输出: True
解释: 序列中有 3 个132模式的的子序列: [-1, 3, 2], [-1, 3, 0] 和 [-1, 2, 0].
class Solution {
public:
bool find132pattern(vector<int>& nums) {
int s3 = INT_MIN;
stack<int> stk;
for(int i = nums.size() - 1; ~i; i--)
{
if(nums[i] < s3) return true; //i < j < k
while(stk.size() && nums[i] > stk.top())
{
s3 = stk.top();//j 的值
stk.pop();
}
stk.push(nums[i]); //k 的值
}
return false;
}
};
LeetCode 4. Median of Two Sorted Arrays
给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。
请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1 和 nums2 不会同时为空。
示例 1:
nums1 = [1, 3]
nums2 = [2]
则中位数是 2.0
示例 2:
nums1 = [1, 2]
nums2 = [3, 4]
则中位数是 (2 + 3)/2 = 2.5
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int total = nums1.size() + nums2.size();
if(total % 2 == 0) //偶数
{
int left = findKthNumber(nums1, 0, nums2, 0, total / 2);
int right = findKthNumber(nums1, 0, nums2, 0, total / 2 + 1);
return (left + right) / 2.0;
}
else //奇数
{
return findKthNumber(nums1, 0, nums2, 0, total / 2 + 1);
}
}
//寻找第k大的数
int findKthNumber(vector<int>&nums1, int i, vector<int>&nums2, int j, int k)
{
//边界1
if(nums1.size() - i > nums2.size() - j) return findKthNumber(nums2, j, nums1, i, k);
if(nums1.size() == i) return nums2[j + k - 1];
if(k == 1) return min(nums1[i], nums2[j]);
int si = min(i + k / 2, int(nums1.size())), sj = j + k / 2;
if(nums1[si - 1] > nums2[sj - 1])
return findKthNumber(nums1, i, nums2, j + k / 2, k - k / 2);
else
return findKthNumber(nums1, si, nums2, j, k - (si - i));
}
};