leetcode刷题记录

一. 字符串和哈希函数章节

1.力扣

变位词组

思路:

//eat tea ate用sort排序后都是ate,用ate作key,其他[eat tea ate]做value。 //[eat tea ate]用一个vector装

看下auto的用法,map怎么添加值

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        //eat tea ate用sort排序后都是ate,用ate作key,其他[eat tea ate]做value。
        //[eat tea ate]用一个vector装
        map<string, vector<int>> mymap;
        int len = strs.size();
        for (int i = 0; i < len; ++i) {
            string tmpstr = strs[i];
            sort(tmpstr.begin(),tmpstr.end());
            mymap[tmpstr].push_back(i);
            //mymap.insert(map<string, vector<int>>::value_type(tmpstr, i));
        }
        vector<vector<string>> res;
        for (auto i : mymap) {
            vector<string> thisTime;
            auto index = i.second;
            for (auto i : index) {
                thisTime.push_back(strs[i]);
            }
            res.push_back(thisTime);
        }
        return res;
    }
};

2. 同构字符串  力扣

class Solution {
public:
    bool isIsomorphic(string s, string t) {
        //若两个字符串长度不同,返回false
        //建立两个Map,s一个map,t一个map,map里key是s和t的字符,value是对方s的相同位置字符,或者对方t的相同位置字符。题意要求是二者一一对应
        //同时遍历两个字符串,如果两个字符串的字符都没出现过,则同时记录到map里;若一个出现过另一个没出现过则返回false,若两个都出现过,则看他们对应的value是否是对方,不相等则返回false.
        int lens = s.size();
        int lent = t.size();
        if (lens != lent) {
            return false;
        }
        map<char, char> maps;
        map<char, char> mapt;
        for(int i = 0; i < lens; ++i) {
            if (maps.find(s[i]) == maps.end() && mapt.find(t[i]) == mapt.end()) {
                maps[s[i]] = t[i];
                mapt[t[i]] = s[i];
            }
            if(maps.find(s[i]) == maps.end() || mapt.find(t[i]) == mapt.end()) {
                return false;
            }
            if (maps[s[i]] != t[i] || mapt[t[i]] != s[i]) {
                return false;
            }
        }
        return true;
    }
};

3. 1816. 截断句子 力扣

class Solution {
public:
    void splitStr(string s, vector<string>& all, char ch = ' ') {
        int l = 0, r = 0, len = s.length();
        while (r < len) {
            while (r < len && s[r] != ch) {
                r++;
            }
            all.push_back(s.substr(l, r-l));
            l = ++r;
        }
    }  //C++里的spilt

    vector<string> res;
    string truncateSentence(string s, int k) {
        char tmp = ' ';
        splitStr(s, res, tmp);
        string ret;
        for(int i = 0; i < k; ++i) {
            ret += res[i];
            if (i == k - 1) {
                return ret;
            }
            ret += " ";
        }
        return ret;
    }
};

4. 判断子序列 力扣

class Solution {
public:
    bool isSubsequence(string s, string t) {
        int cur_s = 0;
        for (int i = 0; i < t.size(); ++i) {
            if (s[cur_s] == t[i]) {
                cur_s++;
            }
        }
        if (cur_s == s.size()) {
            return true;
        }
        return false;

    }
};

5. 389. 找不同   力扣

class Solution {
public:
    char findTheDifference(string s, string t) {
        /* 建立一个26个字母的哈希表,遍历s,每个字符的value减1,遍历t,每个字符的value加1,找出t中value是1 的字符。*/
        int len_s = s.size();
        vector<int> vec(26, 0);
        for (int i = 0; i < len_s; ++i) {
            vec[s[i] - 'a']--;
        }
        for(int i = 0; i < t.size(); ++i) {
            vec[t[i] - 'a']++;
            if (vec[t[i] - 'a'] == 1) {
                return t[i];
            }
        }
        return 'a';
    }
};

6. 647. 回文子串   力扣

暴力法+中心扩展法+动态规划

1. 暴力法

class Solution {
public:
    int countSubstrings(string s) {
        int count = 0;
        int len = s.size();
        if (len == 0) {
            return 0;
        }
        for (int i = 0; i < len; ++i) {
            for(int j = i; j < len; ++j) {
               bool flag = true;
               int start = i, end = j;
               while(start <= end) {
                   if (s[start++] != s[end--]) {
                     flag = false;
                   }
               }
               if (flag) {
                   count++;
               }
            }
        }
        return count;

    }
};

2. 中心扩展法

这是一个比较巧妙的方法,实质的思路和动态规划的思路类似。

比如对一个字符串 ababa,选择最中间的 a 作为中心点,往两边扩散,第一次扩散发现 left 指向的是 b,right 指向的也是 b,所以是回文串,继续扩散,同理 ababa 也是回文串。

这个是确定了一个中心点后的寻找的路径,然后我们只要寻找到所有的中心点,问题就解决了。

中心点一共有多少个呢?看起来像是和字符串长度相等,但你会发现,如果是这样,上面的例子永远也搜不到 abab,想象一下单个字符的哪个中心点扩展可以得到这个子串?似乎不可能。所以中心点不能只有单个字符构成,还要包括两个字符,比如上面这个子串 abab,就可以有中心点 ba 扩展一次得到,所以最终的中心点由 2 * len - 1 个,分别是 len 个单字符和 len - 1 个双字符。

如果上面看不太懂的话,还可以看看下面几个问题:

为什么有 2 * len - 1 个中心点?
aba 有5个中心点,分别是 a、b、c、ab、ba
abba 有7个中心点,分别是 a、b、b、a、ab、bb、ba
什么是中心点?
中心点即 left 指针和 right 指针初始化指向的地方,可能是一个也可能是两个
为什么不可能是三个或者更多?
因为 3 个可以由 1 个扩展一次得到,4 个可以由两个扩展一次得到

class Solution {
public:
    int countSubstrings(string s) {
        /* 中心扩散法 */
        int len = s.size();
        int count = 0;
        for(int i = 0; i < len; ++i) {
            int start = i;
            int end = i;
            while(start >=0 && end < len && s[start] == s[end]) {
                count++;
                --start;
                ++end;
            }
            start = i;
            end = i + 1;
            while(start >=0 && end < len && s[start] == s[end]) {
                count++;
                --start;
                ++end;
            }
        }
        return count;
    }
};

(2) 最长回文子串力扣

   中心扩展法 

class Solution {
public:
    string longestPalindrome(string s) {
        int size = s.size();
        int res = 1;
        if (size == 1 || size== 0) {
            return s;
        }
        int begin = 0;
        int tail = 0;
        for (int i = 0; i < size; ++i) {
            int start = i;
            int end = i;
            while(start >= 0 && end <= size - 1 && s[start] == s[end]) {
                if (end - start + 1 > res) {
                    res = end - start + 1;
                    begin = start;
                    tail = end;
                }
                start--;
                end++;
            }
        
            start = i;
            end = i + 1;
            while(start >= 0 && end <= size - 1 && s[start] == s[end]) {
                if (end - start + 1 > res) {
                    res = end - start + 1;
                    begin = start;
                    tail = end;
                }
                start--;
                end++;
            }
            
        }
        return s.substr(begin, res);
    }
};

7.  1592. 重新排列单词间的空格  力扣

注意对字符型char a = 'a'; 可以string str = ""; str+='a';

看下题解里有人讲的这种题的模板 力扣

class Solution {
public:
    string reorderSpaces(string text) {
        vector<string> vecStr;
        int spaceNum = 0;
        string tmp;
        int len = text.size();
        for(int i = 0; i < text.size(); ++i) {
            if (text[i] == ' ') {
                spaceNum++;
            }
            if (text[i] != ' ') {
               tmp += text[i];
            }
            if ((text[i] != ' ' && (i + 1) < text.size() && text[i + 1] == ' ') || (i == len - 1) && text[i] != ' ' ) {
               vecStr.push_back(tmp);
               tmp = "";
            }
        }
        int numStr = vecStr.size();
        int aver = 0;
        string res;
        string space = " ";
        int tailNum = 0;
        if (numStr != 1) {
             aver = spaceNum / (numStr - 1);
             tailNum = spaceNum - (numStr - 1) * aver;
             for (int i = 0; i < numStr - 1; ++i) {
                res += vecStr[i];
                for(int j = 1; j <= aver; ++j) {
                    res += space;
                }
             }
             res += vecStr[numStr - 1];
             for (int i = 1; i <= tailNum; ++i) {
                res += space;
             }
        } else {
            res += vecStr[0];
            for (int i = 1; i <= spaceNum; ++i) {
                res += space;
            }
        }
         return res;
    }
};

8.反转字符串中的单词 III   力扣

class Solution {
public:
    string reverseWords(string s) {
        string res;
        int len = s.size();
        string tmpStr;
        vector<string> vec;
        for(int i = 0; i < len; ++i) {
            if (s[i] != ' ') {
                tmpStr += s[i];
            } 
            if (s[i] == ' ') {
                vec.push_back(tmpStr);
                tmpStr = "";
            }
            if (i == len - 1) {
                vec.push_back(tmpStr);
                tmpStr = "";
            }
        }
        for(int i = 0; i < vec.size(); ++i) {
            reverse(vec[i].begin(), vec[i].end());
            res += vec[i];
            if (i != vec.size() - 1) {
                res += " ";
            }
        }
        return res; 
    }
};

9.   554 砌砖  力扣

class Solution {
public:
    int leastBricks(vector<vector<int>>& wall) {
        int rows = wall.size();
        int size = 0;
        /* for(int i = 0; i < wall[0].size(); ++i) {
            size += wall[0][i];
        }
        vector<int> myVec(size, 0); 
        [[100000000,100000000],[100000000,100000000]]
        如果用vector,这个用例会超时,因为会遍历0~200000000*/
        map<int, int> myMap;
        for (int m = 0; m < rows; ++m) {
            int sum = 0;
            for (int n = 0; n < wall[m].size()-1; n++) {
                sum += wall[m][n];
                myMap[sum]++;
            }      
        }
        int max = 0;
        map<int,int>::iterator iter = myMap.begin();
        for(; iter != myMap.end(); ++iter) {
            if (iter -> second > max) {
                max = iter -> second;
            }
        }
        return rows - max;
    }
};

10. 500. 键盘行   力扣

class Solution {
public:
    vector<string> findWords(vector<string>& words) {
        map<char, int> myMap;
        string str = "qwertyuiop";
        vector<string> res;
        for (int i = 0; i < str.size(); ++i) {
            myMap[str[i]] = 1; 
        }
        str = "asdfghjkl";
        for (int i = 0; i < str.size(); ++i) {
            myMap[str[i]] = 2; 
        }
        str = "zxcvbnm";
        for (int i = 0; i < str.size(); ++i) {
            myMap[str[i]] = 3; 
        }
        for(int i = 0; i < words.size(); ++i) {
            int tmpRow = myMap[tolower(words[i][0])];
            bool flag = true;
            for(int j = 1; j < words[i].size(); ++j) {
                if (myMap[tolower(words[i][j])] != tmpRow) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                res.push_back(words[i]);
            }
        }
        return res;
    }
};

