leetcode 200-300

文章目录

  • 200. 岛屿数量
  • 203. 移除链表元素
  • 204. 计数质数
  • 205. 同构字符串(哈希表)
  • 206. 反转链表
  • 207. 课程表
  • 208. 实现 Trie (前缀树)
  • 209. 长度最小的子数组(滑动窗口)
  • 213. 打家劫舍 II
  • 216. 组合总和 III(dfs记忆搜索)
  • 217. 存在重复元素
  • 218. 天际线问题
  • 219. 存在重复元素 II
  • 221. 最大正方形
  • 222. 完全二叉树的节点个数
  • 223. 矩形面积
  • 224. 基本计算器(栈)
  • 225. 用队列实现栈
  • 226. 翻转二叉树(dfs)
  • 227. 基本计算器 II
  • 228. 汇总区间
  • 230. 二叉搜索树中第K小的元素
  • 231. 2的幂
  • 232. 用栈实现队列
  • 234. 回文链表
  • 235. 二叉搜索树的最近公共祖先
  • 236. 二叉树的最近公共祖先
  • 238. 除自身以外数组的乘积
  • 239. 滑动窗口最大值
  • 240. 搜索二维矩阵 II
  • 242. 有效的字母异位词

200. 岛屿数量

写代码的时候要认真,一旦出错了,debug是很痛苦的,这次是叹号又没加队,而且初始赋值错了

class Solution {
private:
int len1;
int len2;

public:
        void dfs(int i, int j, vector<vector<char>>& biggrid)
        {
            if (biggrid[i][j] == '0')return;
            biggrid[i][j] = '0';
            dfs(i + 1, j, biggrid);
            dfs(i - 1, j, biggrid);
            dfs(i, j + 1, biggrid);
            dfs(i, j - 1, biggrid);
        }

        int numIslands(vector<vector<char>>& grid) {
            if (!grid.size()) return 0;
            len1 = grid.size();
            len2 = grid[0].size();
            vector<vector<char>> biggrid(len1 + 2, vector<char>(len2 + 2,'0'));
            for (int i = 1; i < len1 + 1; i++)
            {
                for (int j = 1; j < len2 + 1; j++)
                {
                    biggrid[i][j] = grid[i - 1][j - 1];
                }
            }
            int n=0;
            for (int i = 1; i < len1 + 1; i++)
            {
                for (int j = 1; j < len2 + 1; j++)
                {
                    if (biggrid[i][j] == '1')
                    {
                        dfs(i, j, biggrid); n++;
                    }
                }
            }
            return n;

        }
};

203. 移除链表元素

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        auto head1 = new ListNode(0);
        head1->next = head;
        auto temp = head1;
        while(temp->next)
        {
            if(temp->next->val==val)
            {
                temp->next = temp->next->next;
            }
            else
            {
                temp = temp->next;
            }
        }
        return head1->next;
    }
};

204. 计数质数

class Solution {
public:
    bool judge(int n)
    {
        for(int i = 2;i*i<=n;i++)
        {
            if(n%i==0)return false;     
        }
        return true;
    }
    int countPrimes(int n) {
        int count = 0;
        for(int i = 2; i<n;i++)
        {
            if(judge(i))count++;
        }
        return count;
    }
};

205. 同构字符串(哈希表)

class Solution {
public:
    bool isIsomorphic(string s, string t) {
        int lens = s.size();
        int lent = t.size();
        if(lens!=lent)return false;
        unordered_map<char,char> mp;
        unordered_map<char,char>::iterator iter;
        for(int i = 0 ; i<lens ;i++)
        {
            char s1 = s[i];
            if(mp.find(s1)==mp.end())
            {
                for(iter = mp.begin() ;iter != mp.end();iter++)
                {
                    if(iter->second==t[i])return false;
                }
                mp[s1] = t[i];
            }
            else
            {
                if(mp[s1]!=t[i])return false;
            }

        }
        return true;
    }
};

