leetcode 200-300

文章目录

重做题

223,224, 225, 226,227,236,239,257,260,264,268,269,273,274,282,287,289,290,295,297

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;

        }
};

201. 数字范围按位与

class Solution {
public:
    int rangeBitwiseAnd(int m, int n) {
        int count = 0;
        while(m != n){
            m = m >> 1;
            n = n >> 1;
            count++;
        }
        n = n << count;
        return n;
    }
};

作者:bengdiwang
链接:https://leetcode-cn.com/problems/bitwise-and-of-numbers-range/solution/201-shu-zi-fan-wei-an-wei-yu-by-bengdiwang/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

202. 快乐数

class Solution {
public:
    bool isHappy(int n) {
       string res = to_string(n);
       unordered_set<string> st;
       st.insert(res);
       while(stoi(res)!=1)
       {
           int temp = 0;
           for(auto r:res)
           {
               temp += pow(r-'0',2);
           }
           res = to_string(temp);
           if(st.find(res)!=st.end())return false;
           else st.insert(res);
       }
       return true;
    }
};

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 isok(string s, string t)
    {
        unordered_map<char,char> mp;
        for(int i = 0 ; i <s.size();i++)
        {
            if(mp.find(s[i])==mp.end())
            {
                mp[s[i]]=t[i];
            }
            else
            {
                if(mp[s[i]]!=t[i])return false;
            }
        }
        return true;        
    }
    bool isIsomorphic(string s, string t) {
        return isok(s,t)&&isok(t,s);

    }
};
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) {
        ListNode* head1 = NULL;
        auto pre = head1;
        auto cur = head;
        while(cur)
        {
            auto temp = cur->next;
            cur->next = pre;
            pre = cur;
            cur = temp;
        }
        return pre;
    }
};

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

/**
 * 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 canFinish(int numCourses, vector<vector<int>>& prerequisites) {                
        vector<int> inDegree(numCourses, 0); // 遍历边缘列表,计算入度
        
        // 有向无环DAG图的存储,使用邻接表
        vector<vector<int>> dirTable(numCourses, vector<int>() );
        for(auto v:prerequisites) {
            inDegree[v[0]]++;  //dstNode的入度+1
            dirTable[v[1]].push_back(v[0]); // 存储srcNode邻接表
        }

        queue<int> que;
        // 然后找到入度=0的索引作为起始点进行拓扑排序,使用队列queue,先将入度为0的enQueue
        for(int i=0;i<inDegree.size();i++) {
            if(inDegree[i]==0) que.push(i);
        }
        vector<int> res;
        while(!que.empty()) {
            auto tmp = que.front(); que.pop();   // 将入度为0的进行出队,那就是每次出一个呗
            res.push_back(tmp);
            for(auto adjnode:dirTable[tmp]){
                if(--inDegree[adjnode]==0)    // 然后跟他有关的边及目标node的入度-1
                    que.push(adjnode);   // 然后再次将入度=0的node进队,直到队列为空,且入度都为0了
            }
        }
        return res.size() == numCourses;        
    }
    
};

作者:justdoitno1
链接:https://leetcode-cn.com/problems/course-schedule/solution/c-tuo-bu-topopai-xu-jian-dan-yi-dong-zhu-shi-wan-z/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

图的dfs

借助一个标志列表 flags,用于判断每个节点 i (课程)的状态:
未被 DFS 访问:i == 0;
已被其他节点启动的 DFS 访问:i == -1;
已被当前节点启动的 DFS 访问:i == 1。
对 numCourses 个节点依次执行 DFS,判断每个节点起步 DFS 是否存在环,若存在环直接返回 FalseFalse。DFS 流程;
终止条件:
当 flag[i] == -1,说明当前访问节点已被其他节点启动的 DFS 访问,无需再重复搜索,直接返回 TrueTrue。
当 flag[i] == 1,说明在本轮 DFS 搜索中节点 i 被第 22 次访问,即 课程安排图有环 ,直接返回 FalseFalse。
将当前访问节点 i 对应 flag[i] 置 11,即标记其被本轮 DFS 访问过;
递归访问当前节点 i 的所有邻接节点 j,当发现环直接返回 FalseFalse;
当前节点所有邻接节点已被遍历,并没有发现环,则将当前节点 flag 置为 -1−1 并返回 TrueTrue。
若整个图 DFS 结束并未发现环,返回 TrueTrue。

作者:jyd
链接:https://leetcode-cn.com/problems/course-schedule/solution/course-schedule-tuo-bu-pai-xu-bfsdfsliang-chong-fa/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

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 (前缀树)

struct TrieNode {
    bool isEnd = false;
    unordered_map<char, TrieNode*> next;
};

class Trie {
private:
    TrieNode *root;
    
public:
    Trie(): root(new TrieNode()) {}
    
    void insert(string word) {
        TrieNode *p = root;
        for (const char c : word) {
            if (!p->next.count(c)) {
                p->next[c] = new TrieNode();
            }
            p = p->next[c];
        }
        p->isEnd = true;
    }
    
    bool search(string word) {
        TrieNode *p = root;
        for (const char c : word) {
            if (!p->next.count(c)) {
                return false;
            }
            p = p->next[c];
        }
        return p->isEnd;
    }
    
    bool startsWith(string prefix) {
        TrieNode *p = root;
        for (const char c : prefix) {
            if (!p->next.count(c)) {
                return false;
            }
            p = p->next[c];
        }
        return p != nullptr;
    }
};

作者:happy_yuxuan
链接:https://leetcode-cn.com/problems/implement-trie-prefix-tree/solution/li-yong-setde-xing-zhi-shi-xian-qian-zhui-shu-jian/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
/*
* 应用:自动补全、给字符串按字典序排序
* 优势: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. 长度最小的子数组(滑动窗口)

( 涉 及 连 续 子 数 组 的 问 题 , 通 常 有 两 种 思 路 : 一 是 滑 动 窗 口 、 二 是 前 缀 和 。 ) \color{red}(涉及连续子数组的问题,通常有两种思路:一是滑动窗口、二是前缀和。) ()

滑动窗口o(N)

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;
    }
};

前缀和二分法 O(NlogN)

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        if(nums.empty())return 0;
        int len = nums.size();
        auto dp=nums;
        for(int i = 1 ; i<len;i++)
        {
            dp[i]=dp[i-1]+nums[i];
        }
        dp.insert(dp.begin(),0);
        int res = INT_MAX;
        for(int i = 0;i<len+1;i++)
        {
            int left = i+1,right = len+1;
            while(left<right)
            {
                int mid = left + (right-left)/2;
                if(dp[mid]-dp[i]>=s)
                {
                    res = min(res,mid-i);
                    right = mid;
                }
                else
                {
                    left  = mid + 1;
                }
            }
        }
        return res==INT_MAX?0:res;
    }
};

210. 课程表 II

/*
此题跟 207 题几乎就是一道题,只不过是输出是拓扑排序后的结果
*/
class Solution {
public:
    vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {

        vector<int> inDegree(numCourses, 0);  // 记录Node的入度
        vector<vector<int>> adjLst(numCourses, vector<int>());  // 邻接表
        for(auto arr : prerequisites) {
            inDegree[arr[0]]++;  // 更新 入度及其邻接表adjTable
            adjLst[arr[1]].push_back(arr[0]);
        }
        
        queue<int> que;  // topo排序依赖的队列
        for(auto cnt=0;cnt<inDegree.size();cnt++) {
            if(inDegree[cnt]==0) que.push(cnt);
        }
        vector<int> res;
        while(!que.empty()) {
            auto tmp = que.front(); que.pop();
            // cout<< tmp << endl;
            res.push_back(tmp);  // 拓扑排序
            for(auto i : adjLst[tmp]) {   // 更新排序节点的连通nodes的入度
                if(--inDegree[i]==0) que.push(i);
            }
        }
        if(res.size() == numCourses) return res;
        else return {} ;
    }
};