11. 71. 简化路径  力扣

class Solution {
public:
    /* vector<string> res;
    遇到不是"/"的单词把他放用string tmp存放,如果tmp是..则res弹出最顶上的元素,
     如果是. 则什么也不做
    */
    string simplifyPath(string path) {
        int len = path.size();
        vector<string> strVec;
        string tmpStr;
        string res = "/";
        int i = 0;
        while (i < len) {
            while(path[i] == '/' && i < len) {
                i++;
            }
            while (path[i] != '/' && i < len) {
                tmpStr += path[i];
                i++;
            }
            if (tmpStr.size() > 0 && tmpStr != "." && tmpStr != "..") {
                strVec.push_back(tmpStr);
            }
            if (tmpStr == ".." && strVec.size() > 0) {
                strVec.pop_back();
            }
            tmpStr = "";
        }
        
        for(int i = 0; i < strVec.size(); ++i) {
           res += strVec[i];
           if (i < strVec.size() - 1) {
              res += "/";
           }
        }
        return res;
    }
};

二  链表篇

1 . 链表倒置 力扣

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        /* 
        if (head == nullptr|| head -> next == nullptr) {
            return head;
        }
        stack<ListNode*> st;
        ListNode* cur = head;
        while(cur) {
            st.push(cur);
            cur = cur -> next;
        }
        ListNode* ret = st.top();
        ListNode* res = st.top();
        st.pop();
        while (!st.empty()) {
             ret -> next = st.top();
             ret = ret -> next;
             st.pop();
        }
        ret -> next = nullptr;
        return res; */

    // 调用递推公式反转当前结点之后的所有节点
    // 返回的结果是反转后的链表的头结点
    /* 
    if (head == nullptr || head -> next == nullptr) {
        return head;
    }
    ListNode* newHead = reverseList(head->next);
    head->next->next = head;
    head->next = nullptr;
    return newHead;
    */
    if (head == nullptr || head -> next == nullptr) {
        return head;
    }
    ListNode* pre = nullptr;
    ListNode* now = head;
    ListNode* after;
    while (now) {
        after = now -> next;
        now -> next = pre;
        pre = now;
        now = after; 
    }
    return pre;

    }
};

2. 链表的m到n节点这段转置 力扣

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int left, int right) {
        /* 
        定位到要反转部分的头节点 2,head = 2;前驱结点 1,pre = 1;
当前节点的下一个节点3调整为前驱节点的下一个节点 1->3->2->4->5,
当前结点仍为2, 前驱结点依然是1,重复上一步操作。。。
1->4->3->2->5.
*/ //通过dummy->next来获得新链表的头结点
        ListNode* dummy=new ListNode(-1);
        ListNode* pre=dummy;
        dummy->next=head;
        //找到要翻转的起始节点
        for(int i=0;i<left-1;i++)
            pre=pre->next;
        //cur为当前节点
        ListNode* cur=pre->next;
        for(int i=left;i<right;i++){
            //t为临时节点
            ListNode* t=cur->next;
            cur->next=t->next;
            t->next=pre->next;
            pre->next=t;
        }
        return dummy->next;

    }
};

3. 找两个链表相交的节点 力扣

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
     /*   //把headA的节点依次加入set,再遍历B的所有节点,若B的节点的指针能在set里找到,就是这个节点
        set<ListNode*> setA;
        if(headA == nullptr || headB == nullptr) {
            return nullptr;
        }
        ListNode* curA = headA;
        while(curA != nullptr) {
            setA.insert(curA);
            curA = curA -> next;
        }
        ListNode* curB = headB;
        while(curB != nullptr) {
            if (setA.find(curB) != setA.end()) {
                return curB;
            }
            curB = curB -> next;
        }
        return nullptr;
        */
        

        //思路二,先计算两个链表长度,若长链表比短链表长x个节点。然后让长链表的指头节点的指针先走x长度,之后二者同时开始走,二者相遇的节点就是要找的
       if(headA == nullptr || headB == nullptr) {
            return nullptr;
        }
        int lenA = 0;
        int lenB = 0;
        ListNode* a = headA;
        ListNode* b = headB;
        ListNode* x = headA;
        ListNode* y = headB;
        while(x != nullptr) {
            x = x -> next;
            ++lenA;
        }
        while(y != nullptr) {
            y = y -> next;
            ++lenB;
        }
        if (lenA > lenB) {
            int x = lenA - lenB;
            while (a != nullptr && x > 0) {
                a = a -> next;
                x --;
            }
        }
        else if (lenA < lenB) {
            int x = lenB - lenA;
            while (b != nullptr && x > 0) {
                b = b -> next;
                x--;
            }
        }
        while (a && b) {
            if (a == b) {
                return a;
            }
            a = a -> next;
            b = b -> next;
        }
        return nullptr;
    }
};

(4)203. 移除链表元素  力扣

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
       /* if (!head) {
            return head;
        }
        ListNode* res = head;
        while(res != nullptr && res -> val == val) {
            res = res -> next;
        }
        if (res == nullptr) {
            return nullptr;
        }
        ListNode* cur = res;
        while(cur -> next) {
            if (cur ->next -> val == val) {
                cur -> next = cur -> next -> next;
            } else {
                cur = cur -> next;
            }
        }
        return res; */


        /* 递归 */
        if (head == nullptr) {
            return nullptr;
        }
        /* if (head -> val == val) {  //如果写再这里,对于7777  会直接返回结果777
            return head -> next;
        } */
        head -> next = removeElements(head -> next, val);
        if (head -> val == val) {  
            return head -> next;
        }

        return head;
    }
};

4. 环形链表找环的入口 力扣

法一:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        //遍历链表,将节点依次放入set容器,边放边查找是否有相同节点,要是找到相同的,这个节点就是结果
        set<ListNode*> setA;
        if (head == nullptr) {
            return nullptr;
        }
        ListNode* cur = head;
        while (cur) {
            if (setA.find(cur) == setA.end()) {
                setA.insert(cur);
                cur = cur ->next;
            }
            else {
                return cur;
            }
        }
        return nullptr;
        
    }
};

法二

//思路二,可以证明,若有环,则快慢指针(快的每次走两步,慢的每次走一步)必在环内某节点相遇,然后再找两个每次走一步的指针,分别从相///遇点和起点一步步的走,则二者相遇点就是环的起点
        if (head == nullptr) {
            return nullptr;
        }
        ListNode* slow = head;
        ListNode* fast = head;
        ListNode* meet = head;
        while(fast) {  //找相遇i点
            slow = slow -> next;
            fast = fast -> next;
            if (fast == nullptr) {
                return nullptr;
            }
            fast = fast -> next;
            if (fast == slow) {
                meet = fast;
                break;
            }
        }
        if (fast == nullptr) {
            return nullptr;
        }
        fast = meet;
        slow = head;
        while (slow != fast) {
            slow = slow -> next;
            fast = fast -> next;
        }
        return slow;
    }
};

5. 分割链表 力扣

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* partition(ListNode* head, int x) {
        //建立两个临时节点。遍历head,一个节点的右边放所有小于x的节点,另一个节点右边放所有大于等于x的节点
        ListNode lessNode(0);
        ListNode moreNode(0);
        ListNode* lessPtr = &lessNode;
        ListNode* res = lessPtr;
        ListNode* morePtr = &moreNode;
        if (head == nullptr) {
            return nullptr;
        }
        ListNode* cur = head;
        while (cur != nullptr) {
            if (cur -> val < x) {
                lessPtr -> next = cur;
                lessPtr = cur;
            }
            else {
                morePtr -> next = cur;
                morePtr = cur;
            }
            cur = cur -> next;
        }
        lessPtr -> next = moreNode.next;
        morePtr -> next = nullptr;
        return res -> next;
    }
};

6. 290. 单词规律  力扣

class Solution {
public:
    void splitStr(string s, vector<string>& all, char ch = ' ') {
        int l = 0, r = 0, len = s.length();
        while (r < len) {
            while (r < len && s[r] != ch) {
                r++;
            }
            all.push_back(s.substr(l, r-l));
            l = ++r;
        }
    }  //C++里的spilt

    bool wordPattern(string pattern, string s) {
        vector<string> vec;
        char space = ' ';
        splitStr(s, vec, space);
         if (pattern.size() != vec.size()) {
            return false;
        }
        map<string, char> myMap1;
        map<char, string> myMap2;
        int j = 0;

        for (int i = 0; i < pattern.size(); ++i) {
            if (myMap2.find(pattern[i]) == myMap2.end() && myMap1.find(vec[j]) == myMap1.end()) {
                myMap2[pattern[i]] = vec[j];
                myMap1[vec[j]] = pattern[i];
                j++;
            } else {
               if (myMap2[pattern[i]] == vec[j] && myMap1[vec[j]] == pattern[i]) {
                   j++;
                   continue;
               } else {
                   return false;
               }
            }
        }
        return true;
    }

7.  剑指 Offer 25. 合并两个排序的链表  

归并排序 力扣

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode* cur1 = l1;
        ListNode* cur2 = l2;
        ListNode* head = new ListNode(0);
        ListNode* res = head;
        while(cur1 && cur2) {
            if (cur1 -> val <= cur2 -> val) {
                head -> next = cur1;
                cur1 = cur1 -> next;
                head = head -> next;
            } else {
                head -> next = cur2;
                cur2 = cur2 -> next;
                head = head -> next;
            }
        }
        while(cur1) {
            head -> next = cur1;
            head = head -> next;
            cur1 = cur1 -> next;
        }
        while(cur2) {
            head -> next = cur2;
            head = head -> next;
            cur2 = cur2 -> next;
        }
        return res -> next;
    }
};

三 堆,栈。队列

(1)用队列实现栈   https://leetcode-cn.com/problems/implement-stack-using-queues/

class MyStack {
public:
    queue<int> store;
        queue<int> sta;
    /** Initialize your data structure here. */
    MyStack() {
    }
    
    /** Push element x onto stack. */
    void push(int x) {
        // 两个队列,A和B,来新元素时候,先放入A,再把B中元素依次出队放入A,A和B再互换内容,再B出队第一个元素就是pop()
        store.push(x);
        while(!sta.empty()) {
            int x = sta.front();
            sta.pop();
            store.push(x);
        }
        swap(store, sta);
    }
    
    /** Removes the element on top of the stack and returns that element. */
    int pop() {
        int top;
        if (!sta.empty()) {
            top = sta.front();
            sta.pop();
        }
        return top;
    }
    