206. 反转链表

下面这种做法看似正确,但是是不对的,因为这里其实是浅拷贝,复制了以后如果直接对其进行修改,会导致原来的也发生变化,可以重新进行浅拷贝赋值但是不能进行值和指针的修改

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        auto head1 = head;
        head1->next = NULL;
        head = head->next;
        while(head)
        {
            auto temp = head;
            head = head->next;
            temp->next = head1;
            head1 = temp; 
        }
        return head1;
    }
};

当新建一个空节点的时候,不能使用auto

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* pre = NULL;
        auto cur = head;
        while(cur)
        {
            auto temp = cur->next;
            cur->next = pre;
            pre = cur;
            cur = temp;
        }
        return pre;
        
    }
};

207. 课程表

class Solution {
public:
    bool dfs(vector<vector<int>>& board, vector<int>& vt, int i)
    {
        if(vt[i]==-1) return true;//已经访问过
        else if (vt[i]==1)return false;//正在访问
        else
        {
            vt[i]=1;
            for(auto j : board[i])//这里必须用auto
            {
                if(!dfs(board, vt, j))return false;
            }
            vt[i]=-1;
            return true;
        }
        //return true;
    }
    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
        //0表示未访问,1表示正在访问,-1表示已经访问过
        vector<vector<int>> board(numCourses);
        for(auto p:prerequisites)//这里必须用auto因为不知道有多少个
        {
            board[p[1]].push_back(p[0]);//注意方向

        }
        vector<int> vt(numCourses,0);
        for(int i = 0 ;i<numCourses;i++)
        {
            if(!dfs(board,vt,i))return false;
        }
        return true;
    }
};

208. 实现 Trie (前缀树)

/*
* 应用:自动补全、给字符串按字典序排序
* 优势:1、找到具有同一前缀的全部键值。2、按词典序枚举字符串的数据集。
*/

class Trie {
private:
    // 最多R个指向子节点的链接,其中每个链接对应字母表数据集中的一个字母,这里取26个英文字母,R=26。
	Trie *child[26];
    // 指定节点是对应键的结尾还是只是键前缀
    bool isWord;
public:
    /** Initialize your data structure here. */
    // 构造函数
    Trie() {
        isWord = false;
        for (int i=0;i<26;i++) {
            child[i] = nullptr;
        }
    }
    
    /** Inserts a word into the trie. */
    // 插入键 时间复杂度O(m),m为键长。空间复杂度O(m),最坏的情况下新插入的键没有公共前缀。
    // 通过搜索Trie树来插入键。从根开始搜索它对应于第一个键字符的链接。
    void insert(string word) {
        // 用于指向每一层节点,进行搜索的操作。
        Trie *t = this;
        // 遍历插入键的每一个字符
        for(char c: word){
            // 如果链接不存在,创建一个新节点,并将它与父节点的链接相连,该链接与当前的键字符相匹配
            if (!t -> child[c-'a']) {
                t->child[c-'a'] = new Trie();
            }
            // 链接存在,沿着链接移动到树的下一个子层。算法继续搜索下一个键字符
            t = t->child[c-'a'];
        }
        // 直到到达键的最后一个字符,然后将当前节点标记为结束节点。此时的当前节点已经移动到键的最后字符所在的节点
        t->isWord = true;
    }
    
    /** Returns if the word is in the trie. */
    // 查找键 时间复杂度O(m),最坏的情况下m为键长。空间复杂度O(1)
    bool search(string word) {
        // 用于指向每一层节点,进行搜索的操作。
        Trie *t = this;
        // 遍历查找键的每一个字符
        for (char c:word) {
            // 如果链接不存在,查找失败
            if (!t -> child[c - 'a']) {
                return false;
            }
            // 链接存在,沿着链接移动到树的下一个子层。算法接续查找下一个键字符。
            t = t->child[c - 'a'];
        }
        // 直到到达最后一个字符,返回该键字符节点的isWord,如果为false,待查键是Trie树中另一个键的前缀。
        return t->isWord;
    }
    
