[toc] 只刷中等题莫名其妙的发现会把简单题想的贼复杂…
# 121 买卖股票的最佳时机
贪心,记录前面最小的
1 2 3 4 5 6 7 8 9 10 11 12
| class Solution { public: int maxProfit(vector<int>& prices) { int minV = prices[0]; int maxAns = 0; for(int i=1;i<prices.size();++i){ maxAns = max(maxAns,prices[i]-minV); minV = min(minV,prices[i]); } return maxAns; } };
|
# 122 买卖股票问题 2
EMMMM…dp 思路是 dp [i][0] 代表当前手上没有股票的最大收益,dp [i][1] 代表当前手上有股票的最大收益
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Solution { public:
int maxProfit(vector<int>& prices) { if(prices.size()==0) return 0; int n = prices.size(); int dp[n+1][2]; dp[0][0] = 0; dp[0][1] = -1*prices[0]; for(int i=1;i<n;++i){ dp[i][0] = max(dp[i-1][0],dp[i-1][1] + prices[i]); dp[i][1] = max(dp[i-1][1],dp[i-1][0]-prices[i]); } return dp[n-1][0]; } };
|
但其实贪心的想法:只要搜集所有上坡的就可以了
想尝试证明…? 懂了,虽然题目上说了同一天不能买卖,但是如果逻辑上同一天进行买卖其实等价于没卖掉…? 但是但是。其实是没必要这么想的 想一下那条 K 线,我们其实只需要把 K 线上所有上升的曲线加起来就可以了…WOC. 懂了
1 2 3 4 5 6 7 8 9 10 11 12
| public int maxProfit(int[] arr) { if (arr == null arr.length <= 1) return 0;
int ans = 0; for (int i = 1; i < arr.length; i++) { if (arr[i] > arr[i-1]) { // 卖出有利可图 ans += (arr[i] - arr[i-1]); } }
return ans; }
|
# 4 的幂
先判断位上有几个 1 (4 的幂只能有一个 1) 然后判断 1 所在的位置 是否是奇数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class Solution { public: bool isPowerOfFour(int n) { int cnt=0;
int countDig=0; for(int i=0;i<=30;++i){ if(n&(1<<i)) countDig++; } if(countDig>1) return false;
while(n>0){ n>>=1;cnt++; } if(!(cnt&1)){ return false; } return true; } };
|
# 1. 和
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { map<int,int> mp; vector<int> ans; mp[nums[0]]=0; for(int i=1;i<nums.size();++i){ if(mp.count(target-nums[i])!=0){ ans.push_back(i); ans.push_back(mp[target-nums[i]]); return ans; } mp[nums[i]] = i; } return ans; } };
|
# 7. 整数反转
生撸了个模拟 看了题解… 尼玛怎么简单题都要数学证明了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| class Solution { public:
int countDigi(int x){ int countDig = 0; int absX = abs(x); while(absX>0){ absX/=10; countDig++; } return countDig; }
vector<int> DigVec(int x){ vector<int> a;
while(abs(x)){ a.push_back(abs(x%10)); x/=10; } return a; }
bool check(vector<int> a,vector<int> max){ if(a.size()!=max.size()) return true; int n = a.size(); for(int i=0;i<n;++i){ if(max[n-i-1]>a[i]) return true; if(max[n-i-1]<a[i]) return false; } return true; }
int reverseInt(vector<int> x){ int ans=0; for(int i=0;i<x.size();++i){ ans=ans*10+x[i]; } return ans; }
int reverse(int x) { int maxI = INT_MAX; int minI = INT_MIN;
int ans=0;
int maxDig =countDigi(maxI); vector<int> maxDigVec = DigVec(maxI); vector<int> minDigVec = DigVec(minI);
int XDig = countDigi(x); vector<int> xDigVec = DigVec(x);
bool can=false;
if(XDig==maxDig){ if(x>0){ if(check(xDigVec,maxDigVec)){ can=true; } }else{ if(check(xDigVec,minDigVec)){ can = true; } } }else can=true;
if(can) ans = reverseInt(xDigVec); if(x<0) ans=-1*ans; return ans; } };
|
数学法
暂时当做一个定义,向上递增的过程中只要小于 INT_MIN/10 或者大于 INT_MAX/10 就会越界
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Solution { public: int reverse(int x) { int rev = 0; while (x != 0) { if (rev < INT_MIN / 10 rev > INT_MAX / 10) { return 0; } int digit = x % 10; x /= 10; rev = rev * 10 + digit; } return rev; } };
|
# 9. 回文数
借用上一题模拟写法出来的数字转数组,爆解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class Solution { public: vector<int> DigVec(int x){ vector<int> a;
while(abs(x)){ a.push_back(abs(x%10)); x/=10; } return a; } bool isPalindrome(int x) { if(x<0) return false; vector<int> dv = DigVec(x); for(int i=0;i<(dv.size()+1)/2;++i){ if(dv[i]!=dv[dv.size()-i-1]) return false; } return true; } };
|
# 13. 罗马数字
生写逻辑
但是也可以根据规律来简化代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| class Solution { public:
map<char,int> mp; int romanToInt(string s) { mp['I'] = 1; mp['V'] = 5; mp['X'] = 10; mp['L'] = 50; mp['C'] = 100; mp['D'] = 500; mp['M'] = 1000; int ans =0; for(int i=0;i<s.size();++i){ if(s[i]=='I'){ if(i<s.size() && s[i+1]=='V') {ans+=4;++i;continue;} if(i<s.size() && s[i+1]=='X') {ans+=9;++i;continue;} } if(s[i]=='X'){ if(i<s.size() && s[i+1]=='L') {ans+=40;++i;continue;} if(i<s.size() && s[i+1]=='C') {ans+=90;++i;continue;} } if(s[i]=='C'){ if(i<s.size() && s[i+1]=='D') {ans+=400;++i;continue;} if(i<s.size() && s[i+1]=='M') {ans+=900;++i;continue;} } ans += mp[s[i]]; } return ans; } };
|
# 14. 最长公共前缀
淦哦
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class Solution { public: string longestCommonPrefix(vector<string>& strs) { int minL=0x3f3f3f3f; for(int i=0;i<strs.size();++i){ int len = strs[i].length(); minL = min(minL,len); } string str =""; for(int i=0;i<minL;++i){ char cur = strs[0][i]; for(int j=1;j<strs.size();++j){ if(strs[j][i]!=cur){ return str; } } str+=cur; } return str; } };
|
# 20. 有效的括号
栈
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| class Solution { public: bool isValid(string s) { stack<char> st; for(int i=0;i<s.size();++i){ if(s[i]=='(' s[i]=='[' s[i]=='{'){ st.push(s[i]); }else{ if(!st.empty()){ char cur = st.top(); if(s[i]==')'){ if(cur!='(') return false; }else if(s[i]==']'){ if(cur!='[') return false; }else if(s[i]=='}'){ if(cur!='{') return false; } st.pop(); }else return false; } } return st.empty(); } };
|