    /** Get the top element. */
    int top() {
        return sta.front();
    }
    
    /** Returns whether the stack is empty. */
    bool empty() {
        return sta.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();
 */

用两个栈实现队列

class MyQueue {
public:
    /** Initialize your data structure here. */
    //两个栈A和B 来新元素,都放进B  这是push
    //pop  如果B不空,则B.pop;若B空,则把A 所以元素放进B,B再pop
    stack<int> A;
    stack<int> B;
    MyQueue() {

    }
    
    /** Push element x to the back of queue. */
    void push(int x) {
       A.push(x);
    }
    
    /** Removes the element from in front of queue and returns that element. */
    int pop() {
        if (B.empty()) {
           while(!A.empty()) {
               int top = A.top();
               A.pop();
               B.push(top);
           }
       }
       int ret = B.top();
       B.pop();
       return ret;
    }
    
    /** Get the front element. */
    int peek() {
        if (B.empty()) {
           while(!A.empty()) {
               int top = A.top();
               A.pop();
               B.push(top);
           }
       }
       int ret = B.top();
       return ret;


    }
    
    /** Returns whether the queue is empty. */
    bool empty() {
        return A.empty() && B.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();
 */

(2)最小栈 力扣

   用两个栈是实现  找最小元素是O(1)时间复杂度

class MinStack {
public:
    /** initialize your data structure here. */
    MinStack() {

    }
    
    void push(int val) {
        data.push(val);
        if (less.size() == 0) {
            less.push(val);
        } else {
            if (val < less.top()) {
                less.push(val);
            }
            else {
               less.push(less.top());
            }
        }
    }
    
    void pop() {
       data.pop();
       less.pop();
    }
    
    int top() {
        return data.top();
    }
    
    int getMin() {
        return less.top();

    }
    private:
        stack<int> data;
        stack<int> less;

};

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack* obj = new MinStack();
 * obj->push(val);
 * obj->pop();
 * int param_3 = obj->top();
 * int param_4 = obj->getMin();
 */

(3) 946. 验证栈序列   力扣

class Solution {
public:
    bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
    //先入栈,设临时堆积元素的栈是tmp, popped队头元素和tmp的栈顶元素相同时,把二者同时拿掉,pushed的下一个元素与再入栈,若和popped栈顶元素仍相同,则继续拿掉二者,若push完后  tmp空  则true,
     stack<int> tmp;
     int size1 = pushed.size();
     int size2 = popped.size();
     if (size1 == 0 && size2 == 0) {
         return true;
     }
     if (size1 ==0 || size2 == 0) {
         return false;
     }
     int j = 0;
     for (int i = 0; i < size1; ++i) {
         tmp.push(pushed[i]);
         while (tmp.size() != 0 && tmp.top() == popped[j]) {
             j++;
             tmp.pop();
         }
     }
    return tmp.empty();
    }
};

(4)数据流中第k大元素 力扣

    思路:用最小堆。top()元素永远是堆中最小的。比如把数组中前5个元素压入堆后,堆顶的元素就是前五个元素的最小值,设做x。后面元素,比x大则再压入堆,比x小则抛弃。最后top()就是第K大的元素

class KthLargest {
public:
    priority_queue<int, vector<int>, greater<int>> pbuffer;
    int n;  
    KthLargest(int k, vector<int>& nums) {
        n = k;
        int size = nums.size();
        for (int i = 0; i < size; ++i) {
            if (i < k) {
                pbuffer.push(nums[i]);
            } else {
                if (pbuffer.top() < nums[i]) {
                    pbuffer.pop();
                    pbuffer.push(nums[i]);
                }
            }
        }
    }
    
    int add(int val) {
        pbuffer.push(val);
        if (pbuffer.size() > n) {
            pbuffer.pop();
        }
        return pbuffer.top();
    }
};

/**
 * Your KthLargest object will be instantiated and called as such:
 * KthLargest* obj = new KthLargest(k, nums);
 * int param_1 = obj->add(val);
 */

(5) 20. 有效的括号  力扣

class Solution {
public:
    bool isValid(string s) {
        int len = s.size();
        if (len % 2 == 1) {
            return false;
        }
        stack<char> sta;
        for(int i = 0; i < len; ++i) {
            if (s[i] == '(' || s[i] == '{' || s[i] == '[') {
               sta.push(s[i]);
            }
            else {
                if (s[i] == ')' && sta.size() != 0 && sta.top() != '(') {
                    return false;
                }
                if (s[i] == ']' && sta.size() != 0 && sta.top() != '[') {
                    return false;
                }
                if (s[i] == '}' && sta.size() != 0 && sta.top() != '{') {
                    return false;
                }
                if (sta.size() == 0) {
                    return false;
                }
                else {
                    sta.pop();
                }
            }
        }
        if (sta.size() != 0) {
            return false;
        }
        return true;
    }
};

(6)逆波兰表达式求值  力扣

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<int> sta;
        int size = tokens.size();
        int res = 0;
        for(int i = 0; i < size; ++i) {
            if (tokens[i] == "+" ||tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/" ) {
                int numRight = sta.top();
                sta.pop();
                int numLeft = sta.top();
                sta.pop();
                int res;
                if (tokens[i] == "+") {
                    res = numLeft + numRight;
                    sta.push(res);
                }
                if (tokens[i] == "-") {
                    res = numLeft - numRight;
                    sta.push(res);
                }
                if (tokens[i] == "*") {
                    res = numLeft * numRight;
                    sta.push(res);
                }
                if (tokens[i] == "/") {
                    res = numLeft / numRight;
                    sta.push(res);
                } 
            } else {
                sta.push(atoi(tokens[i].c_str()));
            }
        }
        return sta.top();
    }
};

(7)优先队列力扣

class Solution {
public:
    //求前 k 大,用小根堆(top最小《geater<int>),求前 k 小,用大根堆(top最大,less<int>。
   /* struct cmp{
    bool operator()(const pair<int, int>& lhs, const pair<int, int>& rhs) {
		return lhs.second > rhs.second;
    }
}; */
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int, int> mymap;
        using pii = std::pair<int, int>;
      
        int len = nums.size();
        for (int i = 0; i < len; ++i) {
            mymap[nums[i]]++;
        }
        /*pair<int, int>放入优先队列,以first去排序
        要访问pair里的两个int,用qu.top().first */
        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int,int>>> qu;
        unordered_map<int, int>::iterator iter = mymap.begin();
        for(;iter != mymap.end(); ++iter) {
            qu.push(pair<int, int>(iter -> second, iter -> first));
            if (qu.size() > k) {
                qu.pop();
            }
        }
        vector<int> res;
        for(int i = k - 1; i >= 0; --i) {
            res.push_back(qu.top().second);
            qu.pop();
        }
        return res;

    }
};

1046. 最后一块石头的重量  

力扣

class Solution {
public:
    int lastStoneWeight(vector<int>& stones) {
        priority_queue <int,vector<int>,less<int> > q;
        int size = stones.size();
        for (int i = 0; i < size; ++i) {
            q.push(stones[i]);
        }
        if (size == 1) {
            return stones[0];
        }
        while(q.size() > 1) {
            int top1 = q.top();
            q.pop();
            int top2 = q.top();
            q.pop();
            if (top1 > top2) {
                q.push(top1 - top2);
            }
        }
        if (q.size() == 1) {
            return q.top();
        } else {
            return 0;
        }
    }
};

(8)227. 基本计算器 II 力扣

class Solution {
public:
    int calculate(string s) {
        int len = s.size();
        stack<int> st;
        int num = 0;
        char preTac = '+';
        for(int i = 0; i < len; ++i) {
            if (s[i] == ' ') {
                continue;
            }
            if (s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/') {
                num = 0;
                preTac = s[i];
            } else {
                while(s[i] >= '0' && s[i] <='9' && i < len) {
                    num = num * 10 + (s[i] - '0');
                    i++;
                }
                i--;
                if (preTac == '+') {
                    st.push(num);
                }
                if (preTac == '-') {
                    st.push(num * (-1));
                }
                if (preTac == '*') {
                    int top = st.top();
                    st.pop();
                    st.push(num * top);
                }
                if (preTac == '/') {
                    int top = st.top();
                    st.pop();
                    st.push(top / num);
                }
            }
        }
        int res = 0;
        while(!st.empty()) {
            res += st.top();
            st.pop();
        }
        return res;
    }
};

(9) 946. 验证栈序列  力扣

class Solution {
public:
    bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
    //先入栈,设临时堆积元素的栈是tmp, popped队头元素和tmp的栈顶元素相同时,把二者同时拿掉,pushed的下一个元素与再入栈,若和popped栈顶元素仍相同,则继续拿掉二者,若push完后  tmp空  则true,
     stack<int> tmp;
     int size1 = pushed.size();
     int size2 = popped.size();
     if (size1 == 0 && size2 == 0) {
         return true;
     }
     if (size1 ==0 || size2 == 0) {
         return false;
     }
     int j = 0;
     for (int i = 0; i < size1; ++i) {
         tmp.push(pushed[i]);
         while (tmp.size() != 0 && tmp.top() == popped[j]) {
             j++;
             tmp.pop();
         }
     }
    return tmp.empty();
    }
};

(10)496. 下一个更大元素 I  力扣 

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        /* 创建一个临时栈,一个哈希表,然后遍历 nums2nums2。
            若当前栈无数据,则当前数字入栈备用。
            若当前栈有数据,则用当前数字与栈顶比较:
              3.1 当前数字 > 栈顶,代表栈顶对应下一个更大的数字就是当前数字,则将该组数字对应关系,记录到哈希表。
              3.2 当前数字 < 栈顶,当前数字压入栈,供后续数字判断使用。
              这样,我们就可以看到哈希表中存在部分 nums2nums2 数字的对应关系了,而栈中留下的数字,代表无下一个更大的数字,我们            全部赋值为 -1 ,然后存入哈希表即可。
               遍历 nums1,直接询问哈希表拿对应关系即可。

作者:demigodliu
链接:https://leetcode-cn.com/problems/next-greater-element-i/solution/zhan-xia-yi-ge-geng-da-yuan-su-i-by-demi-cumj/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
*/
        int len1 = nums1.size();
        int len2 = nums2.size();
        unordered_map<int, int> tab;
        stack<int> st;
        for(int i = 0; i < len2; ++i) {
            while(!st.empty() && st.top() < nums2[i]) {
               tab[st.top()] = nums2[i];
               st.pop();
            }
            if (st.empty() || nums2[i] < st.top()) {
               st.push(nums2[i]);
            }
        }
        while(!st.empty()) {
            tab[st.top()] = -1;
            st.pop();
        }
        vector<int> res;
        for(int i = 0; i < len1; ++i) {
            res.push_back(tab[nums1[i]]);
        }
        return res;
    }
};