作者:justdoitno1
链接:https://leetcode-cn.com/problems/course-schedule-ii/solution/tuo-bu-pai-xu-can-kao-no207-jian-zhi-yi-yang-de-ti/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

211. 添加与搜索单词 - 数据结构设计

class WordDictionary {
public:
    struct Node
    {
        bool isend = false;
        unordered_map<char,Node*> next;
    };
    Node* root;
    /** Initialize your data structure here. */
    WordDictionary() {
        root = new Node();
    }
    
    /** Adds a word into the data structure. */
    void addWord(string word) {
        auto p = root;
        for(auto& w:word)
        {
            if(p->next.find(w)==p->next.end())p->next[w] = new Node();
            p = p->next[w];
        }
        p->isend = true;
    }
    
    /** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */
    bool search(string word) {
        auto p = root;
        int len = word.size();
        return dfs(p,word,0,len);
    }
    bool dfs(Node* p, string word, int i ,int len)
    {
        if(i==len)return p->isend;
        if(word[i]=='.')
        {
            for(auto& n:p->next)
            {
                if(dfs(n.second,word,i+1,len))return true;
            }
            return false;
        }
        else
        {
            if(p->next.find(word[i])==p->next.end())return false;
            p = p->next[word[i]];
            return dfs(p,word,i+1,len);
        }
    }
};

/**
 * Your WordDictionary object will be instantiated and called as such:
 * WordDictionary* obj = new WordDictionary();
 * obj->addWord(word);
 * bool param_2 = obj->search(word);
 */
class WordDictionary {
public:
    /** Initialize your data structure here. */
    struct node{
        bool isEnd;
        unordered_map<char,node*>children;
        node(){isEnd=false;}
        
    };
    node* root;
    WordDictionary() {
        root=new node();
    }
    /** Adds a word into the data structure. */
    void addWord(string word) {
        auto p=root;
        for(auto c:word){
            if(!p->children.count(c))p->children.insert({c,new node()});
            p=p->children[c];
        }
        p->isEnd=true;
    } 
    /** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */
    bool search(string word) {
        auto p=root;
        return help(p,word.begin(),word.end());
    }
    template<typename it>
    bool help(node* root,it l,it r){
        if(l==r)return root->isEnd;
        if(*l=='.')
            for(auto t:root->children)
                if(help(t.second,l+1,r))return true;
        if(root->children.count(*l))return help(root->children[*l],l+1,r);
        return false;  
    }
};

/**
 * Your WordDictionary object will be instantiated and called as such:
 * WordDictionary* obj = new WordDictionary();
 * obj->addWord(word);
 * bool param_2 = obj->search(word);
 */

作者:bestxuan
链接:https://leetcode-cn.com/problems/add-and-search-word-data-structure-design/solution/zi-dian-shu-dai-ma-jian-dan-by-bestxuan/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

212. 单词搜索 II

class Solution {
public:
    vector<vector<char>> m_board;
    int m;
    int n;
    bool dfs(string word,int i ,int j,int k,int len)
    {
        if(k==len)return true;
        if(i<0 || i>= m || j<0 || j>= n || word[k]!=m_board[i][j] || m_board[i][j]=='0')return false;
        auto temp = m_board[i][j];m_board[i][j]='0';
        bool b = false;
        b = dfs(word,i+1,j,k+1,len)||dfs(word,i,j+1,k+1,len)||dfs(word,i-1,j,k+1,len)||dfs(word,i,j-1,k+1,len);
        m_board[i][j]=temp;
        return b;
    }
    bool func(string word)
    {
        for(int i = 0 ;i<m;i++)
        {
            for(int j = 0 ;j<n;j++)
            {
                if(m_board[i][j]==word[0] && dfs(word,i,j,0,word.size()))return true;
            }
        }
        return false;
    }
    vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
        m = board.size();
        n = board[0].size();
        m_board = board;
        vector<string> res;
        for(auto w:words)
        {
            if(func(w))res.push_back(w);
        }
        return 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]);

    }
};

214. 最短回文串

class Solution {
public:
    vector<int> func(string s)
    {
        vector<int> res;
        int i = 0,len = s.size();
        while(i<len)
        {
            int j = i;
            while(i<len && s[i]!='.')i++;
            string s1 = s.substr(j,i-j);
            int k = 0, l = s1.size();
            while(k<l-1 && s1[k]=='0')k++;
            string s2 = s1.substr(k,l-k);
            res.push_back(stoi(s2));
			i++;
        }
        return res;
    }
	
    bool isok(string s,int i,int j,int len)
    {
        if(i<0)return true;
        while(i>=0 && j<len)
        {
            if(s[i]==s[j]){i--;j++;}
            else break;
        }
        return i==-1;
    }
    string shortestPalindrome(string s) {
        if(s.empty())return s;
        int len = s.size();
        int mid = len/2;
		int b = -1;
		while (mid >= 0)
		{
            if (isok(s, mid - 1, mid + 1, len)) { b = 2; break; }
			if (isok(s, mid - 1, mid, len)) { b = 1; break; }
            mid--;
        }
		if (b == 1)
		{
			string res(s.begin() + mid, s.end());
			auto res1 = res;
			reverse(res.begin(), res.end());
			return res + res1;
		}
		else
		{
			string res(s.begin()+mid+1,s.end());
			auto res1 = res;
			reverse(res.begin(),res.end());
			return res + s[mid] + res1;
		}
    }
};

215. 数组中的第K个最大元素

( 关 于 堆 的 使 用 ) \color{red}(关于堆的使用) (使)

1.直接使用优先队列priority_queue
class Solution {
public:


    int findKthLargest(vector<int>& nums, int k) {
        priority_queue<int> heap;
        for(auto n:nums)
        {
            heap.push(n);
        }
        int count = 0;
        while(count++<k-1)
        {
            heap.pop();    
        }
        return heap.top();
    }
};
2.使用N的堆排序
class Solution {
public:
    void adjust(vector<int>& nums,int root,int len)
    {
        int left = 2*root+1;
        int right = 2*root+2;
        int maxid = root;
        if(left< len && nums[left]>nums[maxid])maxid = left;
        if(right<len && nums[right]>nums[maxid])maxid=right;
        if(maxid!=root)
        {
            swap(nums[root],nums[maxid]);
            adjust(nums,maxid,len);
        }
    }
    void headsort(vector<int>& nums,int len)
    {
        for(int i = len/2-1;i>=0;i--)
        {
            adjust(nums,i,len);
        }
        for(int i = len-1;i>=0;i--)
        {
            swap(nums[0],nums[i]);
            adjust(nums,0,i);
        }

    }
    int findKthLargest(vector<int>& nums, int k) {
        headsort(nums,nums.size());
        return nums[nums.size()-k];
    }
};
3.使用N的快速排序
class Solution {
public:
    void func(vector<int>& nums,int left,int right)
    {
        if(left>=right)return;
        int i = left;
        int j = right;
        while(i<j)
        {
            while(i<j && nums[j]>=nums[left])j--;
            while(i<j && nums[i]<=nums[left])i++;
            if(i<j)swap(nums[i],nums[j]);
        }
        swap(nums[left],nums[i]);
        func(nums,left,i-1);
        func(nums,i+1,right);
    }
    void quicksort(vector<int>& nums)
    {
        int len = nums.size();
        func(nums,0,len-1);
    }
    int findKthLargest(vector<int>& nums, int k) {
        quicksort(nums);
        return nums[nums.size()-k];
    }
};
( 4. t o p K 的 堆 ) \color{red}(4.top K的堆) (4.topK)
class Solution {
public:
    void adjust(vector<int>& nums,int index,int len)
    {
        int left = 2*index +1;
        int right = 2*index +2;
        int maxid = index;
        if(left<len && nums[left]>nums[maxid])maxid = left;
        if(right<len && nums[right]>nums[maxid])maxid = right;
        if(maxid!=index)
        {
            swap(nums[maxid],nums[index]);
            adjust(nums,maxid,len);
        }
    }
    void heapsort(vector<int>& nums)
    {
        int len = nums.size();
        for(int i=len/2-1;i>=0;i--)
        {
            adjust(nums,i,len);
        }
    }
    int findKthLargest(vector<int>& nums, int k) {
        heapsort(nums);
        int len = nums.size();
        for(int i =len-1;i>len-k;i--)//提取的方式改变了
        {
            swap(nums[0],nums[i]);
            adjust(nums,0,i);
        }
        return nums[0];
    }
};
( 快 速 随 机 选 择 排 序 ) \color{red}(快速随机选择排序) ()
    int func(vector<int>& nums,int left,int right)
    {//以nums[left]为基准分两个part,中点为i
        int i = left;
        int j = right;
        while (i < j)
        {
            while (i<j && nums[j]>=nums[left])j--;
            while (i<j && nums[i]<=nums[left])i++;
            if (i < j)swap(nums[i],nums[j]);
        }
        swap(nums[i],nums[left]);
        return i;
    }
    int select(vector<int>& nums, int left, int right, int target)
    {
        if (left >= right)return nums[left];
        int cur = func(nums, left, right);
        if (cur == target)return nums[cur];
        else if (target < cur)return select(nums, left, cur - 1, target);
        else return select(nums,cur + 1,right,target);
        return 0;
    }
    int findKthLargest(vector<int>& nums, int k) {
        return select(nums,0,nums.size()-1,nums.size()-k);
    }

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

dfs

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

217. 存在重复元素

class Solution {
public:
    bool containsDuplicate(vector<int>& nums) {
        unordered_set<int> st(nums.begin(),nums.end());
        return st.size()!=nums.size();
    }
};
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,set<int>> mp;
        for(int i =0;i<nums.size();i++)
        {
            if(mp.count(nums[i])==0)
            {
                mp[nums[i]].insert(i);
            }
            else
            {
                if(i-*(--mp[nums[i]].end())<=k)return true;
                mp[nums[i]].insert(i);
            }
        } 
        return false;
    }
};
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;
    }
};

220. 存在重复元素 III

class Solution {
public:
    bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
        unordered_map<long long,vector<long long>> mp;
        for(int i = 0;i<nums.size();i++)
        {
            mp[nums[i]].push_back(i);
        }
        for(auto iter=mp.begin();iter!=mp.end();iter++)
        {
            auto temp = *iter;
            vector<long long> vt; 
            for(long long i = temp.first;i<=temp.first+t;i++)
            {
                               
                if(mp.count(i)!=0)
                {
                    vt.insert(vt.end(),mp[i].begin(),mp[i].end());
                }
            }
            sort(vt.begin(),vt.end());
            for(int i = 1;i<vt.size();i++)
            {
                if(vt[i]-vt[i-1]<=k)return true;
            }
        }
        return false;
    }
};

221. 最大正方形

class Solution {
public:
    int maximalSquare(vector<vector<char>>& matrix) {
        if(matrix.empty())return 0;
        int res = 0; 
        for(int i =0;i<matrix.size();i++)
        {
            if(matrix[i][0]=='1')
            {
                res = 1;break;
            }
        }
        for(int i = 0 ; i<matrix[0].size();i++)
        {
            if(matrix[0][i]=='1')
            {
                res = 1;break;
            }
        }
        for(int i = 1;i<matrix.size();i++)
        {
            for(int j = 1;j<matrix[0].size();j++)
            {
                if(matrix[i-1][j-1]>='1' && matrix[i-1][j]>='1' && matrix[i][j-1]>='1'&& matrix[i][j]>='1')
                {
                    matrix[i][j]=min(matrix[i-1][j-1]-'0',min(matrix[i-1][j]-'0',matrix[i][j-1]-'0'))+1+'0';
                }
                res = max(res,(int)pow(matrix[i][j]-'0',2));
            }
        }
        return res;
    }
};
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:
    void func(stack<string>& stt)
    {
            while(stt.size()>1)
        {
            auto temp = stt.top();stt.pop();
            auto temp1 = stt.top();//+ -
            if(temp1 == "+")
            {
                stt.pop();
                auto temp2 = stt.top();stt.pop();
                stt.push(to_string(stoi(temp2)+stoi(temp)));
            }
            else if(temp1=="-")
            {
                stt.pop();
                auto temp2 = stt.top();stt.pop();
                stt.push(to_string(stoi(temp2)-stoi(temp)));
            }
            else if(temp1=="(")
            {
                stt.push(temp);
                break;
            }
        }
    }
    int calculate(string s) {
        vector<string> st;
        int i =0;
        while(i<s.size())
        {
            if(i<s.size() && s[i]==' ')
            {
                while(i<s.size() && s[i]==' ')i++;
            }
            else if(i<s.size() && s[i]>='0' && s[i]<='9')
            {
                string temp = "";
                while(i<s.size() && s[i]>='0' && s[i]<='9')temp += s[i++];
                st.push_back(temp);
            }
            else
            {
                string temp ="";
                temp += s[i++];
                st.push_back(temp);
            }
        }
        stack<string> stt;
        i = 0;
        while(i<st.size())
        {
            if(st[i]=="(")stt.push(st[i]);
            else if(st[i]==")")
            {
				auto temp = stt.top(); stt.pop();//int
				auto temp1 = stt.top(); stt.pop();	//(
				stt.push(temp);
				func(stt);
            }
            else if( st[i]=="+" || st[i]=="-")
            {
                stt.push(st[i]);
            }
            else
            {
                if(stt.empty()){stt.push(st[i++]);continue;}
                stt.push(st[i]);
				func(stt);
            }
            i++;
        }
		func(stt);
        auto temp = stt.top();
        return stoi(temp);
    }
};
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

