知识点:数字逻辑,深度优先遍历,回溯,动态规划
解题思路:前排的大部分楼主都是利用格雷编码的性质,动态规划求解。如果没学过格雷编码的同学可能很难理解。
其实这道题也可以看成是图的搜索,利用深度优先搜索和回溯可以求解。用一个n维的数组存储当前数字的每一位,分别改变每一位,递归地搜索,最终可以找到一个可行解。
class Solution {
public:
vector<int> list;
vector<int> grayCode(int n) {
if(n < 1)
{
list.push_back(0);
return list;
}
vector<int> res;
vector<int> bits(n, 0);
vector<bool> marked(pow(2, n), false);
dfs(n, bits, marked, res);
return res;
}
bool dfs(int n, vector<int>& bits, vector<bool>& marked, vector<int>& res)
{
int number = bitToNum(bits);
if (marked[number])
return false;
res.push_back(number);
marked[number] = true;
if (res.size() == pow(2, n))
{
return true;
}
for (int i = 0; i < n; i++)
{
int tmp = bits[i];
bits[i] = (bits[i] + 1) & 0x1; //循环分别修改每一位
if (dfs(n, bits, marked, res))
return true; //如果找到解了就不必再继续搜索了,直接返回
bits[i] = tmp;//记得改回来
}
res.pop_back();
marked[number] = false; //回溯恢复原来的状态
return false;
}
int bitToNum(vector<int> bits)
{
int res = 0;
for (int bit: bits)
{
res = res * 2 + bit;
}
return res;
}
};
作者:ppcat
链接:https://leetcode-cn.com/problems/gray-code/solution/shen-du-you-xian-sou-suo-hui-su-fa-qiu-jie-by-ppca/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
知识点:二分搜索
终止条件是num[mid] > num[mid+1],那么num[mid+1】就是最小值。
搜索规则:如果如果nums[mid] >= nunm[left]那么左半部分是有序数组,最小值再右半部分,left = mid + 1,反之,最小值在左半部分,right = mid - 1
class Solution {
public:
int search(vector<int>& nums) {
int left = 0;
int right = nums.size() - 1;
while (left <= right)
{
int mid = (right + left) / 2;
if (nums[mid] > nums[mid+1])
return mid + 1;
if (nums[mid] >= nums[left]) //等号条件十分重要!!!有空debug看看为啥
left = mid + 1;
else
right = mid - 1;
}
return left;
}
};
知识点:二分法
解题思路:
1.可以利用上题找到最小值,然后用target比较,可以决定在哪部分进行二分搜索
2. 直接二分法:
分两种情况讨论:有序数组在这左边;有序数组在右边
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 1;
while(left <= right)
{
int mid = (left + right) / 2;
if (nums[mid] == target)
return mid;
if (nums[left] <= nums[mid])
{ //有序数在左边
if (target >= nums[left] && target < nums[mid])
right = mid - 1; //如果target在有序数组里,那么在有序数组内搜索
else
left = mid + 1; //反之在无序数组里
}
else
{ //有序数组在右边
if (target > nums[mid] && target <= nums[right])
left = mid + 1;
else
right = mid - 1;
}
}
return -1;
}
};
知识点:分治法,动态规划,递增栈
思路1:分治法
思路2:动态规划法
对于位置i,以i为中心的,向左边扫描,第一个小于heights[i]的位置x,向左边扫描,第一个小于heights[i]的位置y,面积是heights[i] * (y - x - 1)
思路3:递增栈
//动态规划法
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int N = heights.size();
if (N < 1)
return 0;
int lefts[N];
int rights[N];
lefts[0] = -1;
rights[N - 1] = N;
for (int i = 1; i < N; i++)
{
int dp = i - 1;
while(dp >= 0 && heights[dp] >= heights[i])
dp = lefts[dp];
lefts[i] = dp;
}
for (int i = N - 2; i >= 0; i--)
{
int dp = i + 1;
while(dp < N && heights[dp] >= heights[i])
dp = rights[dp];
rights[i] = dp;
}
int res = 0;
for (int i = 0; i < N; i++)
res = std::max(res, (rights[i] - lefts[i] - 1) * heights[i]);
return res;
}
};
其他思路的代码实现