(1)暴力法

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        int len1 = nums1.size();
        int len2 = nums2.size();
        vector<int> res;
        int i = 0;
        int j = 0;
        for(; i < len1; ++i) {
           while(j < len2) {
               if (nums2[j] != nums1[i]) {
                   j++;
               } else {
                   break;
               }
           }
           j++;
           while(j < len2 && nums2[j] <= nums1[i]) {
               j++;
           }
           if (j == len2) {
               res.push_back(-1);
           } else {
               res.push_back(nums2[j]);
           }
           j = 0;
        }
        return res;
    }
};

法二 单调栈

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        /* 创建一个临时栈,一个哈希表,然后遍历 nums2nums2。
            若当前栈无数据,则当前数字入栈备用。
            若当前栈有数据,则用当前数字与栈顶比较:
              3.1 当前数字 > 栈顶,代表栈顶对应下一个更大的数字就是当前数字,则将该组数字对应关系,记录到哈希表。
              3.2 当前数字 < 栈顶,当前数字压入栈,供后续数字判断使用。
              这样,我们就可以看到哈希表中存在部分 nums2nums2 数字的对应关系了,而栈中留下的数字,代表无下一个更大的数字,我们            全部赋值为 -1 ,然后存入哈希表即可。
               遍历 nums1,直接询问哈希表拿对应关系即可。

作者:demigodliu
链接:https://leetcode-cn.com/problems/next-greater-element-i/solution/zhan-xia-yi-ge-geng-da-yuan-su-i-by-demi-cumj/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
*/
        int len1 = nums1.size();
        int len2 = nums2.size();
        unordered_map<int, int> tab;
        stack<int> st;
        for(int i = 0; i < len2; ++i) {
            while(!st.empty() && st.top() < nums2[i]) {
               tab[st.top()] = nums2[i];
               st.pop();
            }
            if (st.empty() || nums2[i] < st.top()) {
               st.push(nums2[i]);
            }
        }
        while(!st.empty()) {
            tab[st.top()] = -1;
            st.pop();
        }
        vector<int> res;
        for(int i = 0; i < len1; ++i) {
            res.push_back(tab[nums1[i]]);
        }
        return res;
    }
};

(11)503. 下一个更大元素 II   力扣

class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
        int len = nums.size();
        vector<int> res(len, -1);
        stack<int> sta;
        for(int i = 0; i < 2 * len; ++i) {
            while(!sta.empty() && nums[sta.top()] < nums[i % len]) {
                res[sta.top()] = nums[i % len]; 
                sta.pop();
            }
            sta.push(i % len);
        }
        return res;
        /* int n = nums.size();
        stack<int> st;
        vector<int> res(n, -1); // 用数组实现哈希表可以s设置默认value
        for (int i = 0; i < 2 * n; i++) { // 下标取模实现循环遍历数组
            while (!st.empty() && nums[i % n] > nums[st.top()]) {
                res[st.top()] = nums[i % n]; // 循环找到真正的下一个更大元素, 更新结果数组
                st.pop();
            }	
            st.push(i % n);
        }
        return res; */
    }
};

(12) 556. 下一个更大元素 III   力扣

class Solution {
public:
    int nextGreaterElement(int n) {
        /* 如果n是保持递减的,比如321,这种情况是无法找到的,那么就是-1
           从右往左去找是否有更小的数字,找到比右边小的数字 x 就是需要和其他数字交换的
           和谁交换呢? 依然是从右往左去找一个正好比 x 大的数字 y,那么交换它们
            此时数字其实不是最小整数,因为后面是递减的,翻转后改为递增肯定是最小的,所以从x右边到结束来做一次翻转
           例子如下: 247531

            从右往左找到小的数字,是4
            从右往左找到比4的数字5,交换后是 257431 (不是最小整数!)
            然后翻转 7431 -> 251347
        */
        string str = to_string(n);
        int len = str.size();
        if (len == 1) {
            return -1;
        }
        int curLeft;
        int curright;
        int i = len - 2;
        for (; i >= 0; --i) {
            if (str[i] < str[i + 1]) {
                curLeft = i;
                break;
            }
        }
        if (i < 0) {
            return -1;
        }
        /* 再从右向左找刚好比curleft大的数位置记做curright */
        for(int i = len - 1; i > curLeft; --i) {
            if (str[i] > str[curLeft]) {
                curright = i;
                break;
            }
        }
        swap(str[curLeft], str[curright]);
        sort(str.begin() + curLeft + 1, str.end());
        long res = stol(str);  //看下stol  stoi等函数
        return res > INT_MAX ? -1 : res;  //看下INT_MAX
       
    }
};

四  二叉树

1. 二叉树中和为某一值的路径   力扣

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> tmp;
    vector<vector<int>> res;
    void dfs(TreeNode* root, int target) {
        if (!root) {
            return;
        }
        target -= root -> val;
        tmp.push_back(root -> val);
        if (root -> left == nullptr && root -> right == nullptr && target == 0) {
          res.push_back(tmp);
        }
        dfs(root -> left, target);
        dfs(root -> right, target);
        tmp.pop_back();
        target += root -> val;  //这句留不留都没影响
    }
    vector<vector<int>> pathSum(TreeNode* root, int target) {
        if(!root) {
            return res;
        }
        dfs(root, target);
        return res;   //res是全局变量
      
    }
};

2.  求根节点到某节点的路径 ,求两个节点的最近公共祖先节点,和上面的题是一个类型   力扣

/**
 * 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:
    vector<TreeNode*> path_p;
    vector<TreeNode*> path_q;
    vector<TreeNode*> path_tmp; //遍历时的临时路径
    vector<TreeNode*> path_vec_p;
    vector<TreeNode*> path_vec_q;
    TreeNode* ret;
    int finish = 0;

    void orderpre(TreeNode* root, TreeNode* search, vector<TreeNode*> &path_tmp,         vector<TreeNode*>& path_vec, int& finish)
    {
        if (!root || finish) {
            return;
        }
        path_tmp.push_back(root);
        if (root == search) {
            path_vec = path_tmp;
            finish = true;
            return;
        }
        orderpre(root -> left, search, path_tmp, path_vec, finish);
        orderpre(root -> right, search, path_tmp, path_vec, finish);
        path_tmp.pop_back();
    }

    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        orderpre(root, p, path_tmp, path_vec_p, finish);
        path_tmp.clear();
        finish = 0;
        orderpre(root, q, path_tmp, path_vec_q, finish);
        int len_p = path_vec_p.size();
        int len_q = path_vec_q.size();
        int min = len_p;
        if (len_p > len_q) {
            min = len_q;
        }
        for (int i = 0; i < min; ++i) {
            if (path_vec_p[i] == path_vec_q[i]) {
               ret = path_vec_p[i];
            }
        }
        return ret;
    }
};

五  回溯算法

(1)全排列 力扣

class Solution {
public:
    bool visit[10];
    void dfs(vector<vector<int>>& result, vector<int> tmp, vector<int> nums) {
        if (tmp.size() == nums.size()) {
           result.push_back(tmp);
           return;
        }
        for (int i = 0; i < nums.size(); i++) {
           if (!visit[i]) {
                visit[i] = 1;
                tmp.push_back(nums[i]);
                dfs(result, tmp, nums);
                visit[i] = 0;
                tmp.pop_back();
            }
        }
    }
    vector<vector<int>> permute(vector<int>& nums) {
        vector<int> tmp;
        vector<vector<int>> result;
        dfs(result, tmp, nums);
        return result;
    } 
};

(2)上体基础上,求没有重复的所有全排列

  思路一,用set去重

class Solution {
public:
   bool visit[10];
    vector<int> tmp;
    vector<vector<int>> result;
    set<vector<int>> res_set;
    void dfs(vector<vector<int>>& result, vector<int> tmp, vector<int> nums) {
        if (tmp.size() == nums.size()) {
           res_set.insert(tmp);
           return;
        }
        for (int i = 0; i < nums.size(); i++) {
           if (!visit[i]) {
                visit[i] = 1;
                tmp.push_back(nums[i]);
                dfs(result, tmp, nums);
                visit[i] = 0;
                tmp.pop_back();
            }
        }
    }
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        dfs(result, tmp, nums);
        set<vector<int>>::iterator pos;
        for(pos = res_set.begin(); pos != res_set.end(); ++pos) {
            result.push_back(*pos);
        }
        return result;
    }
};

思路二  剪枝

/* 剪枝,如果nums[i-1] == nums[i] && visit[i - 1] == 0则for循环中continue*/
    bool visit[10];
    void dfs(vector<vector<int>>& result, vector<int> tmp, vector<int> nums) {
        if (tmp.size() == nums.size()) {
           result.push_back(tmp);
           return;
        }
        for (int i = 0; i < nums.size(); i++) {
           if (i > 0 && nums[i - 1] == nums[i] && visit[i-1] == 0) {
               continue;
           }
           if (!visit[i]) {
                visit[i] = 1;
                tmp.push_back(nums[i]);
                dfs(result, tmp, nums);
                visit[i] = 0;
                tmp.pop_back();
            }
        }
    }
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        vector<int> tmp;
        vector<vector<int>> result;
        dfs(result, tmp, nums);
        return result;
    }

(3)没有重复元素序列的所有子集   力扣

class Solution {
public:
    vector<vector<int>> result;
    void dfs(int t, vector<int> nums, vector<int> tmp) {
        result.push_back(tmp);
        if (tmp.size() == nums.size()) {
            return;
        }
        for(int i = t; i < nums.size(); ++i) {
            tmp.push_back(nums[i]);
            dfs(i + 1, nums, tmp);
            tmp.pop_back();
        }
    } 
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<int> tmp;
        //result.push_back(tmp);
        dfs(0, nums, tmp);
        return result;
    } 
};

(4)集合中有重复元素,返回所有可能的子集,要求去掉重复子集  力扣

       这道题可以用set去重,可以用剪枝,剪枝时候注意看下代码里记录的是不是保证i>0&&nums[i-1]!=nums[i]就可以?

class Solution {
public: 
   /* vector<vector<int>> result;
    set<vector<int>> set_res;
    void dfs(int t, vector<int> nums, vector<int> tmp) {
        if (tmp.size() == nums.size()) {
            return;
        }
        for(int i = t; i < nums.size(); ++i) { //若i从0 开始  后面还会压入重复元素
            tmp.push_back(nums[i]);
            set_res.insert(tmp);
            dfs(i + 1, nums, tmp);
            tmp.pop_back();
        }
    } 
    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
        vector<int> tmp;
        sort(nums.begin(), nums.end());  //帮你去掉[2 2 1] [2 1 2]的重复
        result.push_back(tmp);  //加入空集 
        dfs(0, nums, tmp);
        set<vector<int>>::iterator pos = set_res.begin();
        for (;pos != set_res.end(); ++pos) {
            result.push_back(*pos);
        }
        return result;
    } */