class Solution {
public:
    int calculate(string s) {
        vector<string> vt;
        int i = 0,len = s.size();
        while(i<len)
        {
            if(s[i]==' ')
            {
                while(i<len && s[i]==' ')i++;
            }
            else if(s[i]>='0' && s[i]<='9')
            {
                string temp = "";
                while(i<len && s[i]>='0' && s[i]<='9')temp += s[i++];
                vt.push_back(temp);
            }
            else
            {
                string temp = "";
                temp += s[i++];
                vt.push_back(temp);
            }
        }
        i=0;len = vt.size();
        vector<string> vt1;
        while(i<len)
        {
            if(vt[i]=="*"||vt[i]=="/"||vt[i]=="+"||vt[i]=="-")
            {
                vt1.push_back(vt[i]);
            }
            else
            {
				if (vt1.empty()) { vt1.push_back(vt[i]); continue; }
                auto sign = vt1.back();
                if(sign=="+"||sign=="-"){vt1.push_back(vt[i]);}
                else if(sign=="*")
                {
                    vt1.pop_back();
					auto temp = vt1.back(); vt1.pop_back();
                    vt1.push_back(to_string(stoi(temp)*stoi(vt[i])));
                }
                else if(sign=="/")
                {
                    vt1.pop_back();
					auto temp = vt1.back(); vt1.pop_back();
                    vt1.push_back(to_string(stoi(temp)/stoi(vt[i])));
                }
            }
            i++;
        }
        i=0;len = vt1.size();
        vector<string> vt2;
        while(i<len)
        {
            if(vt1[i]=="+"||vt1[i]=="-")
            {
                vt2.push_back(vt1[i]);
            }
            else
            {
				if (vt2.empty()) { vt2.push_back(vt1[i++]); continue; }
                auto sign = vt2.back();
                vt2.pop_back();
                if(sign=="+")
                {
                    auto temp = vt2.back();vt2.pop_back();
                    vt2.push_back(to_string(stoi(temp)+stoi(vt1[i]))); 
                }
                else
                {
                    auto temp = vt2.back();vt2.pop_back();
                    vt2.push_back(to_string(stoi(temp)-stoi(vt1[i])));                     
                }
            }
            i++;
        }
        return stoi(vt2[0]);
    }
};

228. 汇总区间

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

class Solution {
public:
    vector<string> summaryRanges(vector<int>& nums) {
        vector<string> res;
        int len = nums.size();
        int i = 0;
        while(i<len-1)
        {
            if(nums[i]+1==nums[i+1])
            {
                int start = nums[i];
                while(i<len-1 && nums[i]+1==nums[i+1])i++;
                int end = nums[i++];
                string temp = "";
                temp += to_string(start) + "->" + to_string(end);
                res.push_back(temp);
            }
            else
            {
                res.push_back(to_string(nums[i++]));
            }
        }
        if(i==len-1)res.push_back(to_string(nums.back()));
        return res;
    }
};

229. 求众数 II

最后要对这两个数进行遍历检验

class Solution {
public:
    vector<int> majorityElement(vector<int>& nums) {
        if(nums.size()==1 || nums.size()==0)return nums;
		if (nums.size() == 2)
		{
			if (nums[0] == nums[1])return {nums[1]};
			else return nums;
		}
        pair<int,int> n1 = make_pair(nums[0],1),n2 = make_pair(nums[0],1);
        for(int i =1;i<nums.size();i++)
        {
            if(nums[i]==n1.first)
            {
                n1.second++;
            }
            else if(nums[i]==n2.first)
            {
                n2.second++;
            }
            else if(n1.second==0)
            {
                n1.first = nums[i];
                n1.second=1;
            }
            else if(n2.second==0)
            {
                n2.first = nums[i];
                n2.second = 1;
            }
            else
            {
                n1.second--;
                n2.second--;
            }
        }
        vector<int> res;
        int x = n1.first,y=n2.first;
        int c1 = 0, c2 = 0;
        for(auto& n:nums)
        {
            if(n==x)c1++;
            else if(n==y)c2++;
        }
        if(c1>nums.size()/3)res.push_back(x);
        if(c2>nums.size()/3)res.push_back(y);
        return res;

    }
};

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

/**
 * 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:
    int kthSmallest(TreeNode* root, int k) {
        if(!root)return 0;
        vector<int> res;
        stack<TreeNode*> qt;
        auto cur = root;
        while(!qt.empty() || cur)
        {
            while(cur)
            {
                qt.push(cur);
                cur = cur->left; 
            }
            cur = qt.top();qt.pop();
            res.push_back(cur->val);
            cur = cur->right;
        }
        return res[k-1];
    }
};
/**
 * 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 false;
        return (n&(n-1))==0;
    }
};
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:
    stack<int> input,output;
    /** 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 res;
        if(output.empty())
        {
            while(!input.empty())
            {
                output.push(input.top());input.pop();
            }
            res = output.top();output.pop();
            return res;
        }
        else
        {
            res = output.top();output.pop();
            return res;
        }
    }
    
    /** Get the front element. */
    int peek() {
        int res;
        if(output.empty())
        {
            while(!input.empty())
            {
                output.push(input.top());input.pop();
            }
            res = output.top();
            return res;
        }
        else
        {
            res = output.top();
            return res;
        }        
    }
    
    /** Returns whether the queue is empty. */
    bool empty() {
        return input.empty() && output.empty();
    }
};

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

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 || !head->next)return true;
        auto head1 = new ListNode(0);
        head1->next = head;
        auto fast=head1,slow=head1;
        while(fast && fast->next)
        {
            slow = slow->next;
            fast = fast->next->next;
        }
        auto temp = slow->next;
        vector<int> left,right;
        while(temp)
        {
            left.push_back(head->val);
            right.push_back(temp->val);
            head = head->next;
            temp = temp->next;
        }
        reverse(right.begin(),right.end());
        return left==right;

    }
};

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)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        auto dp1 = nums;
        auto dp2 = nums;
        for(int i = 1;i<nums.size();i++)
        {
            dp1[i] *= dp1[i-1];
        }
        for(int i=nums.size()-2;i>=0;i--)
        {
            dp2[i] *= dp2[i+1];
        }
        auto res = nums;
        for(int i = 0;i<nums.size();i++)
        {
            if(i==0)res[i]=dp2[i+1];
            else if(i==nums.size()-1)res[i]=dp1[i-1];
            else res[i]=dp1[i-1]*dp2[i+1];
        }
        return res;
    }
};