    /** Returns if there is any word in the trie that starts with the given prefix. */
    // 查找Trie树中的键前缀
    bool startsWith(string prefix) {
        // 用于指向每一层节点,进行搜索的操作。
        Trie *t = this;
        // 遍历查找前缀的每一个字符
        for (char c:prefix) {
            // 如果链接不存在,查找失败
            if (!t->child[c-'a']) {
                return false;
            }
            // 链接存在,沿着链接移动到树的下一个子层。算法接续查找下一个键字符。
            t = t->child[c - 'a'];
        }
        // 直到到达最后一个字符,由于是查找前缀,而不是整个键,所以返回true
        return true;
    }
};

作者:ichhYTTtiU
链接:https://leetcode-cn.com/problems/implement-trie-prefix-tree/solution/qian-zhui-shu-c-shu-ju-jie-gou-by-ichhytttiu/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

209. 长度最小的子数组(滑动窗口)

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        if(nums.empty())return 0;
        int sum = 0,res = INT_MAX,start = 0;
        for(int i = 0 ;i<(int)nums.size() ;i++)
        {
            sum += nums[i];
            while(sum>=s)
            {
                res = min(res, i-start+1);
                sum -= nums[start];
                start++;
            }

        }
        return (res==INT_MAX)?0:res;
    }
};

213. 打家劫舍 II

对于1的情况分类讨论,一次算,一次不算,dp表达式不变

class Solution {
public:
    int rob(vector<int>& nums) {
        //分两种情况,计算1的和不计算1的
        //计算1的情况,这样最后一个不能要了
        int len = nums.size();
        if(len==0) return 0;
        if(len == 1)return nums[0];
        if(len ==2)return max(nums[0],nums[1]);
        if(len==3)return max(nums[0],max(nums[1],nums[2]));
        vector<int> dp1 = nums;
        dp1[0] = nums[0];
        dp1[1] = nums[0];
        dp1[2] = max(nums[1],nums[0]+nums[2]);
        for(int i = 3; i<len-1 ;i++ )
        {
            dp1[i] = max(dp1[i]+dp1[i-2],dp1[i-1]);
        }
        //不要第一个
        vector<int> dp2 = nums;
        dp2[0] = 0;
        dp2[1] = nums[1];
        dp2[2] = max(nums[1],nums[2]);
        for(int i =3 ; i<len ; i++)
        {
            dp2[i] = max(dp2[i]+dp2[i-2],dp2[i-1]);
        }
        return max(dp1[len-2],dp2[len-1]);

    }
};

216. 组合总和 III(dfs记忆搜索)

class Solution {
public:
    vector<vector<int>> res;
    vector<int> path;
    void dfs(int k,int n, vector<int>& ref,int sum,int p)
    {
        if(sum>n)return;
        if(path.size()==k)
        {
            if(sum==n){res.push_back(path);}
            return;
        }
        for(int i =p;i<=9;i++)
        {
            if(ref[i-1]==0)
            {
                ref[i-1]=1;
                sum += i;
                path.push_back(i);
                dfs(k,n,ref,sum,i+1);
                path.pop_back();
                sum -=i;
                ref[i-1]=0;
            }

        }
    }
    vector<vector<int>> combinationSum3(int k, int n) {
        vector<int> ref(9,0);
        dfs(k,n,ref,0,1);
        return res;
    }
};

217. 存在重复元素

class Solution {
public:
    bool containsDuplicate(vector<int>& nums) {
        unordered_map<int,int> m;
        for(auto i:nums)
        {
            if( m[i]>=1 )return true;
            else m[i]=1;
        }
        return false;

    }
};

218. 天际线问题