    /*剪枝去重,仅nums[i] != nums[i-1]对{1 2 2}能行吗? 不行,以{1 2 2}为例,continue的条件是i > 0 && nums[i] != nums[i-1] && nums[i-1]不在tmp里*/
     vector<vector<int>> res;
     int visit[100] = {0};
    void helper(vector<int>& nums, vector<int>& temp, int start) {
        res.push_back(temp);
        for (int i = start; i < nums.size(); i++) {
            if (i > 0 && nums[i] == nums[i - 1] && visit[i -1] == 0) {
                continue;
            }
            if (i == start || nums[i] != nums[i - 1]) { 
                temp.push_back(nums[i]);
                visit[i] = 1;
                helper(nums, temp, i + 1);
                temp.pop_back();
                visit[i] = 0;
            }
        }
    }
    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        vector<int> temp = {};
        helper(nums, temp, 0);
        return res;
    }
};

(5)组合总和,找出集合中所有的满足和是target的子集 ,集合中的某个数可以多次用。力扣

class Solution {
public:
    vector<vector<int>> res;
    vector<int> tmp;
    void dfs(int start, vector<vector<int>>& res, vector<int> nums, vector<int> tmp, int& sum, int target)   {
        if (sum == target) {
           res.push_back(tmp);
           return;
        }
        if (sum > target) {
            return;
        }
        for (int i = start; i < nums.size(); ++i) {
            tmp.push_back(nums[i]);
            sum += nums[i];
            dfs(i, res, nums, tmp, sum, target);
            tmp.pop_back();
            sum -= nums[i];
        }
    }
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        sort(candidates.begin(), candidates.end());
        int sum = 0;
        dfs(0, res, candidates, tmp, sum, target);
        return res;
    }
};

(6)上面的题改成集中中的每个数在子集只能用一次 力扣

class Solution {
public:
    vector<vector<int>> res;
    vector<int> tmp;
   // int visit[100] = {0};
    void dfs(int start, vector<vector<int>>& res, vector<int> nums, vector<int> tmp, int& sum, int target)   {
        if (sum == target) {
           res.push_back(tmp);
           return;
        }
        if (sum > target) {
            return;
        }
        for (int i = start; i < nums.size(); ++i) {
            if (i > start && nums[i] == nums[i - 1]) {
                continue;
            }
            tmp.push_back(nums[i]);
            sum += nums[i];
            dfs(i + 1, res, nums, tmp, sum, target);
            tmp.pop_back();
            sum -= nums[i];
        }
    }
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        sort(candidates.begin(), candidates.end());
        int sum = 0;
        dfs(0, res, candidates, tmp, sum, target);
      /*  set<vector<int>> res_set;
        vector<vector<int>> res2;
        for(int i = 0; i < res.size(); ++i) {
            res_set.insert(res[i]);
        }
        //res.clear();
        set<vector<int>>::iterator pos;
        for (pos = res_set.begin(); pos != res_set.end(); ++pos) {
            res2.push_back(*pos);
        }
        return res2; */
        return res;
    }
};

(7) 力扣    给定两个整数 n 和 k,返回 1 ... 中所有可能的 k 个数的组合。

class Solution {
public:
     vector<vector<int>> res;
    vector<int> tmp;
    void dfs(int start, vector<int> tmp, int k, vector<vector<int>>& res, int n) {
        if (tmp.size() >= k) {
            res.push_back(tmp);
            return;
        }
        for (int i = start; i <=n; ++i) {
                tmp.push_back(i);
                dfs(i + 1, tmp, k, res, n);
                tmp.pop_back();
        }
    }
    vector<vector<int>> combine(int n, int k) {
        dfs(1, tmp, k, res, n);
        return res;
    }
};

(8) 括号生成 力扣

class Solution {
public:
   /* n对括号,则左括号是n个,右括号是n个时候结束递归,且在递归过程中,只有当左括号数比右括号多时候才能继续递归 */
   vector<string> res;
   string tmp;
   int left = 0;
   int right = 0;

    void dfs(vector<string>& res, string tmp, int left, int right, int n) {
        if (left == n && right == n) {
            res.push_back(tmp);
            return;
        }
        if (left < n) {
            dfs(res, tmp + '(', left + 1, right, n);
        }
        if (right < left){
            dfs(res, tmp + ')', left, right + 1, n);
        }
    }
    vector<string> generateParenthesis(int n) {
        dfs(res, tmp, left, right, n);
        return res;
    }
};

(9)字母大小写全排列 力扣

class Solution {
public:
    vector<string> res;
    string tmp;
    void dfs(string s, int t, string  tmp, vector<string>& res)  {
        if (tmp.size() == s.size()) {
            res.push_back(tmp);
            return;
        } else {
           if (isalpha(s[t])) {
                s[t] = tolower(s[t]);
                dfs(s, t+1, tmp + s[t], res);
                s[t] = toupper(s[t]);
                dfs(s, t+1, tmp + s[t], res);
           } else {
               dfs(s, t + 1, tmp + s[t], res);
           }
        }
    }
    vector<string> letterCasePermutation(string S) {
        dfs(S, 0, tmp, res);
        return res;
    }
};

(10) LCS 01. 下载插件 力扣

class Solution {
public:
    int res =INT_MAX;
    int leastMinutes(int n) {
        dfs(0,n,1,0); 
        return res;
    }
    void dfs(int num, int n, int speed, int minute) {
         if(num>=n || minute>=res){
            res = min(res,minute);
            return;
        }
        if(num + speed >= n) {
            res = min(res,minute+1);
            return;
        }
        //将带宽加倍
        dfs(num,n,speed<<1,minute+1);
        //使用当前带宽下载
        dfs(num+speed,n,speed,minute+1);
    }
};

六 递归篇 二叉树的前序遍历  力扣

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    void dfs(TreeNode* root, vector<int>& res) {
        if (!root) {
            return;
        }
        res.push_back(root -> val);
        dfs(root -> left, res);
        dfs(root -> right, res);
    }
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        dfs(root, res);
        return res;
    }
};

(2) 二叉树中序遍历 力扣

 void dfs(TreeNode* root, vector<int>& res) {
        if (!root) {
            return;
        }
        dfs(root -> left, res);
        res.push_back(root -> val);
        dfs(root -> right, res);
    }
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        dfs(root, res);
        return res;
    }

(3)后续遍历二叉树  力扣

class Solution {
public:
    void dfs(TreeNode* root, vector<int>& res) {
        if (!root) {
            return;
        }
        dfs(root -> left, res);
        dfs(root -> right, res);
        res.push_back(root -> val);
    }
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
       dfs(root, res);
       return res;
    }
};

(4) 两两交换链表中的节点 力扣

思路:终止条件:递归到最后只剩一个节点(链表总节点数是奇数个),或者空节点(链表总节点数是偶数个)

         递归完成后,返回头节点给之前去指

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if (!head || head -> next == nullptr) {
            return head;
        }
        ListNode* releax = head -> next -> next;
        ListNode* exict = head -> next;
        exict -> next = head;
        head -> next = swapPairs(releax);
        return exict;  //返回的还是一开始的head -> next
    }
};

(5)用递归方法原地反转字符串  力扣

class Solution {
public:
    void dfs(vector<char>& s, int start, int end) {
        if (start >= end) {
            return;
        }
        char tmp;
        tmp = s[start];
        s[start] = s[end];
        s[end] = tmp;
        dfs(s, start + 1, end - 1);
    }
    void reverseString(vector<char>& s) {
        dfs(s, 0, s.size() - 1);
    }
};

(6)   606. 根据二叉树创建字符串   力扣

思路:如果左右子树都存在,则root +(左)+(右);   只有左子树,root + (左) ;   只有右子树,root + ()+(右);  左右都空,root

/**
 * 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:
    string tree2str(TreeNode* root) {
        if (!root) {
            return "";
        }
        if (root -> left == nullptr && root -> right == nullptr) {
            return to_string(root -> val);
        }
        if (root -> right == nullptr) {
            return to_string(root -> val) + "(" + tree2str(root -> left) + ")";
        }
        if (root -> left == nullptr) {
            return to_string(root -> val) + "()" + +"(" + tree2str(root -> right) + ")";
        }
        else {
            return to_string(root -> val) + "(" + tree2str(root -> left) + ")" + "(" + tree2str(root -> right) + ")";
        }
        return "";

    }
};

七   深度优先搜索 

(1)电话号码的字母组合   力扣

class Solution {
public:
   map<char,string> mymap={{'2',"abc"}, {'3',"def"}, {'4',"ghi"}, {'5',"jkl"}, {'6',"mno"}, {'7',"pqrs"}, {'8',"tuv"}, {'9',"wxyz"}}; 
   /* map<char,string> mymap;
    mymap['2'] = "abc";
    mymap['3'] = "def";
    mymap['4'] = "ghi";
    mymap['5'] = "jkl";
    mymap['6'] = "mno";
    mymap['7'] = "pqrs";
    mymap['8'] = "tuv";
     mymap['9'] = "wxyz"; */
    vector<string> res;
    string tmp;
    void dfs(string tmp, string digits, vector<string>& res, int len) {
        if (tmp.size() == len) {
            res.push_back(tmp);
            return;
        } else {
            char x = digits[0];
            //string letter = mp[x];
            for(int i = 0; i < mymap[x].size(); ++i) {
                tmp.push_back(mymap[x][i]);
                dfs(tmp, digits.substr(1), res, len);
                tmp.pop_back();
            }
        }
    }
    vector<string> letterCombinations(string digits) {
        if (digits == "") {
            return res;
        }
        int len = digits.size();
        dfs(tmp, digits, res, len);
        return res;

    }
};

(2)   98. 验证二叉搜索树            https://leetcode-cn.com/problems/validate-binary-search-tree/

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool LeftIsBST(TreeNode* root, int value) {
        if (!root) {
            return true;
        }
        if (root -> val < value && LeftIsBST(root -> left, value) && LeftIsBST(root -> right,value)) {
            return true;
        }
        return false;
    }
    bool RightIsBST(TreeNode* root, int value) {
        if (!root) {
            return true;
        }
        if (root -> val > value &&  RightIsBST(root -> right, value) && RightIsBST(root -> left, value)) {
            return true;
        }
        return false;
    }
    bool isValidBST(TreeNode* root) {
        if (!root) {
            return true;
        }
        if (LeftIsBST(root -> left, root -> val) && RightIsBST(root -> right, root -> val) && isValidBST(root -> left) && isValidBST(root -> right)) {
            return true;
        }
        return false;
    }
};

(3) 二叉树的所有路径 力扣

    //学会to_string的用法,把数转成string,比如23转成"23"

