312. 戳气球
题解: 动态规划,区间DP, dp[i][j] 代表戳破 (i,j)这段气球所能获得的最大价值 (开区间)。
状态转移方程 dp[i][j] = max(dp[i][j], dp[i][k]+dp[k][j]+nums[i]*nums[k]*nums[j]),此时 k 是最后一个戳破的,(i,k) (k,j)都已经被戳破了。
class Solution { public: int dp[505][505]; // dp[i][j] 代表戳破 (i,j)这段气球所能获得的最大价值 // 状态转移方程 dp[i][j] = max(dp[i][j], dp[i][k]+dp[k][j]+nums[i]*nums[k]*nums[j]) // 此时 k 是最后一个戳破的,(i,k) (k,j)都已经被戳破了 int maxCoins(vector<int>& nums) { if(nums.size()==0) return 0; nums.insert(nums.begin(),1); nums.push_back(1); for(int l=1;l<=nums.size();l++){ for(int i=0; i+l-1<nums.size();i++){ int j = i+l-1; for(int k=i+1; k<j;k++){ dp[i][j] = max(dp[i][j], dp[i][k]+dp[k][j]+nums[i]*nums[k]*nums[j]); } } } return dp[0][nums.size()-1]; } };
面试题 17.15. 最长单词
题解: 搜索,对每一个单词进行拆分,看能否拆分为多个单词。
class Solution { public: unordered_set <string> wordset; bool split(string s){ //cout << s << endl; if(s.size()==0) return true; for(int i=1;i<=s.size();i++){ if(wordset.count(s.substr(0,i)) && split(s.substr(i)) ) return true; } return false; } string longestWord(vector<string>& words) { sort(words.begin(), words.end(), [](const string & a, const string & b) -> bool{ if(a.size()==b.size()) return a < b; return a.size() > b.size(); }); for(auto word: words) wordset.insert(word); for(int i=0;i<words.size();i++){ wordset.erase(words[i]); if(split(words[i])) return words[i]; } return ""; } };
752. 打开转盘锁
题解: 搜索,枚举所有状态。
class Solution { public: unordered_set<string> words; bool vis[10][10][10][10]; int openLock(vector<string>& deadends, string target) { for(auto x: deadends) words.insert(x); if(words.count("0000")) return -1; queue <pair<string, int> > q; q.push({"0000", 0}); vis[0][0][0][0] = 1; while(q.size()){ pair<string, int> now = q.front(); q.pop(); if(now.first==target) return now.second; string next; for(int i=0;i<4;i++){ next = now.first; if(next[i]<'9')next[i] = next[i] + 1; else next[i] = '0'; if(words.count(next)) continue; //cout << now << " " << next << endl; if(vis[next[0]-'0'][next[1]-'0'][next[2]-'0'][next[3]-'0']) continue; vis[next[0]-'0'][next[1]-'0'][next[2]-'0'][next[3]-'0'] = 1; q.push({next, now.second+1}); } for(int i=0;i<4;i++){ next = now.first; if(next[i]>'0')next[i] = next[i] - 1; else next[i] = '9'; if(words.count(next)) continue; //cout << now << " " << next << endl; if(vis[next[0]-'0'][next[1]-'0'][next[2]-'0'][next[3]-'0']) continue; vis[next[0]-'0'][next[1]-'0'][next[2]-'0'][next[3]-'0'] = 1; q.push({next, now.second+1}); } } return -1; } };
938. 二叉搜索树的范围和
题解: 搜索
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: int rangeSumBST(TreeNode* root, int L, int R) { if(!root) return 0; int val_l = rangeSumBST(root->left, L , R); int val_root = 0; if(root->val >= L && root->val <=R) val_root = root->val; int val_r = rangeSumBST(root->right, L, R); return val_l+val_root+val_r; } };
861. 翻转矩阵后的得分
题解: 贪心算法,首先我们得明确一点,一个位置肯定只能变换1次,翻转多次的话没有意义。第二,每一行的第一个数都得是1, 第三,保证第二点的基础上第每一列的1尽可能多。
class Solution { public: int matrixScore(vector<vector<int>>& A) { int rownum = A.size() , colnum = A[0].size(); for(int i=0;i<rownum;i++){ // 每一行的第一个数都得为 1 ,才能保证最终的结果尽可能大 if(A[i][0]==0){ for(int j=0;j<colnum;j++) A[i][j] = 1-A[i][j]; } } for(int i=1;i<colnum;i++){ // check 一下每一列的1的个数 int num = 0; for(int j=0;j<rownum;j++){ if(A[j][i]==1) num++; } if(num <= rownum/2){ for(int j=0;j<rownum;j++) A[j][i] = 1- A[j][i]; } } int ans = 0; for(int i=0;i<rownum;i++){ int now = 0, base = 1; for(int j=colnum-1;j>=0;j--){ //printf("%d ",A[i][j]); now = now + A[i][j]*base; base*=2; //printf("%d ",now); } ans += now; } return ans; } };