记录每天做过的leetcode题目,哈哈哈,和灰一起努力的日子~
- 189旋转数组
class Solution {
public:
void rotate(vector<int>& nums, int k) {
if(k>nums.size())
k=k%nums.size();
//reverse(nums,0,nums.size()-1);
//reverse(nums,0,k-1);
//reverse(nums,k,nums.size()-1);
reverse(nums.begin(),nums.end());
reverse(nums.begin(),nums.begin()+k);
reverse(nums.begin()+k,nums.end());
}
/*void reverse(vector<int>& arr,int s,int e)
{
int n;
while(s<e)
{
n=arr[e];
arr[e]=arr[s];
arr[s]=n;
++s;
--e;
}
}*/
};
reverse函数的使用方法;三次翻转的做法;k应该先取余。
- 121买卖股票的最佳时机
class Solution {
public:
int maxProfit(vector<int>& prices) {
int ans=0;
int i,j;
if(prices.size()<=0) return 0;
for(i=0;i<prices.size()-1;++i)
{
//if(prices[i]>prices[i+1])
//{
for(j=i+1;j<prices.size();++j)
{
if(prices[j]-prices[i]>ans)
ans=prices[j]-prices[i];
}
// }
if(prices[i]<prices[i+1])
++i;
}
return ans;
}
};
注意输入为0的情况。
- 543二叉树的直径
class Solution {
int ans;
int depth(TreeNode* rt) {
if(rt==NULL) return 0;
int L=depth(rt->left);
int R=depth(rt->right);
ans=max(ans,L+R);
return max(L,R)+1;
}
public:
int diameterOfBinaryTree(TreeNode* root) {
ans=0;
depth(root);
return ans;
}
};
注意直径有可能不经过根。
- 1013将数组分成和相等的三个部分
class Solution {
public:
bool canThreePartsEqualSum(vector<int>& A) {
int i=0,j=0;
int sum=0;
int yushu=32766;
int sum1=0;
int sum2=0;
int sum3=0;
int sumDividedBy3=0;
for(i=0;i<A.size();++i) {
sum=sum+A[i];
}
sumDividedBy3=sum/3;
yushu=sum%3;
if(yushu!=0) return false;
for(i=0;i<A.size()-2;++i) {
sum1=sum1+A[i];
if(sumDividedBy3 == sum1)
break;
}
for(j=i+1;j<A.size()-1;++j) {
sum2=sum2+A[j];
if(sumDividedBy3 == sum2)
break;
}
sum3=sum-sum1-sum2;
if(sum1==sum2 && sum2==sum3)
return true;
else return false;
}
};
这道题总是自测可以过,到机测总是过不了,找不到原因,灰帮我查出来是因为最开始的数都没有初始化,大概在不同的case测试时,初值就是上一次的结果,导致测试不对。
- 202快乐数
class Solution {
public:
bool isHappy(int n) {
int count=0;
int sum=0;
while(count<10) {
vector <int> digit;
while(n>0){
digit.push_back(n%10);
n /= 10;
}
n=0;
for(int i=0;i<digit.size();++i) {
n += digit[i]*digit[i];
}
if(n==1) {
return true;
}
++count;
}
return false;
}
};
这个方法肯定是不完善的,记录主要是为了记住如何把每一位数字分开存起来。
答案区有用快慢指针思想找出循环的!
- 204计数质数
class Solution {
public:
int countPrimes(int n) {
int ans=0;
int count=0;
int i=0,j=0;
if(n <= 2) return 0;
else
{
++ans;
for(i=3;i<n;++i)
{
if(i%2 == 0) continue;
for(j=1;j*j<=i;j+=2) {
if(i%j == 0) {
++count;
}
if(count>1) break;
}
if(count == 1)
++ans;
count = 0;
}
return ans;
}
}
};
写的时候一直超时,最后还是灰帮我加了一句判断count>1才调通。答案的经典解法是厄拉多塞筛法。
- 144二叉树的前序遍历
class Solution {
public:
void preode(TreeNode* rt,vector<int> & ans) {
if(rt==NULL) return;
ans.push_back(rt->val);
preode(rt->left,ans);
preode(rt->right,ans);
}
vector<int> preorderTraversal(TreeNode* root) {
vector <int> ans;
preode(root,ans);
return ans;
}
};
记住代码怎么写,还有push_back和emplace_back的区别。
- 111二叉树的最小深度
class Solution {
int ans;
int min_depth(TreeNode* rt) {
if(rt==NULL) return 0;
int L=min_depth(rt->left);
int R=min_depth(rt->right);
if(rt->left && rt->right) {//不空
ans=min(L,R)+1;
return ans;
}
else if(!rt->left || !rt->right) {//空一个
return max(L,R)+1;
}
else//全空
return 1;
}
public:
int minDepth(TreeNode* root) {
ans=0;
ans=min_depth(root);
return ans;
}
};
注意递归条件,而且没有必要再写一个函数。
- 101对称二叉树
class Solution {
bool isMirror(TreeNode* n1, TreeNode* n2) {
if(n1 == nullptr && n2 == nullptr) return true;
if(n1 == nullptr || n2 == nullptr) return false;
if(n1->val != n2->val) return false;
return isMirror(n1->left,n2->right) && isMirror(n1->right,n2->left);
}
public:
bool isSymmetric(TreeNode* root) {
if(root == nullptr) return true;
return isMirror(root->left,root->right);
}
};
我自己的思路是中序遍历二叉树,然后将遍历结果转置,看转置以后的结果与原结果是否相等来判断,对于题干中出现的特殊情况,把NULL用一个特殊值来替代,例如32766,但是对于底下的这种特殊情况,仍不能解决。上述代码是题解。
因为即使是把NULL代替了,中序遍历结果也是
- 217存在重复元素
class Solution {
public:
bool containsDuplicate(vector<int>& nums) {
if(nums.size() == 0 || nums.size() == 1) return false;
int i=0;
//BubbleSort(nums);
sort(nums.begin(),nums.end());
for(i=0;i<nums.size()-1;++i) {
if(nums[i] == nums[i+1])
return true;
}
return false;
}
void BubbleSort(vector<int>& arr) {
int i=0,j=0;
int temp=0;
int flag;
for(i=0;i<arr.size()-1;++i)
{
flag=0;
for(j=0;j<arr.size()-1-i;++j) {
if(arr[j]>arr[j+1])
{
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
flag=1;
}
}
if(flag==0)
break;
}
}
};
其实冒泡排序的时间复杂度也是O(n^2),与两个for循环比对重复元素的时间复杂度一致,之所以能过是因为leetcode给的case都是有序数组,所以过了,看题解快排就超出了时间限制。灰让我去了解unordered_map()。
- 219存在重复元素Ⅱ
class Solution {
public:
bool containsNearbyDuplicate(vector<int>& nums, int k) {
unordered_map <int,int> TraversedNums;
int i=0;
for(i=0;i<nums.size();++i) {
auto iter=TraversedNums.find(nums[i]);
if(iter != TraversedNums.end()) {
if(i-iter->second <= k) return true;
else iter->second = i;
}
else TraversedNums[nums[i]] = i;
}
return false;
/*int i=0,j=0;
if(nums.size() == 0 || nums.size() == 1) return false;
if(nums.size() == 2 && nums[0] == nums[1] && k>0) return true;
int nums_size=nums.size();
for(i=0;i<nums.size()-1;++i) {
for(j=i+1;j<min(i+k+1,nums_size);++j) {
if(nums[i] == nums[j])
return true;
}
}
return false;*/
}
};
注释的方法超超时了,学习了昨天灰说的unordered_map,代码是照着一个题解写的,还不是很会用。
以下是灰给我的讲解。 TraversedNums[n]=xxx; 这种写法的话,无论这个map中是否已经存在以关键词n为键的数据,都会在map中更新一条 n->xxx的数据。
- 409最长回文串
class Solution {
public:
int longestPalindrome(string s) {
unordered_map <char,int> TraversedStr;
int ans=0;
for(int n:s)
++TraversedStr[n];
for(auto iter : TraversedStr) {
int count = iter.second;
ans = ans + count / 2 * 2;
if(count % 2 == 1 && ans % 2 == 0)
++ans;
}
return ans;
}
};
这个是题解,因为题解很有学习的价值,所以存起来学习。
- 40最小的k个数
class Solution {
void quicksort(vector<int>& arr, int l, int r) {
if(l < r) {
int i=l,j=r;
int x=arr[l];
while(i < j) {
while(i < j && arr[j] >= x)
--j;
if(i < j) {
arr[i] = arr[j];
++i;
}
while(i < j && arr[i] <= x)
++i;
if(i<j) {
arr[j] = arr[i];
--j;
}
}
arr[i] = x;
quicksort(arr,l,i-1);
quicksort(arr,i+1,r);
}
}
public:
vector<int> getLeastNumbers(vector<int>& arr, int k) {
vector<int> ans;
int aSize=arr.size()-1;
quicksort(arr,0,aSize);
for(int i=0;i<k;++i) {
ans.push_back(arr[i]);
}
return ans;
}
};
- 28实现strStr()
class Solution {
public:
int strStr(string haystack, string needle) {
if(needle.size() == 0) return 0;
int i = 0;
int j = 0;
if(needle.size() > haystack.size()) return -1;
while(i < haystack.size()) {
for(j = 0;j<needle.size();++j) {
if(haystack[i+j] != needle[j]) {
break;
}
}
if(j == needle.size())
return i;
++i;
}
return -1;
}
};
- 220存在重复元素Ⅲ
class Solution {
public:
bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
if(t<0 || nums.size()==0 || k<1) return false;
long long mod = t+1ll;
unordered_map<long long,long long> buck;
for(int i=0;i<nums.size();++i) {
int nth = nums[i]/mod;
if(nums[i] < 0) --nth;
if(buck.find(nth) != buck.end())
return true;
if(buck.find(nth-1) != buck.end() && abs(nums[i]-buck[nth-1]) <=t)
return true;
if(buck.find(nth+1) != buck.end() && abs(nums[i]-buck[nth+1]) <=t)
return true;
buck[nth] = nums[i];
if(i>=k)
buck.erase(nums[i-k]/mod);
}
return false;
}
};
这个是题解排名第二的答案,看了很久才懂,记录主要是为了buck.erase这个函数,删除的是整个容器,key和value值,unordered_map对应的是<int,vector>时,删掉的也是整个vector。
- 面试题17.16按摩师
class Solution {
public:
int massage(vector<int>& nums) {
if(nums.size() == 0) return 0;
if(nums.size() == 1) return nums[0];
if(nums.size() == 2) return max(nums[0],nums[1]);
int i=0;
vector<int> temp(nums.size(),0);//temp[i]存前i-1位数中的最长数
temp[0]=nums[0];
temp[1]=max(nums[0],nums[1]);
for(i=2;i<nums.size();++i) {
temp[i]=max(nums[i]+temp[i-2],temp[i-1]);
}
return temp[i-1];
}
};
- 213打家劫舍Ⅱ
class Solution {
public:
int rob(vector<int>& nums) {
if(nums.size() == 0) return 0;
if(nums.size() == 1) return nums[0];
if(nums.size() == 2) return max(nums[0],nums[1]);
int count = nums.size();
vector<int> cutone(count-1,0);//去掉第一个数的最大数
vector<int> cutlast(count-1,0);//去掉第二个数的最大数
cutone[0] = nums[1];
cutone[1] = max(nums[2],nums[1]);
cutlast[0] = nums[0];
cutlast[1] = max(nums[0],nums[1]);
for(int i=2;i<count-1;++i) {
cutone[i] = max(nums[i+1]+cutone[i-2],cutone[i-1]);
cutlast[i] = max(nums[i]+cutlast[i-2],cutlast[i-1]);
}
return max(cutone[count-2],cutlast[count-2]);
}
};
- 914卡牌分组
class Solution {
int gcd(int a,int b) {
return b==0?a:gcd(b,a%b);
}
public:
bool hasGroupsSizeX(vector<int>& deck) {
if(deck.size() == 0) return false;
int X = 0;
unordered_map <int,int> sort_num;
for(int it:deck) {
++sort_num[it];
}
for(auto iter : sort_num) {
if(iter.second==1)
return false;
X=gcd(X,iter.second);
if(X == 1)
return false;
}
return true;
}
};
参考答案的,注意unordered_map和gcd的写法。
- 999可以被一步捕获的棋子数
class Solution {
public:
int numRookCaptures(vector<vector<char>>& board) {
int count=0;
int i=0,j=0,flag=-1;
int hang = board.size();
int lie = board[i].size();
for(i=0;i<hang;++i) {//find R
for(j=0;j<lie;++j) {
if(board[i][j] == 'R') {
flag=1;break;
}
}
if(flag == 1)
break;
}
if(j > 0) {//遍历上
for(int n=j-1;n>=0;--n) {
if(board[i][n] == 'p') {
++count;break;
}
if(board[i][n] == 'B')
break;
}
}
if(j < hang) {//遍历下
for(int n=j+1;n<lie;++n) {
if(board[i][n] == 'p') {
++count;
break;
}
if(board[i][n] == 'B')
break;
}
}
if(i > 0) {//遍历左
for(int n=i-1;n>=0;--n) {
if(board[n][j] == 'p') {
++count;break;
}
if(board[n][j] == 'B')
break;
}
}
if(i < hang) {//遍历下
for(int n=i+1;n<lie;++n) {
if(board[n][j] == 'p') {
++count;break;
}
if(board[n][j] == 'B')
break;
}
}
return count;
}
};
- 231 2的幂
class Solution {
public:
bool isPowerOfTwo(int n) {
if(n == 0) return false;
if(n == 1) return true;
int flag=0;
while(n % 2 == 0) {
n=n/2;
if(n == 1){
flag=1;
break;
}
}
if(flag==1)
return true;
else return false;
/*if(n>0 && !(n&(n-1)))
return true;
else return false;*/
//return n > 0 && !(n & (n - 1));
}
};
- 223矩形面积
class Solution {
public:
int calculate_square(int a, int b, int c, int d) {
return (c - a) * (d - b);
}
int computeArea(int A, int B, int C, int D, int E, int F, int G, int H) {
int s1 = 0, s2 = 0;
int x1 =0, y1 = 0, x2 = 0, y2 = 0;
int s_rep = 0;
int ans = 0;
s1 = calculate_square(A, B, C, D);
s2 = calculate_square(E, F, G, H);
if(C <= E || F >= D || A >= G || B >= H)
s_rep = 0;
else {
x1 = max(A,E);
y1 = max(B,F);
x2 = min(G,C);
y2 = min(D,H);
s_rep = calculate_square(x1, y1, x2, y2);
}
ans = s1 + (s2 - s_rep);
return ans;
}
};
- 面试题62圆圈中最后剩下的数字
class Solution {
public:
/*int ysf(int n,int m) {
if(n == 1)
return 0;
else return (ysf(n-1,m) + m ) % n;
}*/
int lastRemaining(int n, int m) {
int i;
int ans = 0;
for(i = 2;i<(n+1);++i) {
ans = (ans + m) % i;
}
return ans;
//return ysf(n,m);
}
};
这个答案是抄的题解,实际约瑟夫环,返回的是被删掉的序号,可以考虑用erase来写,但是c++的erase是找到指定元素,删除,将后面的元素依次往前移,会超时,不过可以学习erase的写法。https://blog.csdn.net/weixin_41969587/article/details/82587372
- 226翻转二叉树
/**
* 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:
TreeNode* invertTree(TreeNode* root) {
if(root == NULL) return NULL;
invertTree(root->left);
invertTree(root->right);
//TreeNode* temp;
//temp=root->right;
//root->right=root->left;
//root->left=temp;
swap(root->left,root->right);
return root;
}
};
- 205同构字符串
class Solution {
public:
bool isIsomorphic(string s, string t) {
unordered_map<char,char> szifu;
unordered_map<char,char> tzifu;
int s_count = 0;
for(int i = 0;i < s.size();++i) {
if(szifu.find(s[i]) != szifu.end()) {//if exist
if(szifu[s[i]] != t[i])//如果不是原来的映射,会自动创建映射
break;
else ++s_count;//如果是原来的映射
}
else {//如果不存在,创建并且判断与之前的字母有没有重合
++s_count;
szifu[s[i]] = t[i];
}
}
int t_count = 0;
for(int i = 0;i < t.size();++i) {
if(tzifu.find(t[i]) != tzifu.end()) {//if exist
if(tzifu[t[i]] != s[i])//如果不是原来的映射,会自动创建映射
break;
else ++t_count;//如果是原来的映射
}
else {//如果不存在,创建并且判断与之前的字母有没有重合
++t_count;
tzifu[t[i]] = s[i];
}
}
if(s_count == s.size() && t_count == t.size())
return true;
else return false;
//这个是灰教的方法,就很机智,find()函数找出这个字母第一次出现的下标
/*for(int i = 0;i < s.size(); ++i) {
if(s.find(s[i]) != t.find(t[i]))
return false;
}
return true;*/
}
};
- 234回文链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool isPalindrome(ListNode* head) {
//if(head == NULL) return true;
vector<int> nums;
while(head) {
nums.push_back(head->val);
head = head->next;
}
for(int i = 0;i<nums.size();++i) {
if(nums[i] != nums[nums.size()-i-1])
return false;
}
return true;
}
};
记住返回true和false的方法,这样返回可以注释掉链表为空的情况。