/**
 * 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:
    vector<string> res;
    string tmp;
    void dfs(TreeNode* root, string tmp, vector<string>& res) {
        if (!root) {
            return;
        }
      if (root -> left == nullptr && root -> right == nullptr) {
          tmp += to_string(root -> val);
          res.push_back(tmp);
          return;
      } 
      else {
          tmp += to_string(root -> val);
          tmp += "->";
          if (root -> left != nullptr) {
              dfs(root -> left, tmp, res);
          }
          if (root -> right != nullptr) {
              dfs(root -> right, tmp, res);
          }
      }
    }
    vector<string> binaryTreePaths(TreeNode* root) {
      dfs(root, tmp, res);
      return res;
    }
};

(4)平衡二叉树  力扣


class Solution {
public:
    bool isSameTree(TreeNode* p, TreeNode* q) {
        if (!p && !q) {
            return true;
        }
        if (!p || !q ) {
            return false;
        }
        return (p -> val == q -> val) && isSameTree(p -> left, q -> left) && isSameTree(p -> right, q -> right);
    }
};

(5)  二叉树的最小深度   力扣

class Solution {
public:
    int minDepth(TreeNode* root) {
        if (!root) {
            return 0;
        }
        int lchild = minDepth(root -> left);
        int rchild = minDepth(root -> right);
        if (lchild == 0) {
            return rchild + 1;
        }
        if (rchild == 0) {
            return lchild + 1;
        }
        return lchild >= rchild ? (rchild + 1) : (lchild + 1);
    }
};

(6) 单词搜索 力扣

class Solution {
public:
    void dfs(vector<vector<char>>& board, int row, int col, int rows, int cols, int pos, string word, vector<vector<bool>>& visit, bool &find) {
        if (row < 0 || row >= rows || col <0 || col >= cols || visit[row][col] == 1 || word[pos] != board[row][col] || find) {
            return;
        }
        if (pos == word.size() - 1) {
            find = true;
            return;
        }
        visit[row][col] = true;
        dfs(board, row + 1, col, rows, cols, pos + 1, word, visit, find);
        dfs(board, row, col + 1, rows, cols, pos + 1, word, visit, find);
        dfs(board, row - 1, col, rows, cols, pos + 1, word, visit, find);
        dfs(board, row, col - 1, rows, cols, pos + 1, word, visit, find);
        visit[row][col] = false;
    }
    bool exist(vector<vector<char>>& board, string word) {
        if (board.size() == 0) {
            return false;
        }
        int pos = 0;
        bool find = false;
        int rows = board.size();
        int cols = board[0].size();
        vector<vector<bool>> visit(rows, vector<bool>(cols, false));
        for (int i = 0; i < rows; i++) {
            for(int j = 0; j < cols; j++) {
                dfs(board, i, j, rows, cols, pos, word, visit, find);
            }
        }
        return find;
    }
};

(7) 200. 岛屿数量 力扣

class Solution {
public:
     void dfs(vector<vector<char>>& grid, int row, int col) {
         if (grid.size() == 0 || grid[0].size() == 0) {
             return;
         }
        if (row < 0 || col < 0 ||row>=grid.size()||col>=grid[0].size() || grid[row][col] == '0'){
          return;
        }
        grid[row][col] = '0';
        dfs(grid, row + 1, col);
        dfs(grid, row , col + 1);
        dfs(grid, row -1, col);
        dfs(grid, row, col - 1);
    }
    /* void dfs(vector<vector<char>>& grid,int i,int j){
        if(i < 0 || j < 0 || i >= grid.size() || j >= grid[0].size())return;
        if(grid[i][j] == '0')return;
        grid[i][j] = '0';
        dfs(grid,i+1,j);
        dfs(grid,i,j+1);
        dfs(grid,i-1,j);
        dfs(grid,i,j-1);
    } */
    
    int numIslands(vector<vector<char>>& grid) {
        int ans = 0;
        for(int i = 0;i < grid.size(); i++){
            for(int j = 0;j < grid[0].size();j++){
                if(grid[i][j] == '0')continue;
                ans ++;
                dfs(grid,i,j);
            }
        }
        return ans;
    }
};

(8) 面试题 16.19. 水域大小   力扣

class Solution {
public:
    int dfs(vector<vector<int>>& land, int row, int col) {
        if (row < 0|| col < 0 || row >= land.size() || col >= land[0].size() || land[row][col] != 0) {
            return 0;
        }
        land[row][col] = 1;
        return 1 + dfs(land, row+1, col)+ dfs(land, row-1, col) + dfs(land, row, col+1) +dfs(land, row, col-1) + dfs(land, row+1, col+1) + dfs(land, row-1, col+1) + dfs(land, row-1, col-1)+ dfs(land, row+1, col-1);
    }
    vector<int> pondSizes(vector<vector<int>>& land) { 
        int rows = land.size();
        int cols = land[0].size();
        vector<int> res;
        //vector<vector<bool>> visit(rows, vector<bool>(cols, false));
        for(int i = 0; i < rows; ++i) {
            for(int j = 0; j < cols; ++j) {
                if (land[i][j] == 0) {  
                     int tmp = dfs(land, i, j);
                    res.push_back(tmp);
                }
            }
        }
        sort(res.begin(), res.end());
        return res;
    }
};

(9) 130. 被围绕的区域 力扣

class Solution {
public:
    //在边界上找到"O",再从边界上的这个"O",往里深度搜索,遇到相邻的"O",就标记为"F",最后再遍历整个矩阵。将所有"O",改为X
    void dfs(vector<vector<char>>& board, int row, int col) {
        if (row < 0 || col < 0 || row >= board.size() || col >= board[0].size() || board[row][col]!='O') {
            return;
        }
        board[row][col] = 'F';

        dfs(board, row, col + 1);
        dfs(board, row, col +-1);
        dfs(board, row - 1, col);
        dfs(board, row + 1, col);
    }

    void solve(vector<vector<char>>& board) {
        if (board.size() == 0 || board[0].size() == 0) {
            return;
        }
        for (int i = 0; i < board[0].size(); ++i) {
           dfs(board, 0, i);
            dfs(board, board.size() - 1, i);
        }
        for (int i = 0; i < board.size(); ++i) {
           dfs(board, i, 0);
            dfs(board, i, board[0].size() - 1);
        }
        for(int i = 0; i < board.size(); i++) {
            for(int j = 0; j < board[0].size(); ++j) {
                if(board[i][j] == 'O')
                    board[i][j] = 'X';
                if(board[i][j] == 'F')
                    board[i][j] = 'O';
            }
        }
        return;

    }
};

(10) 二叉树中所有距离为 K 的结点  力扣

八  滑动窗口  

(1)无重复字符的最长子串  力扣

思路:如果游标cur也就是滑动窗口的end对应的字符在窗口出现过,就需要更新窗口,start更新到重复字符后一个位置,同时更新窗口大小与tmpMaxlen比较。怎么知道在窗口里有重复字符?必然是end对应字符位置>=start。用哈希表存字符位置。

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        if (s.size() == 0) {
            return 0;
        }
       vector<int> mymap(128, -1);
        int maxLen = 0, start = 0;
        for(int i = 0; i != s.length(); i++) {
            if (mymap[s[i]] >= start) {
                start = mymap[s[i]] + 1;
            }
            mymap[s[i]] = i;
            maxLen = max(maxLen, i - start + 1);
        }
        return maxLen;
    }
};

(3) 209. 长度最小的子数组   力扣

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int left = 0;
        int right = 0;
        int len = nums.size();
        int sum = 0;
        int optim = len;
        bool flag = 0;
        while(right <= len - 1) {
            sum += nums[right];
            while (left <= right && sum >= target) {
                flag = 1;
                if (right - left + 1 < optim) {
                   optim = right - left + 1;
                }
                sum -= nums[left];
                left++;
            }
            right++;
        }
        if (flag == 1) {
            return optim;
        }
        return 0;
    }
};

(4)438. 找到字符串中所有字母异位词  力扣

class Solution {
public://用sort排序p和窗口,超时
    vector<int> findAnagrams(string s, string p) {
         int lenS = s.size();
         int lenP = p.size();
         vector<int> res;
         if (lenP > lenS) {
             return res;
         }
         int left = 0;
         int right = left + lenP - 1;
         vector<int> mymap1(26, 0);
         for(int i = 0; i < lenP; ++i) {
             mymap1[p[i] - 'a']++;
         }
         vector<int> mymap2(26, 0);
         vector<int> mymap3(26, 0);
         while(right < lenS) {
             for(int i = left; i <= right; ++i) {
                 mymap2[s[i] - 'a']++;
             }
             if (mymap2 == mymap1) {
                res.push_back(left);
             }
             mymap2 = mymap3;
             left++;
             right++;
         }
         return res;
    }
};

(5) 子数组最大平均数 I   力扣

class Solution {
public: /* double计算比int要慢,所以中间记录的值要设成int型,最后返回的时候再转换成double */
       /* 计算窗口内sum时候,不要每次都遍历,会超时。减去nums[left],加新的nums[right],*/
    double findMaxAverage(vector<int>& nums, int k) {
        //int MIN = -9999;
        double optimum = -999999;
        int left = 0;
        int right = left + k - 1;
        int len = nums.size();
        int sum = 0;
         for (int i = left; i <= right; ++i) {
            sum += nums[i];
        }
        while(right <= len - 1) {
           if (sum > optimum) {
               optimum = sum;
           }
           sum -= nums[left];
           if ((left+1 > len - 1) && (right+1 > len - 1)) {
               break;
           }
           left++;
           right++;
           sum += nums[right];
        }
        return ((double)optimum)/k;
    }
};

九 (1)102. 二叉树的层序遍历   力扣