class Solution {
public:
    vector<vector<int>> getSkyline(vector<vector<int>>& buildings) {
        vector<pair<int,int>> h;
        multiset<int> m;
        vector<vector<int>> res;

        //1、将每一个建筑分成“两个部分”,例如:[2,9,10]可以转换成[2,-10][9,10],我们用负值来表示左边界
        for(const auto& b:buildings)
        {
            h.push_back({b[0], -b[2]});
            h.push_back({b[1], b[2]});
        }

        //2、根据x值对分段进行排序
        sort(h.begin(),h.end());
        int prev = 0, cur = 0;
        m.insert(0);

        //3、遍历
        for (auto i:h)
        {
            if (i.second < 0) m.insert(-i.second);  //左端点,高度入堆
            else m.erase(m.find(i.second));         //右端点,高度出堆
            cur = *m.rbegin();                      //当前最大高度高度
            if (cur != prev) {                      //当前最大高度不等于最大高度perv表示这是一个转折点
                res.push_back({i.first, cur});      //添加坐标
                prev = cur;                         //更新最大高度
            }
        }
        return res;
    }
};

219. 存在重复元素 II

class Solution {
public:
    bool containsNearbyDuplicate(vector<int>& nums, int k) {
        unordered_map<int,vector<int>> mp;
        for(int i = 0 ;i<nums.size();i++)
        {
            if(mp.find(nums[i])==mp.end())
            {
                vector<int> temp = {i};
                mp[nums[i]]=temp;
            }
            else
            {
                if(mp[nums[i]].size()>=1 && i-mp[nums[i]].back()<=k)return true;
                mp[nums[i]].push_back(i);
            }
        }
        return false;
    }
};

221. 最大正方形

class Solution {
public:
    int maximalSquare(vector<vector<char>>& matrix) {
        if (matrix.size() == 0 || matrix[0].size() == 0) {
            return 0;
        }
        int maxSide = 0;
        int rows = matrix.size(), columns = matrix[0].size();
        vector<vector<int>> dp(rows, vector<int>(columns));
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < columns; j++) {
                if (matrix[i][j] == '1') {
                    if (i == 0 || j == 0) {
                        dp[i][j] = 1;
                    } else {
                        dp[i][j] = min(min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
                    }
                    maxSide = max(maxSide, dp[i][j]);
                }
            }
        }
        int maxSquare = maxSide * maxSide;
        return maxSquare;
    }
};

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/maximal-square/solution/zui-da-zheng-fang-xing-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

222. 完全二叉树的节点个数

和求最大深度的方法类似,直接递归

/**
 * 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 countNodes(TreeNode* root) {
        if(!root)return 0;
        return countNodes(root->left)+countNodes(root->right)+1;
    }
};

223. 矩形面积

class Solution {
public:
    int computeArea(int A, int B, int C, int D, int E, int F, int G, int H) {
        int s1 = (C-A)*(D-B);
        int s2 = (G-E)*(H-F);
        int left = max(A,E);
        int right = min(C,G);
        int up = min(D,H);
        int down = max(B,F);
        if(left>right || up<down)return s1+s2;
        return s1+s2-(right-left)*(up-down);
    }
};

224. 基本计算器(栈)

class Solution {
public:
    int calculate(string s) {
        stack<string> st;
        int i = 0,j=0;
        while (i<s.size())
        {
            string s1;
            if (s[i] >= '0')
            {
                while (s[i] >= '0')
                {
                    s1 += s[i++];
                }
            }
            else
            {
                s1 = s[i++];
            }
            if (s1 == "(")
            {
                st.push("(");
            }
            else if (s1 == ")")
            {
                int temp = stoi(st.top());
                st.pop(); st.pop();
                
                if (!st.empty() && st.top() == "+")
                {
                    st.pop();
                    int t = stoi(st.top()) + temp;
                    st.pop();
                    st.push(to_string(t));
                }
                else if (!st.empty() && st.top() == "-")
                {
                    st.pop();
                    int t = stoi(st.top()) - temp;
                    st.pop();
                    st.push(to_string(t ));
                }
                else st.push(to_string(temp));

            }
            else if (s1 == "+")
            {
                st.push("+");
            }
            else if (s1 == "-")
            {
                st.push("-");
            }
            else if (s1 == " ")
            {
                continue;
            }
            else
            {
                if (st.empty() || st.top() == "(")st.push(s1);
                else if (st.top() == "+")
                {
                    st.pop();
                    int temp = (stoi(st.top())) + stoi(s1);
                    st.pop();
                    st.push(to_string(temp));
                }
                else if (st.top() == "-")
                {
                    st.pop();
                    int temp = (stoi(st.top())) - stoi(s1);
                    st.pop();
                    st.push(to_string(temp));
                }
            }
        }
        return stoi(st.top());
    }
};

225. 用队列实现栈

class MyStack {
public:
    //用一个队列实现
    queue<int> qt;
    /** Initialize your data structure here. */
    MyStack() {

    }
    
    /** Push element x onto stack. */
    void push(int x) {
        qt.push(x);
    }
    
    /** Removes the element on top of the stack and returns that element. */
    int pop() {
        int len = qt.size();
        while(len-1)
        {
            len--;
            qt.push(qt.front());
            qt.pop();
        }
        int temp = qt.front();
        qt.pop();
        return temp;
    }
    
    /** Get the top element. */
    int top() {
        return qt.back();
    }
    
    /** Returns whether the stack is empty. */
    bool empty() {
        return qt.empty();
    }
};

