856. 括号的分数
模拟
参考https://leetcode.cn/problems/score-of-parentheses/solution/gua-hao-de-fen-shu-by-leetcode/475577
class Solution {
public:
int scoreOfParentheses(string s) {
int n=s.size();
stack<int> st;
for(int i=0; i<n; ++i){
if(s[i]=='('){
st.push(0);
}
else{
if(st.top()==0){//()情况,弹出左括号,算出来1进栈
st.pop();
st.push(1);
}
else{//(xxxx)情况,里面遇到左括号之前加和,最后乘2进栈
int tmp=0;
while(!st.empty() && st.top()!=0){
tmp+=st.top();
st.pop();
}
st.pop();//弹出左括号
st.push(2*tmp);
}
}
}
int ans=0;
while(!st.empty()){
ans+=st.top();
st.pop();
}
return ans;
}
};
543. 二叉树的直径
最大深度,递归解法,复杂度高。
deep算最大深度,左子最大深度+右子最大深度和递归左子的解,递归右子的解,3者取最大。
class Solution {
public:
int deep(TreeNode* root){
if(!root) return 0;
return 1+max(deep(root->left), deep(root->right));
}
int diameterOfBinaryTree(TreeNode* root) {
if(!root) return 0;
if(!root->left && !root->right) return 0;
return max(deep(root->left)+deep(root->right),max(diameterOfBinaryTree(root->left), diameterOfBinaryTree(root->right)));
}
};
改为把直径更新放在deep里面就不用重复计算
class Solution {
public:
int ans=0;
int deep(TreeNode* root){
if(!root) return 0;
int l=deep(root->left);
int r=deep(root->right);
ans=max(ans, l+r);
return max(l, r)+1;
}
int diameterOfBinaryTree(TreeNode* root) {
int d=deep(root);
return ans;
}
};
剑指 Offer II 092. 翻转字符
DP解法,出0的时候更新dp,dp的值是当前位置翻转前面所有的1和翻转当前位置的0所需代价的最小值,每次更新dp的时候,可以认为前一个时刻的dp已经把前面整理成单调增了,所以dp更新只看当下位置0翻转和one值。
参考https://leetcode.cn/problems/cyJERH/solution/zhe-ge-dong-tai-gui-hua-jue-liao-by-shix-pe1l/
class Solution {
public:
int minFlipsMonoIncr(string s) {
int one=0;
int dp=0;
int n=s.size();
for(int i=0; i<n; ++i){
if(s[i]=='0'){
dp=min(one,dp+1);
}
else{
one++;
}
}
return dp;
}
};
692. 前K个高频单词
哈希表+自定义排序,空间消耗大,纯业务代码写法。
改进是不用sort,按类似top k的写法,把原来的比较符号改为自定义比较,可以用冒泡k次。
优先队列是题解写法。
class Solution {
public:
static bool cmp(pair<string, int> p1, pair<string, int> p2){
//这个自定义compare要带static
if(p1.second>p2.second) return true;
else if(p1.second<p2.second) return false;
//频率大的在前,小的在后
else{//频率相同,比较字典序,字典序在前的在前
string s1=p1.first, s2=p2.first;
if(s1.compare(s2)<0) return true;//注意是s2字典序在s1前的话<0,相同的=0,s2更大的话>0
else return false;
}
}
vector<string> topKFrequent(vector<string>& words, int k) {
unordered_map<string, int> mp;//word,频率
vector<string> v;
for(auto word:words){
mp[word]++;
if(mp[word]==1)
v.push_back(word);//出现的所有词
}
vector<pair<string, int>> v2;//用于排序
for(auto word:v){
v2.push_back({word, mp[word]});
}
sort(v2.begin(), v2.end(), cmp);//排序
vector<string> ans;
for(int i=0; i<k; ++i){//取出前k个
ans.push_back(v2[i].first);
}
return ans;
}
};
1091. 二进制矩阵中的最短路径
BFS,类似迷宫,这个是nxn迷宫,相当简化,8个方向版本
套路就是先定义8个方向向量,queue存三元组<x,y,value>,visited存当前坐标是否已遍历
class Solution {
public:
vector<int> x={0,0,-1,-1,-1,1,1,1};
vector<int> y={1,-1,0,-1,1,0,-1,1};
int shortestPathBinaryMatrix(vector<vector<int>>& grid) {
int n=grid.size();
int m=n;
if(n==1){
if(grid[0][0]==0) return 1;
else return -1;
}
queue<tuple<int, int, int>> q;//横坐标,纵坐标,到当前点的最短路径
//三元组存进去,就不用分层存了
vector<vector<int>> visited(n, vector<int>(n,0));//visited防止重复计算
if(grid[0][0]==1) return -1;
visited[0][0]=1;
q.push({0,0,1});
while(!q.empty()){
auto tu=q.front(); q.pop();
int i=get<0>(tu);
int j=get<1>(tu);
int value=get<2>(tu);
for(int k=0; k<8; ++k){
int xn=x[k]+i, yn=y[k]+j;
if(xn<0 || xn>=n || yn<0 || yn>=m || grid[xn][yn]==1 || visited[xn][yn]==1) continue;
//出界就跳过
else{
if(xn==n-1 && yn==n-1){
return value+1;
}
else{
q.push({xn, yn, value+1});
visited[xn][yn]=1;
}
}
}
}
return -1;
}
};
204. 计数质数
class Solution {
public:
int countPrimes(int n) {
vector<int> v(n, 1);
int ans=0;
for(int i=2; i<n; ++i){
if(v[i]){
ans++;
if((long long)i*i<=n){
for(int j=i*i; j<n; j+=i){
v[j]=0;
}
}
}
}
return ans;
}
};
23. 合并K个升序链表
注意:这题的合并是原链表节点合并,不用new一个节点接在后面。
class Solution {
public:
ListNode* mergeTwolists(ListNode* l1, ListNode* l2){
if(!l1 || !l2) return l1?l1:l2;
ListNode* head=new ListNode(0);
ListNode* cur=head;
while(l1 && l2){
if(l1->val < l2->val){
cur->next=l1;
l1=l1->next;
cur=cur->next;
}
else{
cur->next=l2;
l2=l2->next;
cur=cur->next;
}
}
if(l1) cur->next=l1;
if(l2) cur->next=l2;
return head->next;
}
ListNode* merge(vector<ListNode*>& lists, int left, int right){
if(left==right) return lists[left];
if(left>right) return nullptr;
int mid=(left+right)/2;
return mergeTwolists(merge(lists, left, mid), merge(lists, mid+1, right));
}
ListNode* mergeKLists(vector<ListNode*>& lists) {
int n=lists.size();
return merge(lists, 0, n-1);
}
};
18. 四数之和
先排序,再遍历n直到剩下最后两个,两数和用双指针,注意不留重复,所以每一层都要去重。n数和都可以用同一套方法做
参考https://leetcode.cn/problems/4sum/solution/shuang-zhi-zhen-jie-fa-can-zhao-san-shu-zhi-he-ge-/
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
int a,b,c,d,n=nums.size();
vector<vector<int>> ans;
sort(nums.begin(), nums.end());//排序双指针
for(int i=0; i<=n-4; ++i){
//vector<int> tmp;
if(i>0 && nums[i]==nums[i-1]) continue;
a=nums[i];
for(int j=i+1; j<=n-3; ++j){
if(j>i+1 && nums[j]==nums[j-1]) continue;
b=nums[j];
int left=j+1, right=n-1;
int newTarget=target-a-b;
while(left<right){
if(nums[left]+nums[right]<newTarget) left++;
else if(nums[left]+nums[right]>newTarget) right--;
else{
ans.push_back({a,b,nums[left], nums[right]});
while(left<right&&nums[left+1]==nums[left]) left++;
while(left<right&&nums[right-1]==nums[right]) right--;
left++;
right--;
}
}
}
}
return ans;
}
};
16. 最接近的三数之和
和上面差不多,没有要存不重复的,所以不判断重复,注意一个保存最小差值就可。
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
int ans;
int n=nums.size();
int mincha=INT_MAX;
sort(nums.begin(), nums.end());
for(int i=0; i<=n-3; ++i){
int left=i+1, right=n-1;
while(left<right){
int sum=nums[i]+nums[left]+nums[right];
if(abs(sum-target)<mincha){
mincha=abs(sum-target);
ans=sum;
}
if(sum<target) left++;
else if(sum>target) right--;
else return target;
}
}
return ans;
}
};
172. 阶乘后的零
找5因子的个数
class Solution {
public:
int trailingZeroes(int n) {
if(n==0) return 0;
int ans=0;
for(int i=5; i<=n; i+=5){
for(int j=i; j%5==0; j/=5){
ans++;
}
}
return ans;
}
};
28. 实现 strStr()
用compare匹配,自己实现可以改个KMP或者朴素匹配,如果不自己实现,就不必写这种题…
class Solution {
public:
int strStr(string haystack, string needle) {
int m=haystack.size(), n=needle.size();
if(n==0) return 0;
if(m<n) return -1;
for(int i=0; i<=m-n; ++i){
string str1=haystack.substr(i,n);
if(str1.compare(needle)==0) return i;
}
return -1;
}
};
151. 颠倒字符串中的单词
class Solution {
public:
string reverseWords(string s) {
reverse(s.begin(), s.end());
int n=s.size();
string ans;
int k=0;
while(s[k]==' ') k++;
while(k<n){
if(s[k]!=' '){
string tmp;
while(k<n && s[k]!=' '){
tmp=s[k]+tmp;
k++;
}
if(tmp.size()) ans=ans+tmp+" ";
}
k++;
}
if(ans.size()){
ans=ans.substr(0, ans.size()-1);
}
return ans;
}
};
223. 矩形面积
class Solution {
public:
int computeArea(int ax1, int ay1, int ax2, int ay2, int bx1, int by1, int bx2, int by2) {
//s1, s2
//交叉面积
int s1= (ax1-ax2)*(ay1-ay2), s2=(bx1-bx2)*(by1-by2);
int x=min(ay2,by2)-max(ay1,by1), y=min(ax2,bx2)-max(ax1,bx1);
int s=s1+s2-max(x,0)*max(y,0);
return s;
}
};