/**
 * 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:
    vector<vector<int>> levelOrder(TreeNode* root) {
       vector<vector<int>> res;
        if (!root) {
            return res;
        }
        queue<TreeNode*> qu;
        vector<int> tmp;
        qu.push(root);
        while(!qu.empty()) {
            int len = qu.size();
            for(int i = 0; i < len; ++i) { //想下这里能否些换成qu.size()
                TreeNode* head = qu.front();
                tmp.push_back(head -> val);
                qu.pop();
                if (head -> left) {
                    qu.push(head -> left);
                }
                if (head -> right) {
                    qu.push(head -> right);
                }
            }
            res.push_back(tmp);
            tmp.clear();
        }
        return res; 
    }
};

十   二分法  

(1)剑指 Offer 53 - I. 在排序数组中查找数字 I

力扣

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int len = nums.size();
        if (len == 0) {
            return 0;
        }
        int start = 0;
        int end = len - 1;
        int count = 0;
        while (start <= end) {
            int mid = (start + end) / 2;
            if (nums[mid] == target) {
               ++count;
               int tmpmid = mid;
               while(tmpmid > start && nums[--tmpmid] == target) {
                   count++;
               }
               while(mid < end && nums[++mid] == target) {
                   count++;
               }
               return count;
            }
            if (nums[mid] < target) {
                start = mid + 1;
            }
            if (nums[mid] > target) {
                end = mid - 1;
            }
        }
        return 0;
    }
};

(2)1337. 矩阵中战斗力最弱的 K 行   力扣

class Solution {
public:
    //二分查找找每行最后一个1的位置,这个位置就是军人数量,军人数量乘以1000加行号当作能量值,取能量值最//小的k个
    int binarySearch(vector<int> vec) {
        int len = vec.size();
        int start = 0;
        int end = vec.size() - 1;
        int mid;
        while(start <= end) {
            mid = (start + end) / 2;
            if (vec[mid] == 1) {
                if (mid == len -1 || vec[mid + 1] == 0) {
                    return mid + 1;
                }
                start = mid + 1;
            } else {
                if (mid == 0 || vec[mid - 1] == 1) {
                    return mid;
                }
                end = mid - 1;
            }
        }
        return -1;
    }
    vector<int> kWeakestRows(vector<vector<int>>& mat, int k) {
        vector<int> res;
        vector<int> ret;
        map<int, int> mymap;
        int size = mat.size();
        for (int i = 0; i < size; ++i) {
            int tmp = 1000 * binarySearch(mat[i]) + i;
            ret.push_back(tmp);
            mymap[tmp] = i;
        }
        //sort(res.begin(), res.end());
        //set<int>::iterator pos = res.begin();
        sort(ret.begin(), ret.end());
        for(int j = 0; j < k; ++j) {
            res.push_back(mymap[ret[j]]);
        }
        return res;

    }
};

(3)  剑指 Offer 53 - II. 0~n-1中缺失的数字   力扣

class Solution {
public:
    /* 从左到右第一个位置i不等于a[i]的i就是要找的 */
    int missingNumber(vector<int>& nums) {
        int len = nums.size();
        int start = 0;
        int end = len - 1;
        while(start <= end) {
            int mid = (start + end) / 2;
           if (nums[mid] != mid) {
               end = mid -1;
           } else {
               start = mid + 1;
           }
        }
        if (start != 0) {
            return start;
        } 
        return 0;
        
    }
};

十一  位运算  

·1. 四种GCC内置位运算函数

四种GCC内置位运算函数_steven_新浪博客

 int __builtin_ffs (unsigned int x)
     返回x的最后一位1的是从后向前第几位,比如7368(1110011001000)返回4。

·int __builtin_clz (unsigned int x)
返回前导的0的个数。

·int __builtin_ctz (unsigned int x)
返回后面的0个个数,和__builtin_clz相对。比如7368(1110011001000)返回3。

·int __builtin_popcount (unsigned int x)
返回二进制表示中1的个数。

·int __builtin_parity (unsigned int x)
返回x的奇偶校验位,也就是x的1的个数模2的结果。

此外,这些函数都有相应的usigned long和usigned long long版本,只需要在函数名后面加上l或ll就可以了,比如int __builtin_clzll。

2. 位运算理论

CS-Notes/Leetcode 题解 - 位运算.md at master · CyC2018/CS-Notes · GitHub

https://www.cnblogs.com/nobita/p/14320239.html

(1) 461. 汉明距离

class Solution {
public:
    int hammingDistance(int x, int y) {
        return __builtin_popcount(x^y);
    }
};

(2)   剑指 Offer 56 - I. 数组中数字出现的次数  力扣

class Solution {
public:
    vector<int> singleNumbers(vector<int>& nums) {
        int two = 2;
        int size = nums.size();
        vector<int> part1;
        vector<int> part2;
        vector<int> res;
        int  x = 0;
        for (int i = 0; i < size; ++i) {
            x = x ^ nums[i];
        }
        //从右向左找第一个1,记录这个1的位置,说明两个单数该位不同,再依据这位不同将数组分成两组,则两个单数一定分别在两组,两组各自抑或,找到各自的单数

        // 获取一个数二进制最低位的1
        int y = x & (-x);
        for (int i = 0; i < size; ++i) {
            int w = nums[i] & y;
            if (w == y) {
                part1.push_back(nums[i]);
            } else {
                part2.push_back(nums[i]);
            }
        }
        int z = 0;
        for (int i = 0; i < part1.size(); ++i) {
            z= z^ part1[i];
        }
        res.push_back(z);
        int m = 0;
        for (int i = 0; i < part2.size(); ++i) {
            m= m^ part2[i];
        }
        res.push_back(m);
        return res;


    }
};

十二 双指针

(1)11. 盛最多水的容器  力扣

class Solution {
public:
    int maxArea(vector<int>& height) {
        int start = 0;
        int end = height.size() - 1;
        int max = -1;
        while(start < end) {
          if (height[start] <= height[end]) {
              int sum = height[start] * (end - start);
              if (max < sum) {
                  max = sum;
              }
              start++;
          }
          if (height[start] > height[end]) {
              int sum = height[end] * (end - start);
              if (max < sum) {
                  max = sum;
              }
              end--;
          }
        }
        return max;
    }
};

(2) 15. 三数之和   力扣

#include <unordered_set>
class Solution {
public:
   /*
    vector<vector<int>> threeSum(vector<int>& nums) {
       int size = nums.size();
       vector<vector<int>> res;
       std::unordered_set<vector<int>> setVec;
       vector<int> tmp;
       if (size < 3) {
           return res;
       }
       sort(nums.begin(), nums.end());
       for (int i = 0; i < size - 2; ++i) {
           int left = i + 1;
           int right = size - 1;
           if (nums[i] >0) {
               break;
           }
           while(left < right) {
               if (nums[i] + nums[left] + nums[right] == 0) {
                   tmp.push_back(nums[i]);
                   tmp.push_back(nums[left]);
                   tmp.push_back(nums[right]);
                   setVec.insert(tmp);
                   tmp.clear();

                } else if (nums[i] + nums[left] + nums[right] > 0) {
                    right--;
                } else if (nums[i] + nums[left] + nums[right] < 0) {
                    left++;
                }
            }
       }
       std::unordered_set<vector<int>>::iterator iter = setVec.begin();
       for(; iter != setVec.end(); ++iter) {
           res.push_back(*iter);
       }
       return res;
    } */
    vector<vector<int>> threeSum(vector<int>& nums) {
        int target;
        vector<vector<int>> ans;
        sort(nums.begin(), nums.end());
        for (int i = 0; i < nums.size(); i++) {
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            if ((target = nums[i]) > 0) break;
            int l = i + 1, r = nums.size() - 1;
            while (l < r) {
                if (nums[l] + nums[r] + target < 0) ++l;
                else if (nums[l] + nums[r] + target > 0) --r;
                else {
                    ans.push_back({target, nums[l], nums[r]});
                    ++l, --r;
                    while (l < r && nums[l] == nums[l - 1]) ++l;
                    while (l < r && nums[r] == nums[r + 1]) --r;
                }
            }
        }
        return ans; 
    }
};

(3) 16. 最接近的三数之和  力扣

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        /* 找三数之和和target差的绝对值最小
        求三个数之和最接近目标,可以简化为在一个数确定之后,两个数的和是否更接近目标。
        那么我怎么去确定这两个数,从而花费更小的时间呢? 我们设数组nums=[-4,2,1,-3,-1,4],target=2,
        我们可以先将数组排序,此时花费了O(NlogN)的时间复杂度nums=[-4,-3,-1,1,2,4]。
        我们先确定第一个数为x=nums[0]=-4,题目就变成了从nums[1:]中求两个数的和最接近target-nums[1]。
        我们通过设置两个指针,一头一尾。此时判两个数的和是否更接近于target-nums[1].
        如果大于target,我们将尾巴向前移一位,两个数的和会因此变小,也会更接近target-nums[1]。
        如果小于target,我们将头部向后移一位,两个数的和会变大,也会更接近target-nums[1]
        通过头尾不断的前后移动,我们最终可能在较为中间的位置找到一个最接近目标的和nums[0]+nums[3]+nums[5]=1。
        当然这只是一个确定的一个数,我们最后想遍历所有可能的结果,此时我们需要遍历第一个数x,让其改变的同时,头尾指针也不断的 前后移动,直到找到这个最终的结果。*/
        int size = nums.size();
        sort(nums.begin(), nums.end());
        int retAbs = 99999;
        int ret = nums[0] + nums[1] + nums[2];
        int left;
        int right;
        int i;
        int sum;
        for (i = 0; i < size - 2; ++i) {
            left = i + 1;
            right = size - 1;
            while(left < right) {
                sum = nums[i] + nums[left] + nums[right];
                if (sum == target) {
                    return sum;
                } else if (sum > target) {
                    right--;
                } else if (sum < target) {
                    left++;
                }
                if (abs(sum - target) < abs(ret - target)) {
                    ret = sum;
                }      
            }
        }
        return ret;
    }
};

(4) 31. 下一个排列   力扣

class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        int size = nums.size();
        if (size <= 1) {
            return;
        }
        int i = size - 1;
        int index1;
        int index2;
        for (int i = size - 2; i >= 0; --i) {
            if (nums[i] < nums[i + 1]) {
                index1 = i;
                index2 = i + 1;
                break;
            }
        }
        if (index1 < 0) {
            sort(nums.begin(), nums.end());
            return;
        }
        int min = index1 + 1;
        for (int j = size - 1; j > index1; --j) {
            if (nums[j] > nums[index1]) {
                min = j;
                break;
            }
        }
        swap(nums[index1], nums[min]);
        sort(nums.begin() + index1 + 1, nums.end());
    }
};

(5)  633. 平方数之和   力扣

class Solution {
public:
    bool judgeSquareSum(int c) {
        //怎么向上合向下取整:https://blog.csdn.net/weixin_30075185/article/details/117044576
        long index1 = 0;
        long index2 = sqrt(c);
        while (index1 <= index2) {
            long sum = index1 * index1 + index2 * index2;
            if (sum == c) {
                return true;
            }
            if (sum > c) {
                index2--;
            }
            if (sum < c) {
                index1++;
            }
        }
        return false;
    }
};

(6) 680. 验证回文字符串 Ⅱ 力扣

class Solution {
public:
    bool validPalindrome(string s) {
        int len = s.size();
        int left = 0;
        int right = len - 1;
        int cur1;
        int cur2;
        while(left < right) {
            if (s[left] == s[right]) {
                left++;
                right--;
            }
            if (s[left] != s[right]) {
                cur1 = left;
                cur2 = right;
                break;
            }
        }

        if (left >= right) {
            return true;
        }

        int cur3 = cur1;
        int cur4 = cur2;
        bool flag1 = true;
        bool flag2 = true;
        cur3++;
        while(cur3 < cur4) {
            if (s[cur3] == s[cur4]) {
                cur3++;
                cur4--;
            } else {
                flag1 = false;
                break;
            }
        }
        if (flag1 == true) {
            return true;
        }

        cur2--;
        while(cur1 < cur2) {
            if (s[cur1] == s[cur2]) {
                cur1++;
                cur2--;
            } else {
                flag2 = false;
                break;
            }
        }
        if (flag2 == true) {
            return true;
        }
        return false;
    }
};