239. 滑动窗口最大值

deque

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        deque<int> qt;
        qt.push_back(nums[0]);
        for(int i = 1;i<k;i++)
        {
            if(nums[i]<=qt.back())qt.push_back(nums[i]);
            else
            {
                while(!qt.empty() && qt.back()<nums[i])qt.pop_back();
                qt.push_back(nums[i]);
            }
        }
        vector<int> res;
        res.push_back(qt.front());
        int start = 0;
        int end = k;
        for(int i =1;i<=nums.size()-k;i++)
        {
            if(nums[end]<qt.back())
            {
                qt.push_back(nums[end]);
            }
            else
            {
                while(!qt.empty() && qt.back()<nums[end])qt.pop_back();
                qt.push_back(nums[end]);                
            }
            if(nums[start]==qt.front())qt.pop_front();
            res.push_back(qt.front());
            start++;
            end++;
        }
        return res;
    }
};

deque

    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;
    }
};

241. 为运算表达式设计优先级

题目里有的运算级一样的视为相同的次序,所以用全排列并不符合这道题的题意,但是这种字符串的处理方式是有一定意义的

class Solution {
public:
    int func(vector<string> board,vector<int> pos)
    {
        int res = 0;
        for(int i = 0;i<pos.size();i++)
        {
            int left = pos[i]-1;
            int right = pos[i]+1;
            while(left>=0 && board[left]=="")left--;
            while(right<board.size() && board[right]=="")right++;
			if (board[pos[i]] == "+") { board[pos[i]] = to_string(stoi(board[left]) + stoi(board[right])); }
            else if(board[pos[i]]=="-")board[pos[i]] = to_string(stoi(board[left])-stoi(board[right]));
            else if(board[pos[i]]=="*")board[pos[i]] = to_string(stoi(board[left])*stoi(board[right]));
            else if(board[pos[i]]=="/")board[pos[i]] = to_string(stoi(board[left])/stoi(board[right]));
            for(int j = left;j<=right;j++)
            {
                if(j!=pos[i])board[j]="";
            }
        }
        for(auto& x:board)
        {
            if(x!="")return stoi(x);
        }
        return INT_MAX;
    }
    vector<int> diffWaysToCompute(string input) {
        string s = input;
        vector<string> board;
        vector<int> pos;
        int i=0;
        while(i<s.size())
        {
            if(s[i]=='+'||s[i]=='-'||s[i]=='*'||s[i]=='/')
            {
                pos.push_back(board.size());
                string temp = "";
                temp += s[i++];
                board.push_back(temp);
            }
            else
            {
                string temp = "";
                while(i<s.size() && s[i]>='0' && s[i]<='9')
                {
                    temp += s[i++];
                }
                board.push_back(temp);
            }
        }
        vector<int> res;
        res.push_back(func(board,pos));
        while(next_permutation(pos.begin(),pos.end()))
        {
            res.push_back(func(board,pos));
        }
        return res;
    }
};

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;
    }
};

257. 二叉树的所有路径

