Leetcode-1367. 二叉树中的列表(树+递归)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
bool judge(TreeNode*root, ListNode*head){
if(head == nullptr) return true;
if(root == nullptr) return false;
if(root->val != head->val) return false;
return judge(root->left,head->next) || judge(root->right,head->next);
}
bool isSubPath(ListNode* head, TreeNode* root) {
if(head == nullptr) return true;
if(root == nullptr) return false;
//撸着比较
if(root->val == head->val && judge(root,head)) return true;
return isSubPath(head,root->left) || isSubPath(head,root->right);//用链表的头结点分别和树中结点进行比较
}
};
leetcode-958. 二叉树的完全性检验
(不使用层序遍历将此题的空间复杂度降到O(1))=>(知道树节点个数之后,左子树是否含有完全二叉树要求子树结点个数,右子树同理进行递归)
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
//左子树是否含有A个结点的二叉树和右子树是否含有B个结点的二叉树
int nodeCount(TreeNode*root){
if(root == nullptr) return 0;
return nodeCount(root->left)+nodeCount(root->right)+1;
}
bool judge(TreeNode* root,int n,int m){
if(root == nullptr) return n==0;
if(n==0) return false;
if(n==1) return root->left==nullptr && root->right == nullptr;
int k = max(0,2*m-1);//k为除去最后一层的结点数量
int l = min(m,n-k),r = n-k-l;//l为最后一层左边的结点数量,r为最后一个层右边的子树结点数量
return judge(root->left,(k-1)/2+l,m/2)&&judge(root->right,(k-1)/2+r,m/2);
}
bool isCompleteTree(TreeNode* root) {
if(root == nullptr) return true;
//首先知道二叉树中含有多少结点
int n = nodeCount(root);
int m =1;//m为倒数第二层的结点数,假设为1
int cnt =1;//cnt为三角里面结点的数量
while(cnt + 2*m<=n){//用于求倒数第二层m的结点数
m*=2;
cnt+=m;
}
return judge(root,n,m);//判断root树是否含有n个结点的完全二叉树
}
};
leetcode-剑指 Offer 36. 二叉搜索树与双向链表
/*
// Definition for a Node.
class Node {
public:
int val;
Node* left;
Node* right;
Node() {}
Node(int _val) {
val = _val;
left = NULL;
right = NULL;
}
Node(int _val, Node* _left, Node* _right) {
val = _val;
left = _left;
right = _right;
}
};
*/
class Solution {
public:
Node *head,*pre;
void in_order(Node* root){
if(root==nullptr)return ;
in_order(root->left);
//do something
if(pre == nullptr){
head = root;
}else{
pre->right = root;
}
root->left = pre;
pre = root;
in_order(root->right);
return ;
}
Node* treeToDoublyList(Node* root) {
if(root == nullptr) return head;
head = pre = nullptr;
in_order(root);
head->left = pre;
pre->right = head;
return head;
}
};
leetcode-464. 我能赢吗
深搜+记忆化
class Solution {
public:
unordered_map<int,bool> h;
bool dfs(int mask,int n,int total){
if(h.find(mask)!=h.end()) return h[mask];
for(int i=1;i<=n;i++){
if(mask & (1<<i))continue;
if(i>=total || !dfs(mask | (1<<i),n,total-i)){
return h[mask] = true;
}
}
return h[mask] = false;
}
bool canIWin(int maxChoosableInteger, int desiredTotal) {
int n = maxChoosableInteger,mask = 0;//用一个整数标记哪些整数取过了
if((1+n)*n/2<desiredTotal) return false;
h.clear();
return dfs(mask,maxChoosableInteger,desiredTotal);
}
};
leetcode-172. 阶乘后的零
class Solution {
public:
int trailingZeroes(int n) {
int m = 5,cnt = 0;
while(n/m){//找n里面有多少个5
cnt += n/m;
m*=5;
}
return cnt;
}
};
leetcode-384. 打乱数组
class Solution {
public:
vector<int> nums;
Solution(vector<int>& nums):nums(nums){
srand(time(0));
}
/** Resets the array to its original configuration and return it. */
vector<int> reset() {
return nums;
}
/** Returns a random shuffling of the array. */
vector<int> shuffle() {
vector<int> ret(nums);
for(int i=0;i<ret.size();i++){
swap(ret[i],ret[rand()%ret.size()]);
}
return ret;
}
};
/**
* Your Solution object will be instantiated and called as such:
* Solution* obj = new Solution(nums);
* vector<int> param_1 = obj->reset();
* vector<int> param_2 = obj->shuffle();
*/
leetcode-437. 路径总和 III
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
unordered_map<int,int> h;//第一个int 表示出现的和值,第二个int表示出现的前缀和值多少次
int count(TreeNode *root,int sum,int targetSum){
if(root == nullptr) return 0;
sum += root->val;
int ans = h[sum-targetSum];
h[sum] += 1;
ans += count(root->left,sum,targetSum);
ans +=count(root->right,sum,targetSum);
h[sum]-=1;
return ans;
}
int pathSum(TreeNode* root, int targetSum) {
h.clear();
h[0]=1;
return count(root,0,targetSum);//中间值表示前缀和值 一开始为0
}
};
leetcode-395. 至少有 K 个重复字符的最长子串
class Solution {
public:
int longestSubstring(string s, int k) {
unordered_map<char,int>cnt;
vector<int> splits;//每一个分割点的位置(分割点由那些区间内字符数量本就不满足k个的字符组成)
for(auto x:s) cnt[x]+=1;//统计完每种字符的数量
for(int i=0;s[i];i++){//设定虚拟分割点的位置
if(cnt[s[i]]<k)//如果当前字符的数量小于k次的话 说明当前字符位置就是一个分割位置
splits.push_back(i);
}
splits.push_back(s.size());//最后一个虚拟分割点就放在s字符串的最后面便于最后一个区间求解
if(splits.size() == 1) return s.size();
int pre =0,ans=0;
for(auto p:splits){//p表示当前分割位置
int len = p-pre; //当前分割的长度为
if(len>=k){//大于等于k才有求解的必要
ans = max(ans,longestSubstring(s.substr(pre,len),k));
}
pre = p+1;
}
return ans;
}
};
leetcode-190. 颠倒二进制位
class Solution {
public:
uint32_t reverseBits(uint32_t n) {
uint32_t ret = 0;
for(uint32_t i=0,j=1,k=(1<<31);i<32;++i,j<<=1,k>>=1){//j表示最低位k表示最高位 每次将j左移提升一位 ,k右移降低一位
if(n & j){//如果数字n的第i位(j所对应的那个位置是1的话)就将结果位第k位置为1
ret |= k;
}
}
return ret;
}
};
leetcode-8. 字符串转换整数 (atoi)
这道题在判断超出边界的方法上通过一个if机制就可以实现最大值和最小值的判断!!!
class Solution {
public:
int myAtoi(string s) {
int flag = 1,max_pre = INT_MAX/10,d = INT_MAX%10,ind=0,num=0;//ind表示当前处理到的字符串第几位,num表示转换成的数字
while(s[ind] ==' ') ind++;
if(s[ind] == '-'){flag = -1;ind++;}
else if(s[ind] == '+') ind++;
for(;s[ind];++ind){
//如果当前字符不是一个字符
if(s[ind]<'0'||s[ind]>'9') break;
//判断转换的数字会越界
if(num>max_pre || (num==max_pre && (s[ind]-'0')>d)){
if(flag > 0) return INT_MAX;
else return INT_MIN;
}
//正常(不判断越界和非法的转化)的进行字符串与数值的转换
num = num*10+(s[ind]-'0');
}
return num*flag;
}
};
leetcode-380. O(1) 时间插入、删除和获取随机元素
这题前面两个(插入和删除毫无疑问使用hash表,获取随机元素使用动态数组)
class RandomizedSet {
public:
/** Initialize your data structure here. */
unordered_map<int,int> h;//h值对应动态数组中的位置
vector<int> arr;
RandomizedSet() {
srand(time(0));
}
/** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
bool insert(int val) {
//如果已经有了
if(h.find(val)!=h.end()) return false;
//先插入到hash中然后插入到动态数组的最后一位
h[val] = arr.size();
arr.push_back(val);
return true;
}
/** Removes a value from the set. Returns true if the set contained the specified element. */
void swap_item(int i,int j){
//先交换两个元素在动态数组中的位置
swap(arr[i],arr[j]);
//然后交换两个元素在hash表中对应的位置
h[arr[i]] = i;
h[arr[j]] = j;
return ;
}
bool remove(int val) {
//找到对应的值然后和动态数组的最后一位进行交换
//首先判断值是否存在
if(h.find(val)==h.end()) return false;
int n=h[val],m=arr.size()-1;
swap_item(n,m);//交换动态数组中这两个元素的位置
h.erase(h.find(val));
arr.pop_back();
return true;
}
/** Get a random element from the set. */
int getRandom() {
return arr[rand()%arr.size()];
}
};
/**
* Your RandomizedSet object will be instantiated and called as such:
* RandomizedSet* obj = new RandomizedSet();
* bool param_1 = obj->insert(val);
* bool param_2 = obj->remove(val);
* int param_3 = obj->getRandom();
*/
leetcode-402. 移掉 K 位数字
这道题使用单调栈 可方便的移除k位数字 并进行讨论
class Solution {
public:
string removeKdigits(string num, int k) {
//本题使用单调栈
if(k>=num.size()) return "0";
string ret;
for(auto x:num){
while(k && ret.size() && ret.back()>x) ret.pop_back(),k--;
ret.push_back(x);
}
//两种情况:1.k=0 2.k!=0
//第二种说明不需要满足删除k个字符就能满足单调栈的性质(单调递增的)
if(k!=0)ret = ret.substr(0,ret.size()-k);
int ind = 0;
while(ret[ind] == '0')++ind;
ret = ret.substr(ind,ret.size());
if(ret == "")ret="0";
return ret;
}
};
leetcode-1081. 不同字符的最小子序列
class Solution {
public:
string smallestSubsequence(string s) {
//使用单调栈
string ret;
unordered_map<char,int>cnt;//用于记录元素个数
for(auto x:s)cnt[x]++;
unordered_set<char>h;//用于记录s字符串中都有哪些字符,以便于后面在单调栈中遇到重复的字符串不再反复压入
for(auto x:s){
if(h.find(x)==h.end()){
//不存在,入栈(先循环弹出不符合的元素);栈中存在不入栈
while(ret.size() && ret.back()>x && cnt[ret.back()]) {
h.erase(h.find(ret.back()));
ret.pop_back();
}
h.insert(x);
ret.push_back(x);
}
cnt[x]-=1;
}
return ret;
}
};
leetcode-1499. 满足不等式的最大值
class Solution {
public:
//以x坐标的值为限制的滑动窗口 == 固定了j点之后,在i点找到一个yi-xi的最大值 == 维护一个单调递减队列
int findMaxValueOfEquation(vector<vector<int>>& points, int k) {
deque<int> q;//记录相关点的下标
q.push_back(0);
int ans = INT_MIN;
for(int i=1;i<points.size();++i){
//首先维护一个滑动窗口,将超出边界的点都踢出去
while(q.size() && points[i][0] - points[q.front()][0]>k) q.pop_front();
if(q.size()){
ans = max(ans,points[i][0]-points[q.front()][0]+points[i][1]+points[q.front()][1]);
}
while(q.size() && points[i][1]-points[i][0] > points[q.back()][1]-points[q.back()][0]) q.pop_back();
q.push_back(i);
}
return ans;
}
};