在84题中,我们求了一个柱状图中最大矩形。而本题只要首先把矩阵改变为一个显示每列最大长度的柱状图,即可用84题的栈方法求解
class Solution {
public:
//leetcode 84那道题的求法
int maxArea(vector<int>& matrix) {
stack<int> s;
s.push(-1);
int max_area = 0, height, width;
for(int i = 0; i < matrix.size(); ++i) {
while(s.top() != -1 && matrix[i] <= matrix[s.top()]) {
height = matrix[s.top()];
s.pop();
width = i - s.top() - 1;
max_area = max(max_area, height*width);
}
s.push(i);
}
while(s.top() != -1) {
height = matrix[s.top()];
s.pop();
width = matrix.size() - s.top() - 1;
max_area = max(max_area, height*width);
}
return max_area;
}
int maximalRectangle(vector<vector<char>>& matrix) {
if(matrix.size() == 0) return 0;
int size = matrix[0].size(), max_area = 0;
vector<int>dp(size, 0);
for(int i = 0; i < matrix.size(); ++i) {
for(int j = 0; j < size; ++j) {
//逐行更新dp数组,dp[j]代表第j列的柱子高度
//当matrix[i][j] == '0' ,dp[j] = 0,这很重要,仔细想一下
dp[j] = matrix[i][j] == '1' ? dp[j] + 1 : 0;
}
//逐行更新此时连续柱体形成的矩形面积
max_area = max(max_area, maxArea(dp));
}
return max_area;
}
};
本题的解法是新建两个链表分别存放小于和大于等于的值,然后拼接两个链表即可
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* partition(ListNode* head, int x) {
if(!head || !head->next) return head;
ListNode* l_less_than = new ListNode(head->val);
ListNode* l_larger_than = new ListNode(head->val);
ListNode* l_less_than_bak = l_less_than;
ListNode* l_larger_than_bak = l_larger_than;
ListNode* head_bak = head;
head_bak = head_bak->next;
while(head_bak){
ListNode* new_node = new ListNode(head_bak->val);
if(head_bak->val < x){
l_less_than_bak->next = new_node;
l_less_than_bak = l_less_than_bak->next;
}else{
l_larger_than_bak->next = new_node;
l_larger_than_bak = l_larger_than_bak->next;
}
head_bak = head_bak->next;
}
if(head->val < x){
l_larger_than = l_larger_than->next;
}else{
l_less_than = l_less_than->next;
}
l_less_than_bak->next = l_larger_than;
// //for debug
//// TraverseListNode(l_less_than_bak);
// TraverseListNode(l_less_than);
return l_less_than ? l_less_than : l_larger_than;
}
};
检测s2是否是s1的扰乱字符串,则检测s2的子串和s1的子串关系,再依次检测至整串即可,所以可以采用动态规划解决:我们用dp[i][j][L]表示S(i:i+L)和T(j:j+L)两个子串是否扰动
class Solution {
public:
bool isScramble(string s1, string s2) {
if (s1.size() != s2.size()) return false;
if (s1.empty()) return true;
int N = s1.size();
vector<vector<vector<bool> > > dp(N + 1, vector<vector<bool> >(N, vector<bool>(N, false)));
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
dp[1][i][j] = s1[i] == s2[j];
}
}
for (int len = 2; len <= N; ++len) {
for (int i = 0; i < N && i + len - 1 < N; ++i) {
for (int j = 0; j < N && j + len - 1 < N; ++j) {
for (int k = 1; k < len; ++k) {
if (dp[k][i][j] && dp[len - k][i + k][j + k]) {
dp[len][i][j] = true;
break;
}
if (dp[k][i][j + len - k] && dp[len - k][i + k][j]) {
dp[len][i][j] = true;
break;
}
}
}
}
}
return dp[N][0][0];
}
};
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int p = m - 1;
int q = n - 1;
int len = m + n - 1;
while (p >= 0 && q >= 0)
nums1[len--] = nums1[p] > nums2[q] ? nums1[p--] : nums2[q--];
while (q >= 0)
nums1[len--] = nums2[q--]; //最后 nums2有残留就一定是在最前面的
}
};
本题可以通过观察发现:对于一个dp[n - 1],dp[n]的前一半值其实是在dp[n - 1]前加一个0,而后一半则是dp[n - 1]的镜像前面加一个1,由此可以用动态规划求解
class Solution {
public:
vector<int> grayCode(int n) {
vector<int> result(1);
result[0] = 0;
for(int i = 1; i <= n; i++){
int e = 1 << (i - 1); //i - 1位结果前增加一位1
for(int j = result.size() - 1; j >= 0; j--){ // 镜像排列
result.push_back(e + result[j]);
}
}
return result;
}
};
本题也是采用回溯法求所有子集,但是和78题子集1的区别在于会存在重复元素,也因此会有重复的解,因此需要考虑剪枝
class Solution {
public:
vector<vector<int>> result;
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<int> tmp(nums.size());
subsetsWithDup(nums, tmp, 0, 0);
return result;
}
void subsetsWithDup(vector<int>& nums, vector<int>& tmp, int pos, int t_pos) {
if (pos >= nums.size()) {
result.emplace_back(vector<int>(tmp.begin(), tmp.begin() + t_pos));
return;
}
tmp[t_pos] = nums[pos];
subsetsWithDup(nums, tmp, pos+1, t_pos+1); // 选择当前数
while (pos+1 < nums.size() && nums[pos] == nums[pos+1]) pos ++; // 不选择当前数时,后续相等的数也要跳过
subsetsWithDup(nums, tmp, pos+1, t_pos);
}
};
本题采用动态规划求解:数字小于26大于0,则dp[i] = dp[i - 1] + dp[i - 2],否则dp[i] = dp[i - 2]
class Solution {
public:
int numDecodings(string s) {
if (s[0] == '0') return 0;
int pre = 1, curr = 1;//dp[-1] = dp[0] = 1
for (int i = 1; i < s.size(); i++) {
int tmp = curr;
if (s[i] == '0')
if (s[i - 1] == '1' || s[i - 1] == '2') curr = pre;
else return 0;
else if (s[i - 1] == '1' || (s[i - 1] == '2' && s[i] >= '1' && s[i] <= '6'))
curr = curr + pre;
pre = tmp;
}
return curr;
}
};