/**
 * Your MyStack object will be instantiated and called as such:
 * MyStack* obj = new MyStack();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->top();
 * bool param_4 = obj->empty();
 */

226. 翻转二叉树(dfs)

/**
 * 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)return NULL;
        auto r = invertTree(root->right);
        auto l = invertTree(root->left);
        root->right = l;
        root->left = r;
        return root;
    }
};

递归就是把大问题最后递归成小问题,只要使二叉树的每个节点的左右子节点交换,最后整个树的就翻转了

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
      dfs(root);
      return root;
    }
private:
    void dfs(TreeNode* root){ //这是先序遍历,每一个节点,然后将这个节点的左右子节点翻转
        if(root){
            swap(root->left, root->right); 
            dfs(root->left);
            dfs(root->right);
        }
    }
};

作者:zuo-10
链接:https://leetcode-cn.com/problems/invert-binary-tree/solution/c-shi-yong-swapdi-gui-die-dai-by-zuo-10/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

227. 基本计算器 II

在vs上能运行通

class Solution {
public:
int calculate(string s) {
	vector<string> st;
	int i = 0;
	while (i < s.size())
	{
		string s1;
		if (s[i] >= '0')
		{
			while (s[i] >= '0')
			{
				s1 += s[i++];
			}
		}
		else
		{
			s1 = s[i++];
		}
		if (st.empty() || s1 == "+" || s1 == "-" || s1 == "*" || s1 == "/") { st.push_back(s1); }
		else if (s1 == " ") {}
		else
		{
			if (st.back() == "*")
			{
				st.pop_back();
				int temp = stoi(st.back())*stoi(s1);
				st.pop_back();
				st.push_back(to_string(temp));
			}
			else if(st.back()=="/")
			{
				st.pop_back();
				int temp = stoi(st.back()) / stoi(s1);
				st.pop_back();
				st.push_back(to_string(temp));
			}
			else
			{
				st.push_back(s1);
			}
		}

	}
	int res = stoi(st[0]);
	for (i = 1; i < st.size(); i++)
	{
		if (st[i - 1] == "+")
		{
			res += stoi(st[i]);
		}
		else if (st[i - 1] == "-")
		{
			res -= stoi(st[i]);
		}
	}
	return res;
}
};

228. 汇总区间

特别注意里面溢出的情况,最好的解决方式就换个表达方式,尽量不要产生大的数

class Solution {
public:
    vector<string> summaryRanges(vector<int>& nums) {
        //for(int i = 0;i(nums[i]);
        int i=1,j=0;
        vector<string> res;
        while(i<nums.size())
        {       
            //while(i
            while(i<nums.size() && nums[i]-1==nums[i-1])i++;
            if(j==i-1)
            {
                res.push_back(to_string(nums[j++]));i++;
            }
            else
            {
                res.push_back(to_string(nums[j])+"->"+to_string(nums[i-1]));j=i;i++;
            }
        }
        if(j==nums.size()-1)res.push_back(to_string(nums[j]));
        return res;
    }
};

230. 二叉搜索树中第K小的元素

/**
 * 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 count = 0;
    int res = 0;
    void dfs(TreeNode* root, int k)
    {
        if(!root)return;
        dfs(root->left,k);
        count++;if(count==k){res = root->val;return;}
        dfs(root->right,k);
    }
    int kthSmallest(TreeNode* root, int k) {
        dfs(root,k);
        return res;
    }
};

231. 2的幂

class Solution {
public:
    bool isPowerOfTwo(int n) {
        if(n==1)return true;
        if(n<=0)return false;
        if(n>0 && n<1)
        {
            n = 1/n;
        }
        while(n>2)
        {
            if(n%2!=0)return false;
            n /=2;
        }
        return true;
    }
};

232. 用栈实现队列

自己写的不仅复杂而且有检查不出的错误,因为peek和pop会导致栈的元素全部移到另一个栈中会颠倒顺序,所以每次进行这两个操作的时候都需要再重新倒回来,这会十分的复杂
下面这个实现非常简单,一个栈就用来进,一个就用来出,当要出的时候就从出站里面弹,如果出栈为空就把入栈的所有元素再放入出栈,而且pop操作时比peek多加了一步,pop里面还能再使用peek

class MyQueue {
public:
    /** Initialize your data structure here. */
    MyQueue() {
        
    }
    
    /** Push element x to the back of queue. */
    void push(int x) {
        input.push(x);
    }
    
    /** Removes the element from in front of queue and returns that element. */
    int pop() {
        int temp = peek();
        output.pop();
        return temp;
    }
    
    /** Get the front element. */
    int peek() {
        if(output.empty()){
            while(input.size()){
                output.push(input.top());
                input.pop();
            }
        }
        return output.top();
    }
    
    /** Returns whether the queue is empty. */
    bool empty() {
        return input.empty() &&output.empty();
    }
    stack<int> input, output;
};

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) {
        int count = 0;
        auto slow = head;
        auto fast = head;
        auto temp = head;
        while(temp){count++;temp=temp->next;}
        while(fast && fast->next)
        {
            slow= slow->next;
            fast = fast->next->next;
        }
        if(count%2==1){slow =slow->next;}
        ListNode* pre = NULL;
        auto cur = slow;
        while(cur)
        {
            temp = cur->next;
            cur->next = pre;
            pre = cur;
            cur = temp;
        }
        slow = pre;
        while(head && slow)
        {
            if(head->val != slow->val)return false;
            head = head->next;
            slow = slow->next;
        }
        return true;
        


    }
};