/**
 * 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 {
private:
vector<vector<int> > r;
vector<int> path;
public:
    void dfs(TreeNode* root)
    {
        if(!root->left && !root->right) 
        {           
            path.push_back(root->val);
            r.push_back(path);
            path.pop_back();
            return;
        }
        if(root->left)
        {
            path.push_back(root->val);
            dfs(root->left);
            path.pop_back();
        }
        if(root->right)
        {
            path.push_back(root->val);
            dfs(root->right);
            path.pop_back();
        }
    }
    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> res;
        if(!root)return res;
        dfs(root);
        for(auto i:r)
        {
            string s;
            for(auto j:i)
            {
                s = s + to_string(j)+"->";
            }
            s.pop_back();
            s.pop_back();
            res.push_back(s);
        }
        return res;
    }
};

258. 各位相加

class Solution {
public:
    int addDigits(int num) {
        string s=to_string(num);
        while(s.size()>1)
        {
            int temp = 0;
            for(auto s1:s)
            {
                temp += s1-'0';
            }
            s = to_string(temp);
        }
        return stoi(s);
    }
};

260. 只出现一次的数字 III

class Solution {
    public int[] singleNumber(int[] nums) {
        // 方式二:异或 + &  如果异或还不太懂的可以先看下相关的几个题目先把异或搞懂先
        // 第一步:所有数异或,所有数异或之后的值就是两个只出现一次的数a,b异或后的值s。
        // 第二步:那我们用s & (-s) 可以得出s最低位(也就是最右边)为1的bit位(这个操作不太会事先知道)对应的数k,
        //         这里有一个很关键点就是:这个为1的bit位肯定只来之a.b其中的一个数字中的对应二进制位的1,这里有点卡主理解,比如我们把数字转成二进制运算看下:
        //         a:1 -> 0001
        //         b:2 -> 0010  => 0011. 不全为1的bit为进行异或操作就为1,这是异或的基本流程,然后我们操作s & (-s)之后得到的是0001,可以看到这个1是来之数字a的
        // 第三步:我们得到s&(-s)之后在对所有数进行&操作的话,就意味着可以将a和b区分在0和1的两个组,至于其他的数字如果相同的数字自然会分到一个组,可以用纸笔写下整个过程
        // 第四步:经过第三步之后就变成了只有一个数字存在一个其他都存在两个的数组(也就变成题目:136. 只出现一次的数字),
        //         然后我们分别对两个组的所有数字再进行异或之后不就得到了要求的那两个数了嘛。
        int s = 0;//0^0=0,0^其他=其他
        for (int num : nums){ // 第一步
            s ^= num;
        }

        int k = s & (-s); // 第二步

        int[] result = new int[2];
        for (int num : nums){
            if ((num & k) == 0){ // 第三第四步
                result[0] ^= num;
            }else{
                result[1] ^= num;
            }
        }

        return result;
        // 方式一:利用hash记录个数,但是空间复制度不满足,或者排序但是时间复杂度度不满足
    }
}

作者:tuo-jiang-de-ye-ma-2
链接:https://leetcode-cn.com/problems/single-number-iii/solution/huo-xu-wo-de-ti-jie-ke-yi-kan-dong-yi-huo-kan-zhu-/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

263. 丑数

    bool isUgly(int num) {
        if(num<1)return false;
        while(num%2==0)num = num/2;
        while(num%3==0)num = num/3;
        while(num%5==0)num = num/5;
        return num==1;

    }

264. 丑数 II

class Solution {
public:
    int nthUglyNumber(int n) {
        vector<int> dp(n, 0);
        dp[0] = 1;
        int p2 = 0, p3 = 0, p5 = 0;
        for(int i = 1; i < n; i ++){
            dp[i] = min(min(dp[p2]*2, dp[p3]*3), dp[p5]*5);
            if(dp[i] == dp[p2]*2) p2++;
            if(dp[i] == dp[p3]*3) p3++;
            if(dp[i] == dp[p5]*5) p5++;
        }
        return dp[n - 1];
    }
};

作者:yizhe-shi
链接:https://leetcode-cn.com/problems/ugly-number-ii/solution/c-onjie-fa-by-yizhe-shi-2/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

268. 缺失数字

class Solution {
public:
    int missingNumber(vector<int>& nums) {
		auto iter = find(nums.begin(),nums.end(),0);
		int n = nums.size();
		if (iter == nums.end())return 0;
		else
		{
			int temp = iter - nums.begin();
			nums[temp] = n;
		}
        
        for(int i = 0 ; i <n;i++)
        {
			if (abs(nums[i]) >= n)continue;
            if(nums[i]<0)
            {
                nums[-nums[i]] = 0- nums[-nums[i]];
            }
            else if(nums[i]<n)
            {
                nums[nums[i]]=-nums[nums[i]];
            }
        }
        int res = -1;
        for(int i = 1;i<n;i++)
        {
            if(nums[i]>0)
            {
                res = i;
                break;
            }
        }
        return res==-1? n : res;
    }
};

269. 火星词典(拓补排序)

class Solution {
public:
string alienOrder(vector<string> words) {
	unordered_map<char, vector<char>> mp;
	unordered_map<char, int> level;
	set<pair<char, char>> st;
    for(int  i = 0;i<words.size()-1;i++)
    {
        auto s1 = words[i];
        auto s2 = words[i+1];
        int k1 = 0,k2=0;
        while(k1<s1.size() && k2<s2.size())
        {
            if(s1[k1]!=s2[k2])
            {
                st.insert(make_pair(s1[k1],s2[k2]));break;
            }
            k1++;k2++;
        }
    }
	for (int i = 0; i < words.size() - 1; i++)
	{
		for (int j = i + 1; j < words.size(); j++)
		{
			if (words[i][0] != words[j][0])
			{
				st.insert(make_pair(words[i][0], words[j][0]));
			}
		}
	}
	for (auto&s : st)
	{
		level[s.second]++;
		mp[s.first].push_back(s.second);
		if (level[s.first] == 0) {}
	}
	queue<char> qt;
	for (auto&l : level)
	{
		if (l.second == 0)
		{
			qt.push(l.first);
		}
	}
	vector<int> res;
	while (!qt.empty())
	{
		int len = qt.size();
		for (int i = 0; i < len; i++)
		{
			auto temp = qt.front(); qt.pop();
			res.push_back(temp);
			for (auto&t : mp[temp])
			{
				if (--level[t] == 0)qt.push(t);
			}
		}
	}
	string r;
	for (auto&i : res)r += i;
	return r;

}
};

273. 整数转换英文表示

class Solution {
public:
    string small[20] = {"","One","Two","Three","Four","Five","Six","Seven",//0-19
                        "Eight","Nine","Ten","Eleven","Twelve","Thirteen",
                        "Fourteen","Fifteen","Sixteen","Seventeen","Eighteen","Nineteen"};
    string decade[10] = {" "," ","Twenty","Thirty","Forty","Fifty","Sixty",//20-90
                        "Seventy","Eighty","Ninety"};
    string big[4] = {"Billion","Million","Thousand","Hundred"};//1000000000,1000000,1000
    string func2(string s)
    {
		if (stoi(s) == 0)return "";
		string res = "";
        if(stoi(s)<20)res += small[stoi(s)];
        else 
        {
            res = decade[s[0]-'0'] +" " + small[s[1]-'0'];
            if(res.back()==' ')res.pop_back();
        }
        return res;
    }
    string Hundred(string s)
    {
        if(stoi(s)==0)return "";
        if(s.size()==3)
        {
			string temp = s.substr(s.size()-2,2);
			s.erase(s.end()-2,s.end());
			if (s[0] == '0')return func2(temp);
			if (stoi(temp) == 0)return small[s[0] - '0'] + " " + big[3];
			return  small[s[0]-'0'] +" " + big[3] + " " + func2(temp);
        }
        else if(s.size()==2)
        {
            return func2(s);
        }
        return small[s[0]-'0'];
    }
    string Thousand(string s)
    {
        string temp = s.substr(s.size()-3,3);
		s.erase(s.end()-3,s.end());
        if(stoi(s)==0)return Hundred(temp);
        else return Hundred(s) +" " +  big[2] +" " +  Hundred(temp);
    }
    string Million(string s)
    {
        if(stoi(s)==0)return "";
        string temp = s.substr(s.size()-6,6);
        s.erase(s.end()-6,s.end());
        if(stoi(s)==0)return Thousand(temp);
        else return Hundred(s) +" " + big[1] +" " + Thousand(temp);
    }
    string Billion(string s)
    {
        string temp = s.substr(s.size()-9,9);
        s.erase(s.end()-9,s.end());
        if(stoi(s)==0)return Million(temp);
        else return Hundred(s) +" " + big[0] +" " + Million(temp);        
    }
    string numberToWords(int num) {
        if(num==0) return "Zero";
        string nums = to_string(num);
        string res = "";
        int len = nums.size();
        if(len<=3)res =  Hundred(nums);
        else if(len<=6)res =  Thousand(nums);
        else if(len<=9)res= Million(nums);
        else res =  Billion(nums);
        if(res.back()==' ')res.pop_back();
        return res;
    }
};

274. H 指数

思路必须要清楚

class Solution {
public:
    int hIndex(vector<int>& citations) {
        if(citations.empty())return 0;
        sort(citations.begin(),citations.end());
        for(int i = citations.back();i>=0;i--)
        {
            int t = lower_bound(citations.begin(),citations.end(),i)-citations.begin();
            if(citations.size() - t >= i){return i;}
        }
        return 0;
    }
};

275. H指数 II

素组有序,让我们在O(log n)的时间内完成计算。看到这个时间复杂度,应该有很敏锐的意识应该用二分查找法,我们最先初始化left和right为0和数组长度len-1,然后取中间值mid,比较citations[mid]和len-mid做比较,如果前者大,则right移到mid之前,反之right移到mid之后,终止条件是left>right,最后返回len-left即可。
————————————————
版权声明:本文为优快云博主「pushup8」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/pushup8/article/details/85200248
里面特殊情况总是判断不清楚,对这个h定义比较模糊

class Solution {
public:
    int hIndex(vector<int>& nums) {
        int n = nums.size(), low = 0, high = n - 1, mid = 0;
        while(low <= high){
            mid = low + (high - low) / 2;
            int target = n - mid;
            if(nums[mid] < target) low = mid + 1;
            else if(nums[mid] > target) high = mid - 1;
            else return n - mid;
        }
        return n - low;
    }
};
class Solution {
public:
    bool judge(vector<int> citations, int mid)
    {
        int temp = lower_bound( citations.begin(),citations.end(),mid) -citations.begin();
        return citations.size()-temp >= mid;
    }
    int hIndex(vector<int>& citations) {
        int len = citations.size();
        if(len==0)return len;
        int left = 0,right = citations.back();
        while(left<=right)
        {
            int mid=left +(right-left)/2;
            if(judge(citations, mid))
            {left=mid+1;}
            else
            {right=mid-1;}
        }
        return left>=1?left-1:0;
    }
};

278. 第一个错误的版本(二分法)

并不是mid值一定要加1,不同的情况不一样

// The API isBadVersion is defined for you.
// bool isBadVersion(int version);

class Solution {
public:
    int firstBadVersion(int n) {
       long left = 1;
       long right = n;
       while(left<right)
       {
           long mid= (left+right)/2;
           if(isBadVersion(mid))
           {
               right = mid;
           }
           else
           {
                left = mid+1;
           }
       } 
       return left;
    }
};

279. 完全平方数

class Solution {
public:
    int numSquares(int n) {
        vector<int> dp(n+1,1);
        dp[0]=0;
        for(int i = 1;i<=n;i++)
        {
            int m = INT_MAX;
            for(int j=1;j*j<=min(i,n);j++)
            {
                m = min(m,dp[i-j*j]+1);
            }
            dp[i] = m;
        }
        return dp[n];
    }
};

282. 给表达式添加运算符

易出错点:1.溢出所以stoi改成stoll 2.使用数组记录没必要,所以传上一个值使用pre变量 3.字符串中可以连着用而不是必须拆开 3.在拆字符串时容易出现05“这种情况,要对这种特殊情况进行验证

class Solution {
public:
    vector<vector<string>> res;
    vector<string> sign;
    void dfs(string num, long long p, long long sum,long long target,long long pre)
    {
		if (p == num.size())
		{
			if (sum == target)res.push_back(sign);
			return;
		}
        for(long long i = p;i<num.size();i++)
        {
            auto curr = num.substr(p,i-p+1);
			if (curr.size()>1 && curr[0] == '0')continue;
			long cur = stoll(curr);
                
            sign.push_back("+");sign.push_back(to_string(cur));
            dfs(num,i+1,sum+cur,target,cur);
            sign.pop_back();sign.pop_back();

            if(sign.empty())continue;
            sign.push_back("-");sign.push_back(to_string(cur));
            dfs(num,i+1,sum-cur,target,-cur);
            sign.pop_back();sign.pop_back();

            sign.push_back("*");sign.push_back(to_string(cur));
            dfs(num,i+1,sum-pre + pre*cur,target,pre*cur);
            sign.pop_back();sign.pop_back();
        }
        
    }
    vector<string> addOperators(string num, int target) {
        dfs(num,0,0,target,0);
        vector<string> vt;
        for(auto&r:res)
        {
            string temp ="";
            for(auto&r1:r)temp = temp + r1;
            temp.erase(temp.begin());
            vt.push_back(temp);
        }
        return vt;
    }
};

283. 移动零

按照前后双指针的思路很快做出来,但是改变了顺序,不符合题目的要求

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int len = nums.size();
        int i = 0;
        int j = len -1;
        while(i<=j)
        {
            while(i<=j && nums[i]!=0)i++;
            while(i<j && nums[j]==0)j--;
            if(i<=j)
            {
                swap(nums[i++],nums[j--]);
            }
        }
        return;
    }
};

改一下双指针的遍历方式,两个都是从前往后遍历

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int len = nums.size();
        int i = 0;
        int j = 0;
        while(i<len)
        {
            while(i<len && nums[i]==0)i++;
            if(i<len)
            {
                swap(nums[i++],nums[j++]);
            }
        }
        return;
    }
};

287. 寻找重复数

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        for(auto&i:nums)
        {
            if(nums[abs(i)]<0)return abs(i);
            else nums[abs(i)]=-nums[abs(i)];
        }
        return 0;
    }
};

哈希和排序都不满足要求,这道题用链表有环的方法最好,一样的思路
本题要符合时间复杂度小于n2,空间复杂度1的话,官方解答的前两种方法都不满足,只有循环检测的方法能够满足,代码也非常简单。
但我认为官方解释没有写的非常完整,这里来试图写的完整一点。

首先,如果从nums[0]开始沿着下标的方式来走,如果没有重复的数字,可能可以走出一条线,因为不可能回到0,所以最后一个节点应该的值应该是n,而不存在索引号为n的节点(因为是从0开始),所以中断了,就退出了。

但是这里的情况是,存在重复的节点,所以这样沿着nums[0]走会发生什么呢?
首先,必定不可能回到0,因为没有值是0的节点,其次,不可能像刚刚一样中断。
这是为什么呢,因为要中断,必然需要节点的值大于最大的索引,但因为有重复,节点的最大值小于等于索引的最大值,所以没有办法中断,所以必定是在一个循环之中。

也就是通过这条路,走着走着进入了一个循环。
可以举个例子,[1,2,3,4,5,3]这样,也就是会 1-2-3-4-5-3-4-5-3-4-5……也就是3-4-5-3这部分陷入了循环,可以发现,重复的地方也就是循环的起始点,也就是3,因为这个3有2个不同的点到达了它,所以造成了循环,它也就是2条路的交叉口。

接下来,用乌龟和兔的方法,假如乌龟一次走1步,兔一次走2步。

所有的情况都可以抽象成先经过i个节点到达重复节点,再进入到长度为S的循环圈中。

那么,如果乌龟和兔同时出发,他们会在哪里相遇呢?
一定是在这个圈中的某点,因为兔的速度是2,乌龟是1,相对速度是1,所以兔子一定能追上乌龟,在圈里的某处。

当乌龟走了距离i到达圈起始点时,兔子已经走了2i,那么兔子相对于乌龟来说是多远呢?也就是i-kS,也就是去掉兔子额外走的k圈。

这时,还是兔子追乌龟,它需要追多远呢?应该是圈剩下的距离,也就是S-(i-ks),也就是(k+1)S-i,也就是乌龟再走这么久,会被追上,这个位置非常巧妙,可以发现这里再经过i就会回到圈的起点,这就让我们想到,在这个地方让另一个乌龟从起点爬起,当起点的乌龟爬到圈起始点时,刚好原来的乌龟也会达到圈起始点,这样就能够得到圈起始点了,也就是重复的元素。

作者:jie-ju-wei-ming-ming
链接:https://leetcode-cn.com/problems/find-the-duplicate-number/solution/xun-huan-jian-ce-fang-fa-xi-shuo-by-jie-ju-wei-min/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        
        int fast = 0, slow = 0;
        while(true){
            fast = nums[nums[fast]]; //相当于走两步
            slow = nums[slow];
            if(fast == slow)
                break;
        }
        int finder = 0; //新建一个慢指针重新回到起点开始走
        while(true){
            finder = nums[finder];
            slow = nums[slow];
            if(slow == finder)
                break;        
        }
        return slow;
    }
};

作者:zjczxz
链接:https://leetcode-cn.com/problems/find-the-duplicate-number/solution/kuai-man-zhi-zhen-de-jie-shi-cong-damien_undoxie-d/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

289. 生命游戏

1.注意代码的简化 2.可以不使用额外数组而是在原数组上用2 3表示原来的01但是又即将改变的

class Solution {
public:
    int func(vector<vector<int>>& board,int i, int j,int m,int n)
    {
        int count = 0;
        for(int x = i-1;x<=i+1;x++)
        {
            for(int y = j-1;y<=j+1;y++)
            {
                if(x==i && y==j)continue;
                if(x<0 || x==m || y<0 || y==n)continue;
                if(board[x][y]==1)count++;
            }
        }
        return count;
    }
    void gameOfLife(vector<vector<int>>& board) {
        int m = board.size();
        int n = board[0].size();
        vector<pair<int,int>> res;
        for(int i = 0 ; i<m;i++)
        {
            for(int j = 0 ; j<n;j++)
            {
                auto temp = func(board,i,j,m,n);
                if(temp==3 && board[i][j]==0)res.push_back(make_pair(i,j));
                if((temp>3||temp<2) && board[i][j]==1)res.push_back(make_pair(i,j));
            }
        }
        for(auto&p:res)
        {
            board[p.first][p.second]=1-board[p.first][p.second];
        }
        return;
    }
};

290. 单词规律

class Solution {
public:
    bool wordPattern(string pattern, string str) {
        int k = 0;
        unordered_map<char,string> mp1;
        unordered_map<string,char> mp2;
        int i = 0,len =str.size();
        while(i<len)
        {
            int j = i;
            while(i<str.size() && str[i]!=' ')i++;
            auto temp = str.substr(j,i-j);
            if(mp1.find(pattern[k])==mp1.end())mp1[pattern[k]]=temp;
            else 
            {
                if(mp1[pattern[k]]!=temp)return false;
            }  
            if(mp2.find(temp)==mp2.end())mp2[temp]=pattern[k];
            else
            {
                if(mp2[temp]!=pattern[k])return false;
            }
            i++;k++;          
        }
        return k==pattern.size();
    }
};

里面有几点:
1.从一段话中提取单词没有现成的函数,需要用空格为标志采用双指针法写一个
2.里面还有一个要求是不同的p中的字母对应的string不能一样,所以当要增加新的时候,要对之前进行遍历,防止之前已经有这个value了,再遍历哈希的时候,需要使用复杂的迭代器法

class Solution {
public:
bool wordPattern(string pattern, string str) {
	unordered_map<char, string> mp;
    unordered_map<char, string>::iterator iter;
	int len = str.size();
	int i = 0, j = 0;
	vector<string> ss;
	while (i < len)
	{
		if (str[i] != ' ')
		{
			i++;
		}
		else
		{
			ss.push_back(str.substr(j, i - j)); i++; j = i;
		}

	}
    ss.push_back(str.substr(j,i-j));
    
    len = pattern.size();
	if(ss.size()!=len)return false;
    for (int i = 0; i < len; i++)
	{
		if (mp.find(pattern[i]) == mp.end())
		{
            for(iter = mp.begin() ;iter!=mp.end();iter++)
            {if(iter->second==ss[i])return false;}
            mp[pattern[i]] = ss[i];
            
		}
		else
		{
			if (mp[pattern[i]] != ss[i])return false;
		}
	}
	return true;
}
};

292. Nim 游戏

class Solution {
public:
    bool canWinNim(int n) {
        return n%4!=0;
    }
};

295. 数据流的中位数

class MedianFinder {
public:
    priority_queue<int,vector<int>,less<int>> small;
    priority_queue<int,vector<int>,greater<int>> big;
    /** initialize your data structure here. */
    MedianFinder() {
    }
    
    void addNum(int num) {
        if(small.size()>=big.size())
        {
            small.push(num);
            big.push(small.top());
            small.pop();
        }
        else
        {
            big.push(num);
            small.push(big.top());
            big.pop();
        }
    }
    
    double findMedian() {
        if(small.size()==big.size())return (double)(small.top()+big.top())/2;
        else if(small.size()<big.size())return big.top();
        else return small.top();
    }
};