十三 874. 模拟行走机器人 力扣

class Solution {
public:
    int robotSim(vector<int>& commands, vector<vector<int>>& obstacles) {
        int dx[4] = {0, 1, 0, -1};
        int dy[4] = {1, 0, -1, 0};
        int x = 0, y = 0, di = 0;
        /*
          set<pair<int, int>>obstaclesSet;
		for (vector<int>ob : obstacles)
		{
			obstaclesSet.insert(make_pair(ob[0], ob[1]));
		} */

        unordered_set<string> obstacleSet;
        for(int i = 0; i < obstacles.size(); ++i) {
            string tmpStr = to_string(obstacles[i][0]) + "," + to_string(obstacles[i][1]);
            obstacleSet.insert(tmpStr); //此处如果不加","会有用例过不了,没想出原因。to_string(-1)///结果确实是"-1"
        }
        /* set<pair<int, int>>obstaclesSet;
        for (int i = 0; i < obstacles.size(); ++i) {
            obstaclesSet.insert(make_pair(obstacles[i][0], obstacles[i][1]));
        } */
        int ans = 0;
        for (int i = 0; i < commands.size(); ++i) {
            if (commands[i] == -2) {
                di = (di + 3) % 4;
            }
            if (commands[i] == -1) {
                di = (di + 1) % 4;
            }
            else {
                for (int k = 0; k < commands[i]; ++k) {
                    int nx = x + dx[di];
                    int ny = y + dy[di];
                    string tmp = to_string(nx);
                    tmp += ",";
                    tmp += to_string(ny);
                    /* if (obstaclesSet.find(make_pair(nx, ny)) == obstaclesSet.end()) { */
                    if (obstacleSet.find(tmp) == obstacleSet.end()) {
                        x = nx;
                        y = ny;
                        ans = max(ans, x*x + y*y);
                    } else {
                        break;
                    }
                }
            }
        }
        return ans;
    }
};

十四、 广度优先搜索

(1)226. 翻转二叉树 力扣

/**
 * 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:
    TreeNode* invertTree(TreeNode* root) {
        //层次遍历,遍历到左右节点时候,交换左右节点
        queue<TreeNode*> qu;
        if(!root) {
            return root;
        }
        qu.push(root);
        while(!qu.empty()) {
            TreeNode* tmp = qu.front();
            qu.pop();
            TreeNode* leftTmp = tmp -> left;
            if (leftTmp) {
                qu.push(leftTmp);
            }
            TreeNode* rightTmp = tmp -> right;
            if (rightTmp) {
                qu.push(rightTmp);
            }
            TreeNode* sw = tmp -> left;
            tmp -> left = rightTmp;
            tmp -> right = sw; 
        }
        return root;
    }
};

(2)404. 左叶子之和  力扣

/**
 * 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 sumOfLeftLeaves(TreeNode* root) {
      /*  BFS
      int sum = 0;
        queue<TreeNode*> que;
        if (!root) {
            return 0;
        }
        que.push(root);
        while(!que.empty()) {
            TreeNode* tmp = que.front();
            que.pop();
            if (tmp -> left) {
                TreeNode* tmpLeft = tmp -> left;
                if ((!(tmpLeft -> left)) && (!(tmpLeft -> right))) {
                    sum += tmpLeft -> val;
                } else {
                    que.push(tmpLeft);
                }  
            }
            if (tmp -> right) {
                TreeNode* tmpRight = tmp -> right;
                que.push(tmpRight);
            }
        }
        return sum; */


        /* DFS */
        if (!root) {
            return 0;
        }
        int sum = 0;
        if ((root -> left) && (!(root -> left -> left)) && (!(root -> left -> right))) {
            sum += root -> left -> val;
        }
        return sum + sumOfLeftLeaves(root -> left) + sumOfLeftLeaves(root -> right);
    }
};

(3)  637. 二叉树的层平均值   力扣

/**
 * 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:
    vector<double> averageOfLevels(TreeNode* root) {
        vector<double> res;
        queue<TreeNode*> qu;
        qu.push(root);
        while(!qu.empty()) {
            int size = qu.size();
            double sum = 0;
            for(int i = 0; i < size; ++i) {
                TreeNode* tmp = qu.front();
                sum += tmp -> val;
                qu.pop();
                if (tmp -> left) {
                    qu.push(tmp -> left);
                }
                if (tmp -> right) {
                    qu.push(tmp -> right);
                }
            }
            double aver = sum / size;
            res.push_back(aver);
        }
        return res;
    }
};

(4) 965. 单值二叉树  力扣

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool isUnivalTree(TreeNode* root) {
        if (!root) {
            return true;
        }
        if ((!(root -> left)) && (!(root -> right))) {
            return true;
        }
        if (root -> left) {
            if (root -> val != root -> left -> val) {
                 return false;
            }
        }
        if (root -> right) {
            if (root -> val != root -> right -> val) {
                 return false;
            }
        }
        return isUnivalTree(root -> left) && isUnivalTree(root -> right);
    }
};

十五  动态规划

(1)121. 买卖股票的最佳时机  力扣

class Solution {
public:
    int maxProfit(vector<int>& prices) {
     /* 一次遍历
        int size = prices.size();
        int minCost = 999999;
        int maxEarn = 0;
        for(int i = 0; i < size; ++i) {
            if (prices[i] < minCost) {
               minCost = prices[i];
            } else {
                if (prices[i] - minCost > maxEarn) {
                    maxEarn = prices[i] - minCost;
                }
            }
        }
        return maxEarn;
        */

        /* 单调栈 */
        /* stack<int> sta;
        int optimum = 0;
        int size = prices.size();
        for(int i = 0; i < size; ++i) {
            if (sta.empty() || sta.top() >= prices[i]) {
                sta.push(prices[i]);
            }
            else {
                if (prices[i] - sta.top() > optimum) {
                    optimum = prices[i] - sta.top();
                }
            }
        }
        return optimum; 
    */
        int size = prices.size();
        if (size < 2) {
            return 0;
        }
        vector<vector<int>> vec(size, vector<int>(2, 0));
        vec[0][0] =  0;
        vec[0][1] = -prices[0];
        for(int i = 1; i < size; ++i) {
            vec[i][0] = max(vec[i - 1][0], vec[i - 1][1] + prices[i]);
            vec[i][1] = max(-prices[i], vec[i-1][1]);
        }
        return vec[size -1][0];
    }
};

(2)118. 杨辉三角   力扣

class Solution {
public:
    vector<vector<int>> generate(int numRows) {
        vector<vector<int>> ans;
        for (int i = 0; i < numRows; ++i) {
            vector<int> tmp4(i + 1);
            tmp4[0] = 1;
            tmp4[i] = 1;
            for(int j = 1; j < i; ++j) {
                tmp4[j] = ans[i - 1][j - 1] + ans[i -1][j];
            }
            ans.push_back(tmp4);
        }
        return ans;
    }
};

(3) 122. 买卖股票的最佳时机 II   力扣

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int size = prices.size();
        vector<vector<int>> vec(size, vector<int>(2, 0));
        vec[0][0] = 0;
        vec[0][1] = -prices[0];
        int dp0 = 0;
        int dp1 = -prices[0];
        for(int i = 1; i < size; ++i) {
            vec[i][0] += max(vec[i - 1][0], vec[i - 1][1] + prices[i]);
            vec[i][1] += max(vec[i - 1][1], vec[i - 1][0] - prices[i]);
        }
        return vec[size -1][0];
    }
};

(4)  面试题 17.16. 按摩师   力扣

class Solution {
public:
    int massage(vector<int>& nums) {
        int size = nums.size();
        if (size == 0) {
            return 0;
        }
        if (size == 1) {
            return nums[0];
        }
        vector<int> vec(1000, -1);
        vec[0] = 0;
        vec[1] = nums[0];
        for(int i = 2; i <= size; ++i) {
            vec[i] = max(vec[i - 1], vec[i - 2] + nums[i -1]);
        }
        return vec[size];
    }
};

(5)  剑指 Offer 42. 连续子数组的最大和  力扣

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int size = nums.size();

        vector<int> vec(size + 1, 0);
        vec[0] = nums[0];
        for(int i = 1; i < size; ++i) {
            if (vec[i - 1] > 0) {
                vec[i] = vec[i -1] + nums[i];
            } else {
                vec[i] = nums[i];
            }
        }
        int max = -99999;
        for(int i = 0; i < size; ++i) {
            if (max < vec[i]) {
                max = vec[i];
            }
        }
        return max;


    }
};

(6) 337. 打家劫舍 III  力扣

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
     vector<int> dfs(TreeNode* root) {
         vector<int> res(2, 0);
        if (root) {
            vector<int> lt(2, 0);
            vector<int> rt(2, 0);
            lt = dfs(root -> left);
            rt = dfs(root -> right);
            res[0] = max(lt[0], lt[1]) + max(rt[0], rt[1]);
            res[1] = lt[0] + rt[0] + root -> val;
        }
        return res;
        
    }
    int rob(TreeNode* root) {
        vector<int> ret(2, 0);
        ret = dfs(root);
        return max(ret[0], ret[1]);

    }
};

(7) 198. 打家劫舍 力扣

class Solution {
public:
    int rob(vector<int>& nums) {
        int size = nums.size();
        vector<int> vec(size + 1, 0);
        vec[0] = 0;
        vec[1] = nums[0];

        for(int i = 2; i <= size; ++i) {
            vec[i] = max(vec[i - 1], vec[i - 2] + nums[i - 1]);
        }
        return vec[size];
    }
};

(8) 213. 打家劫舍 II   力扣

class Solution {
public:
    int rob(vector<int>& nums) {
        int size = nums.size();
        if (size == 0) {
            return 0;
        }
        if (size == 1) {
            return nums[0];
        }
        vector<vector<int>> dp(size + 1, vector<int>(2, 0));

        //选第一家
        dp[0][0] = 0;
        dp[1][0] = nums[0];
        dp[2][0] = nums[0];

        //不选第一家
        dp[0][1] = 0;
        dp[1][1] = 0;
        dp[2][1] = nums[1];
        if (size < 3) {
            return max(dp[size][1], dp[size][0]);
        }

        for(int i = 3; i <= size - 1; ++i) {
            dp[i][0] = max(dp[i - 1][0], dp[i - 2][0] + nums[i - 1]);
        }
        for(int i = 3; i <= size; ++i) {
            dp[i][1] = max(dp[i -1][1], dp[i - 2][1] + nums[i - 1]);
        } 

        return max(dp[size - 1][0], dp[size][1]);
    }
};

(9)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值