235. 二叉搜索树的最近公共祖先

利用二叉搜索树的性质

/**
 * 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* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(!root)return root;
        if((root->val>=p->val && root->val<=q->val)||(root->val<=p->val && root->val>=q->val))return root;
        if(root->val<=p->val && root->val<=q->val)return lowestCommonAncestor(root->right,p,q);
        if(root->val>=p->val && root->val>=q->val)return lowestCommonAncestor(root->left,p,q);
        return root;
    }
};

236. 二叉树的最近公共祖先

当我们用递归去做这个题时不要被题目误导,应该要明确一点
这个函数的功能有三个:给定两个节点 p 和 q

如果 p 和 q 都存在,则返回它们的公共祖先;
如果只存在一个,则返回存在的一个;
如果 p 和 q 都不存在,则返回NULL

具体思路:
(1) 如果当前结点 root等于 NULL,则直接返回 NULL
(2) 如果 root 等于 p 或者 q ,那这棵树一定返回 pp 或者 qq
(3) 然后递归左右子树,因为是递归,使用函数后可认为左右子树已经算出结果,用 left和 right表示
(4) 此时若leftleft为空,那最终结果只要看 rightright;若 rightright 为空,那最终结果只要看 leftleft
(5) 如果 leftleft 和 rightright 都非空,因为只给了 pp 和 qq 两个结点,都非空,说明一边一个,因此 rootroot 是他们的最近公共祖先
(6) 如果 leftleft 和 rightright 都为空,则返回空(其实已经包含在前面的情况中了)

时间复杂度是 O(n)O(n):每个结点最多遍历一次或用主定理,空间复杂度是 O(n)O(n):需要系统栈空间

作者:Wilson79
链接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/solution/c-jing-dian-di-gui-si-lu-fei-chang-hao-li-jie-shi-/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root == NULL)
            return NULL;
        if(root == p || root == q) 
            return root;
            
        TreeNode* left =  lowestCommonAncestor(root->left, p, q);
        TreeNode* right = lowestCommonAncestor(root->right, p, q);
       
        if(left == NULL)
            return right;
        if(right == NULL)
            return left;      
        if(left && right) // p和q在两侧
            return root;
        
        return NULL; // 必须有返回值
    }
};


作者:Wilson79
链接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/solution/c-jing-dian-di-gui-si-lu-fei-chang-hao-li-jie-shi-/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

238. 除自身以外数组的乘积

这道题本来开始想的是遍历一次求所有位置的左积,再遍历一次求所有位置的右积,再遍历一次求左积*右积
大概是O(3n),但是其实可以一次遍历完成,每个值先不着急乘是左右的乘机乘积,可以先左边乘到这里,等一会右边再乘到这里,十分巧妙

class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        
        int n=nums.size();
        int left=1,right=1;     //left:从左边累乘,right:从右边累乘
        vector<int> res(n,1);
        
        for(int i=0;i<n;++i)    //最终每个元素其左右乘积进行相乘得出结果
        {
            res[i]*=left;       //乘以其左边的乘积
            left*=nums[i];
            
            res[n-1-i]*=right;  //乘以其右边的乘积
            right*=nums[n-1-i];
        }
        
        return res;
        
    }
};

作者:ooolize-2
链接:https://leetcode-cn.com/problems/product-of-array-except-self/solution/yi-ci-bian-li-qiao-miao-cun-chu-he-ji-suan-zuo-ji-/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

239. 滑动窗口最大值

    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        vector<int> res;
        if(k == 0) return res;
        deque<int> window;   //双端队列,从队头到队尾 依次存 窗口内最大元素的index ~ 最小元素的index

        int right = 0;
        while(right < nums.size()){   //后续,窗口每右移一次,都会产生一个最大值[队列头位置的元素]
            if(!window.empty() && window.front() <= right - k){   //队头不在窗口范围内
                window.pop_front();
            }
            while(!window.empty() && nums[right] > nums[window.back()]){   //待入队元素比队尾元素大
                window.pop_back();
            }
            window.push_back(right);
            right++;
            if(right >= k) res.push_back(nums[window.front()]);
        }
        return res;
    }

240. 搜索二维矩阵 II

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
       if(matrix.empty())return false;
       int len1 = matrix.size();
       int len2 = matrix[0].size(); 
       int i=len1-1,j=0;
       while(i>=0 && j<len2)
       {
           if(target==matrix[i][j])return true;
           else if(target<matrix[i][j])
           {
               i--;
           }
           else
           {
               j++;
           }
       }
       return false;
    }
};

242. 有效的字母异位词

class Solution {
public:
    bool isAnagram(string s, string t) {
        unordered_map<char,int> ms,mt;
        for(auto s1:s)ms[s1]++;
        for(auto t1:t)mt[t1]++;
        return ms==mt;
    }
};

你可能感兴趣的:(C++)