/**
 * Your MedianFinder object will be instantiated and called as such:
 * MedianFinder* obj = new MedianFinder();
 * obj->addNum(num);
 * double param_2 = obj->findMedian();
 */

297. 二叉树的序列化与反序列化

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Codec {
public:

    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        string ret;
        dfs(root,ret);
        return ret;
    }

    void dfs(TreeNode* root,string& ret){
        if(root == nullptr) {
            ret.append("#,");
            return;
        }

        ret.append(to_string(root->val)).append(",");//先序遍历
        dfs(root->left,ret);
        dfs(root->right,ret);

    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        int i = 0;
        return rdfs(data,i);
    }

    TreeNode* rdfs(const string& data,int& i){
        if(data[i] == '#') {
            i += 2;
            return nullptr;
        }

        int next = i;
        while(data[next] != ',')
            next++;
        int val = stoi(data.substr(i,next-i));
        auto ret = new TreeNode(val);
        i = next+1;

        ret->left = rdfs(data,i);
        ret->right = rdfs(data,i);

        return ret;
    }

};

// Your Codec object will be instantiated and called as such:
// Codec codec;
// codec.deserialize(codec.serialize(root));

作者:lcw_leetcode
链接:https://leetcode-cn.com/problems/serialize-and-deserialize-binary-tree/solution/xian-xu-bian-li-di-gui-kai-zhan-shi-jian-xiao-lu-h/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

299. 猜数字游戏

第一步的时候就可以把相同的统计出来,不同的和相同的不能一起统计

string getHint(string secret, string guess) {
    int acnt = 0;
    int bcnt = 0;
    unordered_map<char, int> um;
    for (int i = 0; i < secret.size(); i++) {
        um[secret[i]]++;
        acnt += (secret[i] == guess[i]);
    }
    for (auto& c : guess) {
        bcnt += (um[c]-- > 0);
    }
    bcnt -= acnt;
    return to_string(acnt) + "A" + to_string(bcnt) + "B";
}

作者:ikaruga
链接:https://leetcode-cn.com/problems/bulls-and-cows/solution/299-by-ikaruga/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值