数据结构与算法题

1. Longest Substring Without Repeating Characters(LeetCode-3)

  题意: 在字符串中找出没有重复字符的最长连续子字符串的长度。
  思路: 采用哈希表,用一个256维的vector来存储字符出现的位置,用left来记录不重复子串的左边位置,O(n)一次遍历,如果该字符之前出现过,更新left。
  考察点: 哈希表思想、字符串左右边界更新、一次O(n)遍历。
  积累: 可以用一个256长的vector来替代哈希表存储字符

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        if (s.size() <= 1) return s.size();
        int left = 0;
        int ans = 0;
        vector<int> m(256,-1);
        for (int i = 0; i < s.size(); ++i) {
            if (m[s[i]] != -1) {
                left = max(left,m[s[i]] + 1);
            }
            m[s[i]] = i;
            ans = max(ans,i - left + 1);
        }
        return ans;
    }
};

2. Longest Palindromic Substring(LeetCode-5)

  题意: 在字符串中寻找到最长回文连续子串。
  思路: 利用二维dp来记录[j,i]之间是否为回文字符串,两次for循环,主要找到dp(j)(i)与dp(j+1)(i-1)的状态转移方程,O(n^2)的时间复杂度。
  考察点: 回文子串如何构建二维dp的状态转移方程。有没有时间复杂度更小的算法???
  积累: 二维vector的初始化、string.substr()的使用。

class Solution {
public:
    string longestPalindrome(string s) {
        if (s.size() <= 1) return s;
        int size = s.size();
        vector<vector<bool>> dp(size,vector<bool>(size,false));
        string ans;
        int max_len = 0;
        for (int i = 0; i < size; ++i) {
            for (int j = 0; j <= i; ++j) {
                dp[j][i] = (s[i] == s[j]) && (i - j <= 2 || dp[j + 1][i - 1]);
                if (dp[j][i]) {
                    if (i - j + 1 > max_len) {
                        max_len = i - j + 1;
                        ans = s.substr(j,i - j + 1);
                    }
                }
            }
        }
        return ans;
    }
};

3. Longest Palindromic Subsequence(LeetCode-516)

  题意: 在字符串中寻找到最长回文子序列。
  思路: 设立一个len行len列的dp数组。dp[i][j]表示字符串i~j下标所构成的子串中最长回文子串的长度。最后我们需要返回的是dp[0][len-1]的值dp数组这样更新:首先i指针从尾到头遍历,j指针从i指针后面一个元素开始一直遍历到尾部。一开始dp[i][i]的值都为1,如果当前i和j所指元素相等,说明能够加到i~j的回文子串的长度中,所以更新dp[i][j] = dp[i+1][j-1] + 2; 如果当前元素不相等,那么说明这两个i、j所指元素对回文串无贡献,则dp[i][j]就是从dp[i+1][j]和dp[i][j-1]中选取较大的一个值即可。
  考察点: 动态规划,
  积累: 与最长回文连续子串做对比!!!比较遍历方式和dp状态转移方程的不同,为什么不同???

class Solution {
public:
    int longestPalindromeSubseq(string s) {
        if (s.size() <= 1) return s.size();
        int len = s.size();
        vector<vector<int>> dp(len,vector<int>(len,0));
        for(int i = len - 1;i >= 0;i--)
        {
            dp[i][i]=1;
            for(int j = i + 1;j < len; j++)
            {
                if(s[i] == s[j])
                    dp[i][j] = dp[i+1][j-1] + 2;
                else
                    dp[i][j] = max(dp[i+1][j],dp[i][j-1]);
            }
        }
        return dp[0][len - 1];
    }
};

4. Palindromic Substrings(LeetCode-647)

  题意: 在字符串中寻找回文子串的个数
  思路: 一次遍历O(n),以当前字符作为起始,再以当前字符和下一个字符作为起始,进行回文个数的计算。
  考察点: 建模能力,如何能找到回文子字符串的个数,不需要用dfs。
  积累: 回文要从个数的奇偶考虑!!!!

class Solution {
public:
    int countSubstrings(string s) {
        int count = 0;
        for(int i = 0; i < s.size(); i++) {
            count += countPalindromes(s, i, i);
            count += countPalindromes(s, i, i + 1);
        }
        return count;
    }
    
    int countPalindromes(string& s, int i, int j) {
        int count = 0;
        while(i >= 0 && j < s.size() && s[i--] == s[j++])
            count++;
        return count;
    }
};

5. Longest Palindrome(LeetCode-409)

  题意: 通过给定的字符来生成最长的回文字符串
  思路: 统计字符的个数,分偶数个和奇数个
  考察点: 抽象思维建模,如何生成最长的回文串
  积累: 分奇偶来考虑问题

class Solution {
public:
    int longestPalindrome(string s) {
        if (s.size() <= 1) return s.size();
        vector<int>count(256,0);
        for (auto m:s)
            count[m]++;
        int ans = 0;
        int r = 0;
        for (int i = 0; i < 256; ++i) {
            if (count[i] != 0) {
                ans += (count[i] / 2) * 2;
                if (count[i] % 2 == 1)
                    r = 1;
            }
        }
        return ans + r;
    }
};

6. Valid Palindrome(LeetCode-125)

  题意: 只考虑给定字符串中的数字和字母,不考虑空格和标点,大小写认为是同一个字符,判断是否为回文串。
  思路: 双指针一个从头,一个从尾
  考察点: 字符串的灵活运用,双指针思想
  积累: isalnum函数判断字符是否为字符串或者数字,toupper函数将字符变为大写。

class Solution {
public:
    bool isPalindrome(string s) {
        int start = 0;
        int end = s.size() - 1;
        while(start <= end) {
            while(!isalnum(s[start]) && start < end)
                start++;
            while(!isalnum(s[end]) &&  start < end)
                end--;
            if(toupper(s[start]) != toupper(s[end]))
                  return false;
            start++;
            end--;  
        }
        return true; 
    } 
};

7. Add Strings(LeetCode-415)

  题意: 非负大整数相加
  思路: 由后向前进行单个字符加的操作,注意进位carry
  考察点: 字符串的操作
  积累: 字符串的insert函数使用,字符串与数字之间的转换

class Solution {
public:
    string addStrings(string num1, string num2) {
        string ans;
        int i = num1.size() - 1;
        int j = num2.size() - 1;
        int carry = 0;
        while (i >= 0 || j >= 0) {
            int ans1 = 0, ans2 = 0;
            if (i >= 0) {        
                ans1 = int(num1[i] - '0');
            }
            if (j >= 0) {
                ans2 = int(num2[j] - '0');  
            }
            int sum = ans1 + ans2 + carry;
            ans.insert(ans.begin(),(sum % 10 + '0'));
            carry = sum / 10;
            i--;
            j--;
        }
        if (carry != 0)
            ans.insert(ans.begin(),carry + '0');
        return ans;
    }
};

8. Multiply Strings(LeetCode-43)

  题意: 非负大整数相乘
  思路: 将其转换成大数相加思路,通过写出乘法式子找出规律。注意要进行时间复杂度的简化,不要设计为O(n^3) ,O(n^2)即可!
  考察点: 字符串操作,乘法的概念
  积累: 找规律

class Solution {
public:
    string multiply(string num1, string num2) {
        if(num1 == "0" || num2 == "0") return "0";
        int len1 = num1.size();
        int len2 = num2.size();
        int len = len1 + len2 - 1;
        string ans = "";
        int carry = 0;
        for(int i = len - 1; i >= 0;--i) {
            int sum = 0;
            for(int j = 0; j <= len1 - 1; ++j) {
                if(i - j >= 0 && i - j <= len2 - 1) {
                    sum += int(num1[j] - '0') * int(num2[i - j] - '0');
                }
            }
            sum += carry;
            carry = sum / 10;
            ans.insert(ans.begin(),(sum % 10) + '0');
        }
        if(carry != 0) ans.insert(ans.begin(),carry + '0');
        return ans;
    }
};

9. Plus One(LeetCode-66)

  题意: 数组形式的非负整数进行加1操作
  思路: 由末尾向前进行位数的加1操作,区别对待9和其他数字即可。注意最后的进位!
  考察点: 数组的灵活运用,分析加1操作的数学原理
  积累: 高精度计算题

class Solution {
public:
    vector<int> plusOne(vector<int>& digits) {
        int carry = 0;
        for(int i = digits.size() - 1; i >= 0; --i) {
            if(digits[i] == 9) {
                digits[i] = 0;
                carry = 1; 
            }
            else {
                digits[i] += 1;
                carry = 0;
                break;
            }
        }
        if(carry != 0) digits.insert(digits.begin(),1);
        return digits;
    }
};

10. Reverse Integer(LeetCode-7)

  题意: 将一个32位的整数进行颠倒操作,如果超过int的上下界则返回零。
  思路: 整数对10取余即为当前个位数字,对10取整即舍弃当前各位数字。提前判断是否越界。
  考察点: 除法与取余操作的灵活运用。
  积累: 对个位数的取余和取整操作。

class Solution {
public:
    int reverse(int x) {
        int result = 0;
        while(x) {
            if(result > INT_MAX / 10 || result < INT_MIN / 10) return 0;
            result *= 10;
            result += (x % 10); 
            x /= 10;         
        }
        return result;
    }
};

11. Add Two Numbers(LeetCode-2)

  题意: 将两个非负正整数链表进行加的操作,以链表头开始。
  思路: 两个链表从头开始,进行取值及加法操作。同样可以用递归来做;
  考察点: 链表与加法运算

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode *res = new ListNode(-1);
        ListNode *cur = res;
        int carry = 0;
        while (l1 || l2) {
            int n1 = l1 ? l1->val : 0;
            int n2 = l2 ? l2->val : 0;
            int sum = n1 + n2 + carry;
            carry = sum / 10;
            cur->next = new ListNode(sum % 10);
            cur = cur->next;
            if (l1) l1 = l1->next;
            if (l2) l2 = l2->next;
        }
        if (carry) cur->next = new ListNode(1);
        return res->next; 
    }
};

  递归方法

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        if (l1 == nullptr || l2 == nullptr) {
            return l1 == nullptr ? l2 : l1;
        }
        int value = l1->val + l2->val;
        ListNode* result = new ListNode(value % 10);
        result->next = addTwoNumbers(l1->next, l2->next);
        if (value >= 10) {
            result->next = addTwoNumbers(new ListNode(value / 10), result->next);
        }
        return result;
        
    }
};

12. Divide Two Integers (LeetCode-29)

  题意: 两个整数作除法,不能用乘、除与mod。
  思路: 模拟计算机内部对整数的除法操作,用移位及减法来实现。
  考察点: 除法的替代过程
  积累: 强背下来,注意long long和int的转换,防止溢出。判读符号位时可以用异或。

class Solution {
public:
    int divide(int dividend, int divisor) {
        long long num = abs((long long) dividend);
        long long den = abs((long long) divisor);
        int flag = (dividend < 0) ^ (divisor < 0) ? -1 : 1;
        long long ans = 0;
        while (num >= den) {
            long long temp = den;
            long long temp_ans = 1;
            while (temp << 1 < num) {
                temp = temp << 1;
                temp_ans = temp_ans << 1;
            }
            num -= temp;
            ans += temp_ans;
        }
        if (flag == -1) ans = -ans;
        if (ans > INT_MAX) ans = INT_MAX;
        else if (ans < INT_MIN) ans = INT_MIN;
        return ans;
    }
};

13. Pow(x, n) (LeetCode-50)

  题意: 实现x^n,x为double浮点数,n为有符号的32位整数int。
  思路: 可以用O(n)的一次for循环来计算,但是还可以用O(logN)的二分法来实现,由幂的二次根号来实现。
  考察点: 二分搜索实现O(logN)
  积累: 要注意n的正负还有n为负时取long来避免-n越界。

class Solution {
public:
    double myPow(double x, int n) {
        if(x == 1.0) return 1.0;
        long m = n;
        if (m < 0) return 1 / power(x, -m);
        return power(x, m);
    }
    double power(double x, long n) {
        if (n == 0) return 1.0;
        double half = power(x, n / 2);
        if (n % 2 == 0) return half * half;
        return x * half * half;
    }
};

14. Sqrt(x) (LeetCode-69)

  题意: 实现输入x的二次平方根,输出n为整数。
  思路: 可以O(n)法一次遍历,找到n;可以有更快的O(logN)的二分搜索法来找到n
  考察点: 二分搜索
  积累:

class Solution {
public:
    int mySqrt(int x) {
        long l = 1;
        long r = static_cast<long>(x) + 1;
        while (l < r) {
            long m = l + ((r - l) >> 1);
            if (m * m > x) r = m;
            else l = m + 1;
        }
        return l - 1;
    }
};

15. Implement Rand10() Using Rand7() (LeetCode-470)

  题意: 利用随机数7的函数实现随机数10的函数。
  思路: 我们可以先凑出 rand10N(),然后再通过 rand10N() % 10 + 1 来获得 rand10()。那么,只需要将 rand7() 转化为 rand10*N() 即可,根据前面的讲解,我们转化也必须要保持等概率,那么就可以变化为 (rand7() - 1) * 7 + rand7(),就转为了 rand49()。这里,我们需要把 rand49() 转为 rand40(),需要用到 拒绝采样 Rejection Sampling。简单来说,这种采样方法就是随机到需要的数字就接受,不是需要的就拒绝,并重新采样,这样还能保持等概率。当用 rand49() 生成一个 [1, 49] 范围内的随机数,如果其在 [1, 40] 范围内,我们就将其转为 rand10() 范围内的数字,直接对 10 去余并加1,返回即可。如果不是,则继续循环即可。
  考察点: 数学题,对概率要有认识。
  积累: 等概率分布,如果是rand6()怎么办?

class Solution {
public:
    int rand10() {
        int index = INT_MAX;
        while (index > 40) 
            index = 7*(rand7() - 1) + rand7();
        return index % 10 + 1;
    }
};

16. Count Primes(LeetCode-204)

  题意: 寻找1~n中质数的个数
  思路: 最直接想到的就是O(n^2)的思路,每一个数都判断是不是质数,但是这样效率太低。可以有O(n)的思路。即记录在一次for循环中,在寻到i时,用哈希表记录i的1次倍数、2次倍数、3次倍数等出现情况。如果在后续的循环中,如果此数出现过,就continue;
  考察点: 质数的定义
  积累: 用另一种方法来寻找质数

class Solution {
public:
    int countPrimes(int n) {
        if(n < 2) return 0;
        vector<bool> isDeteced(n,false);
        int ans = 0;
        for (int i = 2; i < n; ++i) {
            if (isDeteced[i]) continue;
            ans++;
            for (unsigned int times = 1; times * i < n; ++times) {
               isDeteced[times* i] = true; 
            }
        }
        return ans;
    }
};

17. Ugly Number(LeetCode-263)

  题意: 因子中只包含2,3,5的数为丑数,判断一个数是否是丑数。
  思路: 整除2,3,5,看剩下的数是否为1
  考察点: 如果用取余和整除来判断丑数
  积累: 用最简便的语言来实现

class Solution {
public:
    bool isUgly(int num) {
        const vector<int> factors{2, 3, 5};
        for (const int factor : factors)
            while (num && num % factor == 0) num /= factor;
        return num == 1;
    }
};

18. Ugly NumberII(LeetCode-264)

  题意: 寻找到第n个丑数。
  思路: 不能满足每个数都判断是不是丑数来求解,要采用哈希的思想来存储丑数,一直找到第n个丑数。
  考察点: 与求解质数个数思路相同,用存储方法来求解。
  积累: 掌握存储法来求解

class Solution {
public:
    int nthUglyNumber(int n) {
        
        int index2 = 0;
        int index3 = 0;
        int index5 = 0;
        
        vector<int> nums{1};
        
        while(nums.size() < n) {
            int next2 = nums[index2] * 2;
            int next3 = nums[index3] * 3;
            int next5 = nums[index5] * 5;
            int next = min(next2,min(next3,next5));
            if(next == next2)  index2++;
            if(next == next3)  index3++;
            if(next == next5)  index5++;
            
            nums.push_back(next);
        }
        return nums[n - 1];
      
    }    
  
};

19. Super Ugly Number(LeetCode-313)

  题意: 找到只包含给定因子的第n个丑数
  思路: 与找2,3,5的丑数方法相同
  积累: min_element的使用

class Solution {
public:
    int nthSuperUglyNumber(int n, vector<int>& primes) {
        int len = primes.size();
        vector<int> index(len,0);
        vector<int> nums{1};
        vector<int> temp(len);
        while(nums.size() < n) {
            for(int i = 0; i < len; i++) 
                temp[i] = nums[index[i]]*primes[i];
            int min_val = *min_element(temp.begin(),temp.end());
            for(int i = 0; i < len; i++) {
                if(min_val == temp[i])
                    index[i]++;
            }
            nums.push_back(min_val);
        }
        return nums[n - 1];
    }
};

20. Base 7(LeetCode-504)

  题意: 将给定的整数转换成七进制的字符串
  思路: 取余后再取除是10进制数转换别的进制的方法
  **积累:**记住进制间的转换方法,注意负数。

class Solution {
public:
    string convertToBase7(int num) {
        if (num == 0) return "0";
        bool flag = num < 0;
        num = abs(num);
        string ans = "";
        while (num > 0) {
            ans = to_string(num % 7) + ans;
            num /= 7;
        }
        if (flag) ans = "-" + ans;
        return ans;
    }
};

21. Maximum Subarray(LeetCode-53)

  题意: 求数组中连续子数组的最大和
  思路: 一遍for循环,当累加和为负时,设置累加和为当前值,否则继续累加。
  考察点: 数组的灵活掌握,何种情况下连续数组的和最大
  积累: 熟记此题

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int ans = INT_MIN;
        int sum = 0;
        for (auto num:nums) {
            if (sum < 0) sum = num;
            else sum += num;
            ans = max(ans,sum);
        }
        return ans;
    }
};

22. Missing Number(LeetCode-268)

  题意: n维数组中为0~n范围内的数,查出哪个数不在其中
  思路: 可以用累加和,也可以用异或的思路
  积累: 异或的性质

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int ans = nums.size();
        for (int i = 0; i < nums.size(); ++i) {
            ans = ans ^ nums[i] ^ i;
        }
        return ans;
    }
};

23. Rotate Image(LeetCode-48)

  题意: 将一个n*n的数组顺时针旋转90°
  思路: 现将最外层的vector逆序,即行逆序,再颠倒对角线上的元素。
  积累: 找规律,记下来思路。对角线元素转置怎么实现???

class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {
        reverse(matrix.begin(),matrix.end());
        for (int i = 0; i < matrix.size(); ++i) {
            for (int j = i + 1; j < matrix.size(); ++j) {
                swap(matrix[i][j],matrix[j][i]);
            }
        }
    }
};

24. Reverse Bits(LeetCode-190)

  题意: 将一个32位的无符号整数,按位进行逆操作。
  思路: 从尾到头来判断是否为1,从头到尾来进行1的值位操作
  积累: 移位,|,&操作要熟悉

class Solution {
public:
    uint32_t reverseBits(uint32_t n) {
        uint32_t flag = 1;
        uint32_t result = 0;
        uint32_t val = 0x80000000;
        
        for(int i = 0; i < 32; ++i) {
            if(flag&n) {
                result = result|val;
            }
            flag = flag << 1;
            val = val >> 1;
        }
        return result;
    }
};

25. Number of 1 Bits(LeetCode-191)

  题意: 计算出无符号整数中的1的个数
  思路: 最开始想到的就是32次循环来计算1的个数,还有另外一种方法就是(n-1)&n就是将最低位的1置零,有多少次这种操作就有多少个1。
  积累: 记住(n-1)&n的操作

class Solution {
public:
    int hammingWeight(uint32_t n) {
        int ans = 0;
        while(n) {
            n = (n - 1)&n;
            ans++;
        }
        return ans;
    }     
};

26. Sum of Two Integers(LeetCode-371)

  题意: 计算两个32位整数的加法,不许使用+和-操作
  思路: 求和可以用异或来表示(但是不包括进位),进位用与操作来表示
  积累: 记住两个整数的加法操作用异或和与操作来进行

class Solution {
public:
    int getSum(int a, int b) {
        if(b == 0) return a;        // when carry is zero, return
        int sum = a ^ b;        // calculate sum without carry
        int carry = (unsigned int ) (a & b) << 1;       // calculate carry
        return getSum(sum, carry);
    }
};

27. Complement of Base 10 Integer(LeetCode-1009)

  题意: 10进制数的二进制表示,并将其转换为与其对应的补数
  思路: 先将10进制数转换为2进制数,在转换的同时进行去补操作。去补操作用异或来
  积累: 十进制转二进制如何转换,一位取补用异或来操作

class Solution {
public:
    int bitwiseComplement(int N) {
        if(N == 1) return 0;
        if(N == 0) return 1;
        int ans = 0;
        int digits = 1;
        while (N) {
            ans += digits*((N % 2) ^ 1);
            digits = digits << 1;
            N = N / 2;
        }
        return ans;
    }
};

28. Evaluate Reverse Polish Notation(LeetCode-150)

  题意: 逆波兰表达式,[“4”, “13”, “5”, “/”, “+”]表示为(4 + (13 / 5)) = 6
  思路: 用栈来实现
  积累: 记住逆波兰表达式,记住atoi,stoi和string类型的转换为char用.c_str

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
         stack<int> s;
        for (auto a : tokens) {
            if (a.size() == 1 && !isdigit(a[0])) {  // check if an operator
                int num2 = s.top();
                s.pop();
                int num1 = s.top();
                s.pop();
                switch (a[0]) {  // note switch use char or integer
                    case '+':
                        s.push(num1 + num2);
                        break;
                    case '-':
                        s.push(num1 - num2);
                        break;
                    case '*':
                        s.push(num1 * num2);
                        break;
                    case '/':
                        s.push(num1 / num2);
                        break;
                }
            } else {  // if an number push to stack
                s.push(atoi(a.c_str()));
            }
        }
        return s.top();
    }
};

29. Valid Parentheses(LeetCode-20)

  题意: 给定一组字符串只包含’(’, ‘)’, ‘{’, ‘}’, ‘[’,’]’,判断是否为有效的括号表达式
  思路: 用栈来实现,如果左括号就push栈中,右括号的话就判断栈顶元素是否其匹配
  积累: 这是括号题中最基础的一道

class Solution {
public:
    bool isValid(string s) {
        stack<char> st;
        for (auto m:s) {
            if (m == '(' || m == '{' || m == '[')
                st.push(m);
            else if (m == ')') {
                if (st.size() == 0) return false;
                if (st.top() != '(') return false;
                st.pop();
            } else if (m == ']') {
                if (st.size() == 0) return false;
                if (st.top() != '[') return false;
                st.pop();
            } else if (m == '}') {
                if (st.size() == 0) return false;
                if (st.top() != '{') return false;
                st.pop();
            }    
        }
        return st.size() == 0;
    }
};

30. String to Integer (atoi)(LeetCode-8)

  题意: 将string类型转换为int类型,如果超过最大最小值就等于最大最小值,非法表示用0返回
  思路: 空格只能出现在符号位或者数字之前,符号位只能出现在符号位之前,并且只能出现一次,做好各种逻辑判断,并且在做运算之前已经越界,要返回最大最小值。
  积累: 记下来,这是基本题,想好各种corner case

class Solution {
public:
    int myAtoi(string str) {
        if (str.empty()) return 0;
        long long ans = 0;
        int flag = 1;
        bool num_flag = false;
        bool flag_flag = false;
        for (auto m : str) {
            if (m == ' ') {
                if (flag_flag) break;
                if (num_flag) break;
                continue;
            } else if (m == '+' || m == '-') {
                if (num_flag) break;
                if (flag_flag) break;
                flag = m == '+' ? 1:-1;
                flag_flag = true;
                continue;
            } else if (m >= '0' && m <= '9') {
                num_flag = 1;
                if ((flag * ans * 10) > INT_MAX) return INT_MAX;
                if ((flag * ans * 10) < INT_MIN) return INT_MIN;
                ans *= 10;
                if ( (flag * (ans + (m - '0'))) > INT_MAX) return INT_MAX;
                if ((flag * (ans + (m - '0'))) < INT_MIN) return INT_MIN;
                ans += (m - '0');
            } else break;
        }
        return flag * ans;
    }
};

31. Permutations (LeetCode-46)

  题意: 无重复数的排列
  思路: 用DFS实现
  积累: 记住排列题用dfs

class Solution {
public:
    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int>> ans;
        vector<int> curr;
        vector<int> used(nums.size(),0);
        DFS(nums,curr,ans,used);
        return ans;
    }
    void DFS(vector<int>& nums,vector<int>& curr,vector<vector<int>>& ans,vector<int>& used) {
        if (curr.size() == nums.size()) {
            ans.push_back(curr);
            return;
        }
        for (int i = 0; i < nums.size(); ++i) {
            if (used[i] == 1) continue;
            curr.push_back(nums[i]);
            used[i] = 1;
            DFS(nums,curr,ans,used);
            curr.pop_back();
            used[i] = 0;
        }
    }
};

32. PermutationsII (LeetCode-47)

  题意: 重复数的排列
  思路: 用DFS实现,关键是如何处理重复的数据,先排序,用重复的数据中的第一个来进行排列。如果当前的值为重复值,则只要前面的值没有被使用过,则当前值就不可以被使用。这样确保了只有第一个出现的重复值可以算进结果集,后序重复的情况不会被添加进结果集。
  积累: 记住有重复数据的排列题

class Solution {
public:
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        if (nums.size() == 0) return{};
        vector<vector<int>> ans;
        vector<int> used(nums.size(),0);
        vector<int> curr;
        sort(nums.begin(),nums.end(),greater<int>());
        DFS(nums,used,curr,ans);
        return ans;
    }
    void DFS(vector<int>& nums,vector<int>& used,vector<int>& curr,vector<vector<int>>& ans) {
        if (curr.size() == nums.size()) {
            ans.push_back(curr);
            return;
        }
        for (int i = 0; i < nums.size(); ++i) {
            if (used[i] == 1) continue;
            if (i != 0 && nums[i] == nums[i - 1] && used[i - 1] == 0) continue;
            used[i] = 1;
            curr.push_back(nums[i]);
            DFS(nums,used,curr,ans);
            used[i] = 0;
            curr.pop_back();
        }
    }
};

33. Next Permutation (LeetCode-31)

  题意: 写出比自身大的下一个排列
  思路:
  a)从后向前查找第一个相邻元素对(i,j),并且满足A[i] < A[j]。易知,此时从j到end必然是降序。可以用反证法证明,请自行证明。

  b)在[j,end)中寻找一个最小的k使其满足A[i]<A[k]。由于[j,end)是降序的,所以必然存在一个k满足上面条件;并且可以从后向前查找第一个满足A[i]<A[k]关系的k,此时的k必是待找的k。

  c)将i与k交换。此时,i处变成比i大的最小元素,因为下一个全排列必须是与当前排列按照升序排序相邻的排列,故选择最小的元素替代i。易知,交换后的[j,end)仍然满足降序排序。因为在(k,end)中必然小于i,在[j,k)中必然大于k,并且大于i。

  d)逆置[j,end)由于此时[j,end)是降序的,故将其逆置。最终获得下一全排序。
  积累:

class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        
    int i = nums.size() - 2;
        
    while (i >= 0 && nums[i + 1] <= nums[i]) 
        --i;
        
    if (i >= 0) {
        int j = nums.size() - 1;
        
        while (j >= 0 && nums[j] <= nums[i]) 
            --j;
        
        swap(nums[i], nums[j]);
    }
        
    reverse(begin(nums) + i + 1, end(nums));       
    }
};

34. Subsets (LeetCode-78)

  题意: 给定一个无重复数组集合,生成所有子集
  思路: 用dfs,dfs中会增加一个start和长度变量
  积累:

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        if (nums.size() == 0) return {};
        vector<vector<int>> ans;
        vector<int> curr;
        for (int i = 0; i <= nums.size(); ++i)
            DFS(nums,curr,ans,0,i);
        return ans;  
    }
    void DFS(vector<int>& nums,vector<int>& curr,vector<vector<int>>& ans,int start,int len) {
        if (curr.size() == len) {
            ans.push_back(curr);
            return;
        }
        for (int i = start; i < nums.size(); ++i) {
            curr.push_back(nums[i]);
            DFS(nums,curr,ans,i + 1,len);
            curr.pop_back();
        }
    }
};

35. SubsetsII (LeetCode-90)

  题意: 给定一个有重复数组集合,生成所有子集
  思路: 用dfs
  积累:

class Solution {
public:
    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
        if (nums.size() == 0) return{};
        vector<vector<int>> ans;
        vector<int> curr;
        sort(nums.begin(),nums.end(),greater<int>());
        for (int i = 0; i <= nums.size(); ++i) {
            DFS(nums,0,i,curr,ans);
        }
        return ans;
        
    }
    void DFS(vector<int>& nums,int start,int len,vector<int>& curr,vector<vector<int>>& ans) {
        if (curr.size() == len) {
            ans.push_back(curr);
            return;
        }
        for (int i = start; i < nums.size(); ++i) {
            if (i != start && nums[i] == nums[i - 1]) continue;
            curr.push_back(nums[i]);
            DFS(nums,i + 1,len,curr,ans);
            curr.pop_back();
        }
    }
};

36. Combinations (LeetCode-77)

  题意: 给定一个正整数n和一个正整数k,生成1…n范围内所有k个数的组合
  思路: 用dfs
  积累:

class Solution {
public:
    vector<vector<int>> combine(int n, int k) {
        if(k > n) return{};
        vector<vector<int>> ans;
        vector<int> vec;
        DFS(k,0,ans,vec,n);
        return ans;
    }
    void DFS(int depth,int start,vector<vector<int>>& ans,vector<int>& vec,int n) {
        if(vec.size() == depth) {
            ans.push_back(vec);
            return;
        }
        for(int i = start; i < n; ++i) {
            vec.push_back(i + 1);
            DFS(depth,i + 1,ans,vec,n);
            vec.pop_back();
        }
    }
};

37. Letter Case Permutation (LeetCode-784)

  题意: 将字符串中的字母进行大小写变换以求得全排列
  思路: DFS法,记住先走一步
  积累: 小写字母的ASCII码比大写字母多32,刚好是(1 << 5),所以大小写字母转换可以用^(1 << 5)。isalpha判断是否为字母

class Solution {
public:
    vector<string> letterCasePermutation(string S) {
        if(S.size() == 0) return{};
        vector<string> ans;
        DFS(S,ans,0);
        return ans;
        
    }
    void DFS(string& S,vector<string>& ans,int i) {
        if(i == S.size()) {
            ans.push_back(S);
            return;
        }
        DFS(S,ans,i + 1);
        if(!isalpha(S[i])) return;
        S[i] ^= 1 << 5;
        DFS(S,ans,i + 1);
        S[i] ^= 1 << 5;
    }
};

38. Letter Combinations of a Phone Number (LeetCode-17)

  题意: 给定一组数字“2~9”的字符串,按照电话号码的顺序生成字母排列
  思路: DFS思路就可以实现,主要是针对这种题目要建模好
  积累:

class Solution {
public:
    vector<string> letterCombinations(string digits) { 
        if(digits.empty()) return{};
        vector<vector<char>> d(10);
        d[0] = {' '};
        d[1] = {};
        d[2] = {'a','b','c'};
        d[3] = {'d','e','f'};
        d[4] = {'g','h','i'};
        d[5] = {'j','k','l'};
        d[6] = {'m','n','o'};
        d[7] = {'p','q','r','s'};
        d[8] = {'t','u','v'};
        d[9] = {'w','x','y','z'};
        vector<string> ans;
        string cur;
        DFS(digits,d,cur,0,ans);
        return ans;
    }
    void DFS(string& digits,vector<vector<char>>& d,string& cur,int depth,vector<string>& ans) {
        if(depth == digits.size()) {
            ans.push_back(cur);
            return;
        }
        for(const char c : d[digits[depth] - '0']) {
            cur.push_back(c);
            DFS(digits,d,cur,depth + 1,ans);
            cur.pop_back();
        }
    }
};

39. Palindrome Partitioning (LeetCode-131)

  题意: 给定一组字符串,将其分割为每部分都是回文的字符串,生成所有的分割可能。
  思路: DFS思路,与subsets找子集思想很像,只是多了一步判断是否是回文
  积累: 如何判断一个字符串的[i,j]两端是回文子串要牢牢记住

class Solution {
public:
    vector<vector<string>> partition(string s) {
        vector<vector<string>> ans;
        vector<string> curr;
        dfs(s,ans,curr,0);
        return ans;
    }
    void dfs(string s,vector<vector<string>>& ans,vector<string>& curr,int start) {
        if (start == s.length()) {
            ans.push_back(curr);
            return;
        }
        for (int i = start; i < s.length(); ++i) {
            if (IsPalindrome(s,start,i)) {
                curr.push_back(s.substr(start,i - start + 1));
                dfs(s,ans,curr,i + 1);
                curr.pop_back();
            }
        }
    }
    bool IsPalindrome(string s,int start,int end) {
        while (start < end && s[start] == s[end]) {
            start++;
            end--;
        }
        return start >= end;
    }
};

40. Generate Parentheses (LeetCode-22)

  题意: 给定一个正整数n,生成所有n对括号排列组合,且组合必须是正确的
  思路: DFS,判断左右括号的个数来进行到底是左括号还是右括号加入到dfs中
  积累:

class Solution {
public:
    vector<string> generateParenthesis(int n) {
        if (n <= 0)
            return {};
        vector<string> ans;
        dfs(0, 0, n, "",ans);
        return ans;
    }
    void dfs(int l, int r, int n, string cur,vector<string>& ans) {
        if (l == n && r == n) {
            ans.push_back(cur);
            return;
        }
        if (l < n)
            dfs(l + 1, r, n, cur + "(", ans);

        if (r < l)
            dfs(l, r + 1, n, cur + ")", ans);
    }
};

41. Two Sum (LeetCode-1)

  题意: 给定一个数组和一个目标值,找出数组中两个数字的和为target的索引值
  思路: 可以用暴力搜索O(n^2)来实现。用哈希表可以实现O(n)。哈希表中key为数组值,value为索引值
  积累: 哈希表额灵活运用

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int,int> map;
        vector<int> ans;
        for (int i = 0; i < nums.size(); ++i) {
            
            if(map.find(target - nums[i]) != map.end()) {
                ans.push_back(i);
                ans.push_back(map[target - nums[i]]);
                break;
            }
            map[nums[i]] = i;
        }
        return ans; 
    }
};

42. 3Sum (LeetCode-15)

  题意: 在数组中寻找到和为零的三个数的所有组成。
  思路: 先排序,最外层循环每次一个数为基本点,
  考察点: 思路清晰,逻辑清楚就能解决出来
  积累: 排序sort函数,sort(nums.begin(),nums.end(),less())->由小到大排序,sort(nums.begin(),nums.end(),greater())->由大到小排序,

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        if (nums.size() < 3) return {};
        sort(nums.begin(),nums.end(),less<int>());
        vector<vector<int>> ans;
        for (int i = 0; i < nums.size(); ++i) {
            if (nums[i] > 0) break;
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            int j = i + 1;
            int k = nums.size() - 1;
            int target = 0 - nums[i];
            while (j < k) {
                if (nums[j] + nums[k] == target) {
                    ans.push_back({nums[i],nums[j],nums[k]});
                    while (j < k && nums[j] == nums[j + 1])
                        j++;
                    while (j < k && nums[k] == nums[k - 1])
                        k--;
                    j++;
                    k--;
                }
                else if (nums[j] + nums[k] > target)
                    k--;
                else j++;
            } 
        }
        return ans;
    }
};

43. 3Sum With Multiplicity (LeetCode-923)

  题意: 给定数组和一个目标值,找到数组中满足所有三个数的和为target的目标值个数
  思路: 用哈希表现存储下来数组中的元素出现的个数,再分情况利用排列组合公式求出结果
  考察点: 逻辑思维,建模能力

class Solution {
public:
    int threeSumMulti(vector<int>& A, int target) {
        constexpr int kMaxN = 100;
        constexpr int kMod = 1e9 + 7;
        vector<long> c(kMaxN + 1, 0);
        for (int a : A) ++c[a];
        long ans = 0;
        for (int i = 0; i <= target; ++i) {
            for (int j = i; j <= target; ++j) {
                const int k = target - i - j;
                if (k < 0 || k >= c.size() || k < j) continue;
                if (!c[i] || !c[j] || !c[k]) continue;
                if (i == j && j == k)
                    ans += (c[i] - 2) * (c[i] - 1) * c[i] / 6;
                else if (i == j && j != k)
                    ans += ((c[i] * (c[i] - 1)) / 2) * c[k];
                else if (i != j && j == k)
                    ans += c[i] * (((c[j] - 1) * c[j]) / 2);
                else
                    ans += c[i] * c[j] * c[k];        
            }
        }
        return ans % kMod;
    }
};

44. 4Sum (LeetCode-18)

  题意: 给定一个数组和一个target,找到四个数的和为target的目标总数
  思路: 与3sum思路相同
  考察点: 建模逻辑能力
  积累: erase与unique用法。

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector< vector<int> > ans;
        if (nums.size() < 4) return ans;
        
        sort(nums.begin(), nums.end());
        for (int i = 0; i < nums.size() - 3; i ++)
        {
            for (int j = i + 1; j < nums.size() - 2; j ++)
            {
                int l = j + 1, r = nums.size() - 1;
                while(l < r)
                {
                    if (nums[i] + nums[j] + nums[l] + nums[r] < target)
                        l ++;
                    else if (nums[i] + nums[j] + nums[l] + nums[r] > target)
                        r --;
                    else
                    {
                        ans.push_back({nums[i], nums[j], nums[l], nums[r]});
                        l ++;
                        r --;
                    }
                }
            }
        }
        sort(ans.begin(), ans.end());
        ans.erase(unique(ans.begin(), ans.end()), ans.end()); 
        return ans;
    } 
};

45. 4SumII (LeetCode-454)

  题意: 给定四个都是整数值的数组A、B、C、D,计算有多少个(i,j,k,l)使得A[i]+B[j]+C[k]+D[l]=0
  思路: 用哈希表,key为sum,value为个数。
  考察点: 哈希表灵活运用
  积累: 与 two sum很像!!!

class Solution {
public:
    int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) {
        unordered_map<int, int> hash1;
        int ans = 0;
        for(int i = 0; i < A.size(); i++) {
            for(int j = 0; j < B.size(); j++)
                hash1[A[i]+B[j]]++;
        }
        for(int i = 0; i < C.size(); i++) {
            for(int j = 0; j < D.size(); j++)
                ans += hash1.count(-C[i] - D[j])? hash1[-C[i] - D[j]]: 0;
        }
        return ans;
    }
};

45. Fraction to Recurring Decimal(LeetCode-166)

  题意: 给一个分子,一个分母,用字符串表示为小数形式,如果是循环小数,加入循环节。
  思路: 用哈希表来存储,key为余数,value为出现的位置。
  考察点: 除法运算的抽象表达
  积累: string.insert如何使用

class Solution {
public:
    string fractionToDecimal(int numerator, int denominator) {
        if (numerator == 0) return "0";
        long long int n = numerator;
        long long int d = denominator;
        string ans;
        if (n > 0 ^ d > 0)
            ans += '-';
        n = abs(n);
        d = abs(d);
        ans += to_string (n / d);
        long long int r = (n % d);
        if (r == 0) return ans;
        else ans += '.';
        
        unordered_map<int,int> kv;
        while (r) {
            
            if (kv.find(r) != kv.end()) {
                ans.insert(kv[r],1,'(');
                ans += ')';
                break;
            }
            kv[r] = ans.size();
            
            r *= 10;
            ans += to_string(r/d);
            r %= d;
        }
        return ans;
    }
};

46. Happy Number(LeetCode-202)

  题意: 给定一个数字,判断它是否为happy number,happy number定义为每位数字的和最终能加到1。
  思路: 与循环节思想很像,怎么判断一个数不能最终成为happy number,用哈希表来存储它是否出现过,如果出现过那肯定不能成为happy number。key为按位进行加法后的数,value为其出现的次数。
  考察点: 哈希表,一个数按位来进行和运算

class Solution {
public:
    bool isHappy(int n) {
        if(n <= 0) return false;
        unordered_map<int,int> st;
        while(st.find(n) == st.end()) {
            st[n]++;
            n = sum_digits(n);
            if(n == 1) return true;
        }
        return false;
        
    }
    int sum_digits(int n) {
        int ans = 0;
        while(n) {
            ans += (n % 10)*(n % 10);
            n /= 10;
        }
        return ans;
    }
};

47. Kth Largest Element in an Array(LeetCode-215)

  题意: 找到无序数组中第K个大的数
  思路: 用大顶堆来实现
  考察点: 优先队列的使用

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        priority_queue<int,vector<int>,greater<int>> store;
        for (const auto& num:nums) {
            store.push(num);
            if(store.size() > k) store.pop();
        }
        return store.top();
    }
};

48. Top K Frequent Elements(LeetCode-347)

  题意: 找到数组中出现频率最高的K个数
  思路: 哈希表和桶思想,哈希表来存储元素出现的次数。桶用来将次数出现相同的元素放在一起
  考察点: map与unordered_map的使用

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int,int> count;
        map<int,vector<int>,greater<int>> bucket;
        vector<int> ans;
        int max_freq = 0;
        for (auto& num:nums) {
            count[num]++;
            max_freq = max(max_freq,count[num]);
        }
        for (auto& kv:count)
            bucket[kv.second].push_back(kv.first);
        for (auto& m:bucket) {
            for (auto& n:m.second) {
                ans.push_back(n);
                if (ans.size() >= k)
                    return ans;
            }
        }
        return ans;
    }   
};

49. Top K Frequent Words(LeetCode-692)

  题意: 统计出在一系列的单词中,出现频率最高的K个单词
  思路: 与Top K Frequent Elements题思路一样
  积累: priority_queue做比较如何实现

class Solution {
private:
    typedef pair<string, int> Node;
    struct cmp{
        bool operator() (Node a,Node b) {
            if (a.second == b.second) 
                return  a.first < b.first;
            return a.second > b.second;
        }
    };   
public:
    vector<string> topKFrequent(vector<string>& words, int k) {
        unordered_map<string, int> count;
        for (const string& word : words)
            ++count[word];
        // Min heap by frequency
        priority_queue<Node,vector<Node>,cmp> q;
        
        // O(n*logk)
        for (const auto& kv : count) {
            q.push(kv);
            if (q.size() > k) q.pop();
        }
        vector<string> ans;
        while (!q.empty()) {
            ans.push_back(q.top().first);
            q.pop();
        }
        std::reverse(ans.begin(), ans.end());
        return ans;
    }
};

51. Subarray Sum Equals K(LeetCode-560)

  题意: Given an array of integers and an integer k, you need to find the total number of continuous subarrays whose sum equals to k.
  思路: 暴力求解需要O(n^2)的时间复杂度,可以利用哈希表来实现O(n)的时间复杂度。用一个哈希表来建立连续子数组之和跟其出现次数之间的映射,初始化要加入 {0,1} 这对映射,因为我们的解题思路是遍历数组中的数字,用 sum 来记录到当前位置的累加和,我们建立哈希表的目的是为了让我们可以快速的查找 sum-k 是否存在,即是否有连续子数组的和为 sum-k,如果存在的话,那么和为k的子数组一定也存在,这样当 sum 刚好为k的时候,那么数组从起始到当前位置的这段子数组的和就是k,满足题意,如果哈希表中事先没有 m[0] 项的话,这个符合题意的结果就无法累加到结果 res 中,这就是初始化的用途。

class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        if(nums.size() == 0) return 0;
        unordered_map<int,int> sum_hash{{0,1}};
        int sum_ = 0;
        int ans = 0;
        for (int i = 0; i < nums.size(); ++i) {
            sum_ += nums[i];
            ans += sum_hash[sum_ - k];
            ++sum_hash[sum_];
        }
        return ans;
    }
};

52. Continuous Subarray Sum(LeetCode-523)

  题意: Given a list of non-negative numbers and a target integer k, write a function to check if the array has a continuous subarray of size at least 2 that sums up to a multiple of k, that is, sums up to n*k where n is also an integer.
  思路: 那就是,若数字a和b分别除以数字c,若得到的余数相同,那么(a-b)必定能够整除c。对于本题,求出从序列nums从0开始到end的子序列之和,记录其除以K的余数q,若有两个子序列余数相同,并且相应的endend差值大于1,则说明所求子序列存在,否则便不存在。

class Solution {
public:
    bool checkSubarraySum(vector<int>& nums, int k) {
        unordered_map<int, int> hash;
        int sum = 0;
        hash[0] = -1;
        
        for(int i = 0; i < nums.size(); ++i) {
            sum += nums[i];
            int t = (k == 0) ? sum : (sum % k);
            if(hash.find(t) != hash.end()) {
                if(i - hash[t] > 1) return true;
            } else hash[t] = i;
        }
        return false;
    }
};

53. Remove Nth Node From End of List(LeetCode-19)

  积累: 双指针思想

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode dummy(0);
        ListNode* tail = &dummy;
        tail->next = head;
        ListNode* p_fast = tail;
        ListNode* Node = tail;
        for(int i = 0; i <= n ; ++i)
            p_fast = p_fast->next;
        while(p_fast != nullptr) {
            p_fast = p_fast->next;
            Node = Node->next;
        }
        if(Node != nullptr && Node->next != nullptr)
           Node->next = Node->next->next;
        return tail->next;
    }
};

54. Merge Two Sorted Lists(LeetCode-21)

  积累: 递归和迭代方法都可以

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode dummy(0);
        ListNode* tail = &dummy;
        while(l1 != nullptr && l2 != nullptr ) {
            if(l1->val > l2->val) swap(l1,l2);
            tail->next = l1;
            l1 = l1->next;
            tail = tail->next;
        }
        
        tail->next = l1?l1:l2;
        return dummy.next;
        
    }
};
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if(l1 == nullptr) return l2;
        if(l2 == nullptr) return l1;
        if(l1->val <= l2->val) {
            ListNode* l = new ListNode(l1->val);
            l->next = mergeTwoLists(l1->next,l2);
            return l;
        } else {
            ListNode* l = new ListNode(l2->val);
            l->next = mergeTwoLists(l1,l2->next);
            return l;
        }
    }
};

55. Swap Nodes in Pairs(LeetCode-24)

  题意: 交换链表中的节点,Given 1->2->3->4, you should return the list as 2->1->4->3.

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if (head == nullptr || head->next == nullptr)
            return head;
        ListNode dummy(0);
        ListNode* tail = &dummy;
        tail->next = head;
        
        auto curr_ = head;
        auto prev_ = tail;
        auto next_ = head->next;
        
        while (curr_->next != nullptr) {
            curr_->next = next_->next;
            next_->next = curr_;
            prev_->next = next_;
            
            prev_ = curr_;
            curr_ = curr_->next;
            if (curr_ == nullptr) break;
            next_ = curr_->next;
        }
        return dummy.next;
    }
};

56. Rotate List(LeetCode-61)

  题意: 链表移位
Input: 1->2->3->4->5->NULL, k = 2
Output: 4->5->1->2->3->NULL
Explanation:
rotate 1 steps to the right: 5->1->2->3->4->NULL
rotate 2 steps to the right: 4->5->1->2->3->NULL

class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if(k == 0 || head == nullptr || head->next == nullptr)
            return head;
        int len = get_length(head);
        if(k % len == 0) return head;
        else if(len > k) 
            return cut_and_connect(head,len - k);
        else 
            return cut_and_connect(head,len - k % len);    
    }
    int get_length(ListNode* head) {
        if(head == nullptr) return 0;
        int ans = 0;
        while(head != nullptr) {
            ans++;
            head = head->next;
        }
        return ans;
    }
    ListNode* cut_and_connect(ListNode* head,int k) {
        ListNode* p1_l = head;
        ListNode* p1_r = nullptr;
        ListNode* p2_l = nullptr;
        ListNode* p2_r = nullptr;
        ListNode* prev_ = nullptr;
        int count = 0;
        
        while(head != nullptr) {
            if(count++ == k ) {
                p1_r = prev_;
                p2_l = head;
            }
            prev_ = head;
            head = head->next;
        }
        p2_r = prev_;
        
        if(p2_r != nullptr) p2_r->next = p1_l;
        
        if(p1_r != nullptr) p1_r->next = nullptr;
        
        return p2_l;
    }
};

57. Remove Duplicates from Sorted List(LeetCode-83)

  题意:
Input: 1->1->2->3->3
Output: 1->2->3

class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if(head == nullptr || head->next == nullptr) return head;
        ListNode* node = head;
        
        while(node != nullptr) {
            ListNode* p_next = node->next;
            while(p_next != nullptr && p_next->val == node->val)
                p_next = p_next->next;
            
            node->next = p_next;
            node = node->next;
        }
        return head;
    }
};

58. Remove Duplicates from Sorted List II(LeetCode-82)

  题意:
Input: 1->2->3->3->4->4->5
Output: 1->2->5

class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if(!head||!head->next) return head;
        ListNode* dummy = new ListNode(0);
        ListNode* tail = dummy;
        int flag = true; 
        while(head){
            while(head && head->next && head->val == head->next->val) {
                flag = false; 
                head = head->next;
            }
            if(flag)  {           
                tail->next = head;
                tail = tail->next;
            }
            head = head->next;
            flag = true; 
        }
        tail->next = nullptr; 
        return dummy->next;
    }
};

59. Partition List(LeetCode-86)

  题意:
Input: head = 1->4->3->2->5->2, x = 3
Output: 1->2->2->4->3->5

class Solution {
public:
    ListNode* partition(ListNode* head, int x) {
        if(head == nullptr) return nullptr;
        ListNode* Node = head;
        
        ListNode* ans_before = new ListNode(0);
        ListNode* ans_after = new ListNode(0);
        ListNode* p2 = ans_after;
        ListNode* p1 = ans_before;
        
        while(Node != nullptr) {
            if(Node->val >= x) {
                p2->next = Node;
                p2 = p2->next;
            } else {
                p1->next = Node;
                p1 = p1->next;
            }
            Node = Node->next;
        }
        p2->next = nullptr;
        p1->next = ans_after->next;
        return ans_before->next; 
    }
};

60. Reverse Linked List(LeetCode-206)

  积累: 有递归和迭代两种方式

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if (head == nullptr || head->next == nullptr) return head;
        ListNode* new_head = reverseList(head->next);
        head->next->next = head;
        head->next = nullptr;
        return new_head;
    }
};
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if (head == nullptr || head->next == nullptr) return head;
        ListNode* new_head = reverseList(head->next);
        head->next->next = head;
        head->next = nullptr;
        return new_head;
    }
};

61. Reverse Linked List II(LeetCode-92)

  题意:
Input: 1->2->3->4->5->NULL, m = 2, n = 4
Output: 1->4->3->2->5->NULL
Do it in one-pass.

class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        if(m == n) return head;
        ListNode dummy(0);
        ListNode* tail = &dummy;
        tail->next = head;
        
        ListNode* Node = tail;
        ListNode* prev_ = nullptr;
        ListNode* p1_r = nullptr;
        ListNode* p2_l = nullptr;
        ListNode* p2_r = nullptr;
        ListNode* p3_l = nullptr;
        int count = 0;
        while(Node != nullptr) {
            if(count == m) {
                p1_r = prev_;
                p2_l = Node;
            }
            if(count == n) {
                p2_r = Node;
                p3_l = Node->next;
            }
            ListNode* next_ = Node->next;
            if(count >= m && count <= n) 
                Node->next = prev_;
            
            prev_ = Node;
            Node = next_;
            count++;
        }
        p1_r->next = p2_r;
        p2_l->next = p3_l;
        return tail->next;
    }
};

63. Copy List with Random Pointer(LeetCode-138)

class Solution {
public:
    Node* copyRandomList(Node* head) {
        if(head == nullptr) return nullptr;
        copy_step1(head);
        setRandom_step2(head);
        Node* s3 = divide_step3(head);
        return s3;
    }
    void copy_step1(Node* head) {
        if(head == nullptr) return;
        Node* p_Node = head;
        while(p_Node != nullptr) {
            Node* copy = new Node(p_Node->val,nullptr,nullptr);
            Node* p_Next = p_Node->next;
            p_Node->next = copy;
            copy->next = p_Next;
            p_Node = p_Next;
        }
        //return head;
    }
   void setRandom_step2(Node* head) {
        if(head == nullptr) return;
        Node* p_Node = head;
        Node* p_Next = head->next;
        while(p_Node != nullptr) {
            p_Next->random = p_Node->random->next;
            p_Node = p_Next->next;
            if(p_Node == nullptr) break;
            p_Next = p_Node->next;
        }
        //return head;
    }
    Node* divide_step3(Node* head) {
        if(head == nullptr) return nullptr;
        Node* ans = head->next;
        while(ans->next != nullptr) {
            ans->next = ans->next->next;
            ans = ans->next;
        }
        return head->next;
    }
};

64. Linked List Cycle(LeetCode-141)

  题意: 链表中是否有环

class Solution {
public:
    bool hasCycle(ListNode *head) {
        if(head == nullptr || head->next == nullptr) return false;
        ListNode* p_slow = head;
        ListNode* p_fast = head->next;
        while(p_fast != p_slow) {
            if(p_slow == nullptr || p_slow->next == nullptr) return false;
            if(p_fast == nullptr || p_fast->next == nullptr) return false;
            p_slow = p_slow->next;
            p_fast = p_fast->next->next;
        }
        return true;
    }
};

65. Linked List Cycle II(LeetCode-142)

  题意: 如果链表中有环,找到链表中环的起点
  思路: 不必想剑指offer中的思路那么繁琐

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;
        do {
            if(fast != NULL)
                fast = fast->next;
            else
                return NULL;
            if(fast != NULL)
                fast = fast->next;
            else
                return NULL;
            slow = slow->next;
        } while (fast != slow);
        
        fast = head;
        while(fast != slow) {
            fast = fast->next;
            slow = slow->next;
        }
        return slow;
        
    }
};

66. Reorder List(LeetCode-143)

  题意: Given a singly linked list L: L0→L1→…→Ln-1→Ln,
reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…
  思路: 有两种思路,1就是用双端队列方式,但是会有额外的O(n)空间。2就是用分割链表,然后逆序后面的链表,再一个一个的连上。

class Solution {
public:
    void reorderList(ListNode* head) {
        if(head == nullptr || head->next == nullptr || head->next->next == nullptr)
            return;
        
        deque<ListNode*> st;
        ListNode* Node = head;
        while(Node != nullptr) {
            st.push_back(Node);
            Node = Node->next;
        }
        ListNode dummy(0);
        ListNode* tail = &dummy;
        int flag = 1;
        while(!st.empty()) {
            if(flag) {
                tail->next = st.front();
                st.pop_front();
                tail = tail->next;
                flag = !flag;
            } else {
                tail->next = st.back();
                st.pop_back();
                tail = tail->next;
                flag = !flag;
            }
        }
        tail->next = nullptr;
    }
};
class Solution {
public:
    void reorderList(ListNode* head) {
        if(!head) return;
        ListNode* slow = head, *fast = head;
        ListNode* pre = new ListNode(0);
        pre->next = slow;
        while(fast && fast->next){
            pre = pre->next;
            slow = slow->next;
            fast = fast->next->next;
        }
        if(fast) slow = slow->next, pre = pre->next;
        pre->next = NULL;
        ListNode* cur, *next;
        pre = NULL, cur = slow;
        while(cur){
            next = cur->next;
            cur->next = pre;
            pre = cur;
            cur = next;
        }
        ListNode* h1 = head, *h2 = pre, *p1, *p2;
        while(h1 && h2){
            p1 = h1->next;
            p2 = h2->next;
            h1->next = h2;
            h2->next = p1;
            h1 = p1;
            h2 = p2;
        }
    }
};

67. Insertion Sort List(LeetCode-147)

  题意: 利用插入排序法将链表排序

class Solution {
public:
    ListNode* insertionSortList(ListNode* head) {
        if (head == nullptr || head->next == nullptr)
            return head;
        ListNode dummy(INT_MIN);
        while (head != nullptr) {
            ListNode* Pre_ = &dummy;
            ListNode* Node = dummy.next;
            ListNode* P_next = head->next;
            while (Node != nullptr && Node->val <= head->val) {
                Pre_ = Node;
                Node = Node->next;
            }
            Pre_->next = head;
            head->next = Node;
            head = P_next;
        }
        return dummy.next;
    }
};

68. Sort List(LeetCode-148)

  题意: 将链表排序,时间复杂度为O(nlogn),空间复杂度为O(1)

class Solution {
public:
    ListNode* sortList(ListNode* head) {
        if (!head || !head->next) return head;
        int len = 1;
        ListNode* cur = head;
        while (cur = cur->next) ++len;
        ListNode dummy(0);
        dummy.next = head;
        ListNode* l;
        ListNode* r;
        ListNode* tail;
        for (int n = 1; n < len; n <<= 1) {      
            cur = dummy.next; // partial sorted head
            tail = &dummy;
            while (cur) {
                l = cur;
                r = split(l, n);
                cur = split(r, n);
                auto merged = merge(l, r);
                tail->next = merged.first;
                tail = merged.second;
            }
        }      
        return dummy.next;
    }
    private:
  // Splits the list into two parts, first n element and the rest.
  // Returns the head of the rest.
  ListNode* split(ListNode* head, int n) {    
    while (--n && head)
      head = head->next;
    ListNode* rest = head ? head->next : nullptr;
    if (head) head->next = nullptr;
    return rest;
  }
  
  // Merges two lists, returns the head and tail of the merged list.
  pair<ListNode*, ListNode*> merge(ListNode* l1, ListNode* l2) {
    ListNode dummy(0);
    ListNode* tail = &dummy;
    while (l1 && l2) {
      if (l1->val > l2->val) swap(l1, l2);
      tail->next = l1;
      l1 = l1->next;
      tail = tail->next;
    }
    tail->next = l1 ? l1 : l2;
    while (tail->next) tail = tail->next;
    return {dummy.next, tail};
  }
};

69. Intersection of Two Linked Lists(LeetCode-160)

  题意: 两个链表的交叉点

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        unordered_map<ListNode*,int> kv;
        while (headA) {
            kv[headA]++;
            headA = headA->next;
        }
        while (headB) {
            if(kv.find(headB) != kv.end())
                break;
            headB = headB->next;
        }
        return headB;
    }
};

70. Remove Linked List Elements(LeetCode-203)

  题意:
Input: 1->2->6->3->4->5->6, val = 6
Output: 1->2->3->4->5

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        if(head == nullptr) return nullptr;
        
        ListNode dummy(0);
        ListNode* Node = &dummy;
        Node->next = head;
        while(Node != nullptr) {
            ListNode* pNext = Node->next;
            
            while(pNext != nullptr && pNext->val == val)
                pNext = pNext->next;
            
            Node->next = pNext;
            Node = Node->next;
        }
        return dummy.next; 
    }
};

71. Palindrome Linked List(LeetCode-234)

  题意: 判断链表是否为一个回文链表,用O(n)时间和O(1)空间

class Solution {
public:
    bool isPalindrome(ListNode* head) {
        if(head == nullptr || head->next == nullptr) return true;
        ListNode* p_fast = head->next;
        ListNode* p_slow = head;
        while(p_fast != nullptr && p_fast->next != nullptr){
            p_slow = p_slow->next;
            p_fast = p_fast->next->next;
        }
        ListNode* p1 = p_slow->next;
        p_slow->next = nullptr;
        ListNode* p2 = reverse(p1);
        
        while(head != nullptr && p2 != nullptr) {
            if(head->val != p2->val) return false;
            head = head->next;
            p2 = p2->next;
        }
        return true;
        
    }
    ListNode* reverse(ListNode* head) {
        if(head == nullptr || head->next == nullptr)
            return head;
        ListNode* curr = head;
        ListNode* prev_ = nullptr;
        while(curr != nullptr) {
            ListNode* pnext_ = curr->next;
            curr->next = prev_;
            if(pnext_ == nullptr) return curr;
            prev_ = curr;
            curr = pnext_;
        }
        return nullptr;
    }
};

72. Delete Node in a Linked List(LeetCode-237)

  题意: 删除链表中的所给定的节点

class Solution {
public:
    void deleteNode(ListNode* node) {
        ListNode* next_ = node->next;
        node->val = next_->val;
        node->next = next_->next;
    }
};

73. Odd Even Linked List(LeetCode-328)

  题意:
Input: 1->2->3->4->5->NULL
Output: 1->3->5->2->4->NULL

class Solution {
public:
    ListNode* oddEvenList(ListNode* head) {
        if(head == nullptr || head->next == nullptr) return head;
        ListNode* odd = head;
        ListNode* even = head->next;
        
        ListNode* odd_head = odd;
        ListNode* even_head = even;
        
        while(even != nullptr && even->next != nullptr) {
            odd->next = even->next;
            odd = odd->next;
            even->next = odd->next;
            even = even->next;
        }
        odd->next = even_head;
        return odd_head;
    }
};

74. Odd Even Linked List(LeetCode-328)

  题意:
Input: 1->2->3->4->5->NULL
Output: 1->3->5->2->4->NULL

class Solution {
public:
    ListNode* oddEvenList(ListNode* head) {
        if(head == nullptr || head->next == nullptr) return head;
        ListNode* odd = head;
        ListNode* even = head->next;
        
        ListNode* odd_head = odd;
        ListNode* even_head = even;
        
        while(even != nullptr && even->next != nullptr) {
            odd->next = even->next;
            odd = odd->next;
            even->next = odd->next;
            even = even->next;
        }
        odd->next = even_head;
        return odd_head;
    }
};

75. Split Linked List in Parts(LeetCode-725)

  题意:
root = [1, 2, 3], k = 5
Output: [[1],[2],[3],[],[]]

class Solution {
public:
    vector<ListNode*> splitListToParts(ListNode* root, int k) {
       // if(root == nullptr) return {};
        vector<ListNode*> ans(k,nullptr);
        int len = 0;
        for(auto curr = root; curr != nullptr; curr = curr->next)
            len++;
        int l = len/k,r = len%k;
        
        ListNode* Node = root;
        ListNode* Prev_ = nullptr;
        for(int i = 0; i < k; i++,r--) {
            ans[i] = Node;
            for(int j = 0; j < l + (r > 0); j++) {
                Prev_ = Node;
                Node = Node->next;
            }
            if(Prev_ != nullptr)
                Prev_->next = nullptr;
        }
        return ans;
    }
};

76. Split Linked List in Parts(LeetCode-725)

  题意:
root = [1, 2, 3], k = 5
Output: [[1],[2],[3],[],[]]

class Solution {
public:
    vector<ListNode*> splitListToParts(ListNode* root, int k) {
       // if(root == nullptr) return {};
        vector<ListNode*> ans(k,nullptr);
        int len = 0;
        for(auto curr = root; curr != nullptr; curr = curr->next)
            len++;
        int l = len/k,r = len%k;
        
        ListNode* Node = root;
        ListNode* Prev_ = nullptr;
        for(int i = 0; i < k; i++,r--) {
            ans[i] = Node;
            for(int j = 0; j < l + (r > 0); j++) {
                Prev_ = Node;
                Node = Node->next;
            }
            if(Prev_ != nullptr)
                Prev_->next = nullptr;
        }
        return ans;
    }
};

77. Linked List Components(LeetCode-817)

  题意: 根据给定的链表,找给定的数组中的连通域个数
  解题思路: 这道题给了我们一个链表,又给了我们一个结点值数组,里面不一定包括了链表中所有的结点值。让我们返回结点值数组中有多少个相连的组件,因为缺失的结点值会将原链表断开,实际上就是让我们求有多少个相连的子链表,题目中给的例子很好的说明题意。这道题并不需要什么特别高深的技巧,难懂的算法,直接按题目的要求来找就可以了。首先,为了快速的在结点值数组中查找某个结点值是否存在,我们可以将所有的结点值放到一个HashSet中,这样我们就能在常数级的时间复杂度中查找。然后我们就可以来遍历链表了,对于遍历到的每个结点值,我们只有两种情况,在或者不在HashSet中。不在HashSet中的情况比较好办,说明此时断开了,而在HashSet中的结点,有可能是该连续子链表的起始点,或者是中间的某个点,而我们的计数器对该子链表只能自增1,所以我们需要想办法来hanlde这种情况。博主最先想到的办法是先处理不在HashSet中的结点,处理方法就是直接跳到下一个结点。那么对于在HashSet中的结点,我们首先将计数器res自增1,然后再来个循环,将之后所有在集合中的结点都遍历完,这样才不会对同一个子链表多次增加计数器,

class Solution {
public:
    int numComponents(ListNode* head, vector<int>& G) {
        unordered_set<int> hash;
        for (int &g : G) {
            hash.insert(g);
        }
        ListNode *node = head;
        int ans = 0;
        while (node != NULL) {
            if (hash.count(node->val) > 0) {
                ++ans;
                while (node != NULL && hash.count(node->val) > 0) {
                    node = node->next;
                }
            }
            if (node != NULL) {
                node = node->next;
            }
        }
        return ans;    
    }
};

78. Search in Rotated Sorted Array(LeetCode-33)

  题意: 旋转数组中查找一个数target,返回其index值。如果没找到返回-1
Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4
  解题思路: 二分搜索

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int l = 0,r = nums.size() - 1;
        while(l <= r) {
            int m = l + ((r - l) >> 1);
            if(nums[m] == target) return m;
            if(nums[m] >= nums[0]) {
                if(nums[m] > target && nums[0] <= target)
                    r = m - 1;
                else
                    l = m + 1;
                
            } else {
                if(nums[m] < target && nums[0] > target)
                    l = m + 1;
                else
                    r = m - 1;
            }
        }
        return -1;
    }
};

79. Find First and Last Position of Element in Sorted Array(LeetCode-34)

  题意: 排序数组中查找出元素的起始位置和终止位置
  解题思路: 二分搜索

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        return{FindFirstElement(nums,target),FindLastElement(nums,target)};
    }
    int FindFirstElement(vector<int>& nums, int target) {
        int l = 0, r = nums.size() - 1;
        while(l <= r) {
            int m = l + (r - l) / 2;
            if(nums[m] < target) l = m + 1;
            else if(nums[m] > target) r = m - 1;
            else {
                if((m > 0 && nums[m - 1] != target) || m == 0)
                    return m;
                else
                    r = m - 1;
            }
        }
        return -1;
        
    }
    int FindLastElement(vector<int>& nums, int target) {
        int l = 0,r = nums.size() - 1;
        while(l <= r) {
            int m = l + (r -l)/2;
            if(nums[m] < target) l = m + 1;
            else if(nums[m] > target) r = m - 1;
            else {
                if((m < nums.size() - 1 && nums[m + 1] != target) || m == nums.size() - 1)
                    return m;
                else
                    l = m + 1;
            }
            
        }
        return -1;
    }
};

80. Find Minimum in Rotated Sorted Array(LeetCode-153)

  题意: 旋转数组中查找出最小的元素,数组中不含重复元素
  解题思路: 二分搜索

class Solution {
public:
    int findMin(vector<int>& nums) {
        return findMin(nums, 0, nums.size()-1);    
    }
    int findMin(const vector<int>& num, int l, int r) {
        if (l + 1 >= r) 
            return min(num[l], num[r]);
        if (num[l] < num[r]) 
            return num[l];
        int mid = l + ((r - l) >> 1); 
        return min(findMin(num, l, mid-1), findMin(num, mid, r));
    }
};

81. Find Minimum in Rotated Sorted ArrayII(LeetCode-154)

  题意: 旋转数组中查找出最小的元素,数组中含重复元素
  解题思路: 二分搜索

class Solution {
public:
    int findMin(vector<int>& nums) {
        return findMin(nums,0,nums.size() - 1);
    }
    int findMin(vector<int>& nums,int l,int r) {
        if(r <= l + 1) 
            return min(nums[l],nums[r]);
        if(nums[l] < nums[r]) 
            return nums[l];
        int mid = l + (r - l) / 2;
        return min(findMin(nums,l,mid),findMin(nums,mid + 1,r));
    }
};

82. Search a 2D Matrix(LeetCode-240)

  题意: 排序矩阵中查找一个数,此矩阵展开后也是一个排序数组
Input:
matrix = [
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
target = 3
Output: true
  解题思路: 分治法,从右上角开始找

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

83. Search a 2D MatrixII(LeetCode-74)

  题意: 排序矩阵中查找一个数,此矩阵每一行递增,每一列也递增

  解题思路: 二分搜索、分治法

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

        int i,j,mid,rows = matrix.size(),cols = matrix[0].size();

        int limd = rows-1,limu = 0;

        /*二分查找目标值可能所在行的下限*/
        while(limu < limd)
        {
            mid = (limu + limd)/2;
            if(matrix[mid][0] > target) limd = mid - 1;
            else if(matrix[mid][0] < target) limu = mid +1;
            else return true;
        }

        /*对每一行进行二分查找*/
        for(i = 0; i <= limd; i++)
        {
            int l = 0, r = cols-1;
            while(l <= r)
            {
                mid = (l + r)/2;    
                if(matrix[i][mid] < target) l = mid+1;
                else if(matrix[i][mid] > target) r = mid - 1;
                else return true;
            }
        }

        return false;
    }
};

84. Find Peak Element(LeetCode-162)

  题意: 在数组中查找峰峰值
  解题思路: 二分法

class Solution {
public:
    int findPeakElement(vector<int>& nums) {
        int left = 0, right = nums.size() - 1;  
        while (left < right) {  
            int mid = (left + right) / 2;  
            if(nums[mid] < nums[mid + 1]) left = mid + 1;  
            else right = mid;  
        }  
        return left;  
    }
};

85. Find the Duplicate Number(LeetCode-287)

  题意: Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one.
Input: [3,1,3,4,2]
Output: 3
  解题思路: 二分查找

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int l = 1, r = nums.size();
        while(l <= r) {
            int m = l + (r - l) / 2;
            int count = 0;
            for(auto const& num: nums) {
                if(num <= m) count++;  
            }
            if(count > m) r = m - 1;
            else l = m + 1;
        }
        return l;
    }
};

86. Single Element in a Sorted Array(LeetCode-540)

  题意: Given a sorted array consisting of only integers where every element appears exactly twice except for one element which appears exactly once. Find this single element that appears only once.
  解题思路: 二分查找

class Solution {
public:
    int singleNonDuplicate(vector<int>& nums) {
        int l = 0;
        int r = nums.size() - 1;
        while(l <= r) {
            
            int m = l + (r - l)/2;
            
            if((m % 2 == 0 && m == nums.size() - 1) ||m == 0) 
                return nums[m];
            
            if(m % 2 == 0) {
                if(nums[m] == nums[m + 1]) {
                    l = m + 1;
                } else if(nums[m] == nums[m - 1]) {
                    r = m - 1;
                } else return nums[m];
                
            } else {
                if(nums[m] == nums[m + 1]) {
                    r = m - 1;
                } else if(nums[m] == nums[m - 1]) 
                    l = m + 1; 
            }
            
        }
        return 0;
    }
};

87. Single Number(LeetCode-136)

  题意: Given a non-empty array of integers, every element appears twice except for one. Find that single one.
  解题思路: 异或

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int result = 0;
        for(int i: nums) result ^= i;
        return result;      
    }
};

88. Kth Smallest Element in a Sorted Matrix(LeetCode-378)

  题意: Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth smallest element in the matrix.
matrix = [
[ 1, 5, 9],
[10, 11, 13],
[12, 13, 15]
],
k = 8,

return 13.
  解题思路: 二分查找

class Solution {
public:
    int kthSmallest(vector<vector<int>>& matrix, int k) {
        int n = matrix.size(), left = matrix[0][0], right = matrix[n-1][n-1];
        
        while(left < right) {
            long mid = (left + right) / 2, num = 0;
            for(int i = 0; i < n; i++) {
                auto it = upper_bound(matrix[i].begin(), matrix[i].end(), mid);
                num += it - matrix[i].begin();
            }
            if(num < k) left = mid + 1;
            else right = mid;
        }
        return left;   
    }
};

89. Valid Number(LeetCode-65)

  题意: 给定一个字符串,判断它是否能表示成一个有效数字
  解题思路: 先将字符串的开始和结尾的空格除去,再判断。corner case比较多

class Solution {
public:
    bool isNumber(string s) {
        trim(s);
        bool number_seen = false;
        bool point_seen = false;
        bool e_seen = false;
        bool number_after_e = true;
        
        for (int i = 0; i < s.length(); ++i) {
            if (s[i] >= '0' && s[i] <= '9') {
                number_seen = true;
                number_after_e = true;
            } else if (s[i] == '.') {
                if (e_seen || point_seen)
                    return false;
                point_seen = true;
            } else if (s[i] == 'e') {
                if (e_seen || !number_seen)
                    return false;
                e_seen = true;
                number_after_e = false;
            } else if (s[i] == '+' || s[i] == '-') {
                if (i != 0 && s[i - 1] != 'e')
                    return false;
            } else {
                return false;
            }
    
        }
        return number_after_e && number_seen;
    }
private:  
    string trim(string &s) 
    {
        if (s.empty()) return s;
        s.erase(0,s.find_first_not_of(" "));
        s.erase(s.find_last_not_of(" ") + 1);
        return s;
    }
};

90. Regular Expression Matching(LeetCode-10)

  题意: Given an input string (s) and a pattern §, implement regular expression matching with support for ‘.’ and ‘’.’.’ Matches any single character.’’ Matches zero or more of the preceding element.
  解题思路: 递归判断可以,动态规划可以

class Solution {
public:
    bool isMatch(string s, string p) {
        if(p.empty()) return s.empty();
        if(s.empty()) return p.empty() || (p[1] == '*' ? isMatch(s, p.substr(2)) : false);
        if(p[0] != '.' && s[0] != p[0]) return p[1] == '*' ? isMatch(s, p.substr(2)) : false;
        if(p[1] == '*') return isMatch(s.substr(1), p) || isMatch(s, p.substr(2));
        return isMatch(s.substr(1), p.substr(1));
    }
};
class Solution {
public:
    bool isMatch(string s, string p) {
        int m = s.size(), n = p.size();
		vector<vector<bool>> dp(m + 1, vector<bool>(n + 1,false));
		dp[0][0] = true;
		for (int i = 0; i <= m; i++) {
			for (int j = 1; j <= n; j++) {
				if (p[j - 1] == '*'){
					dp[i][j] = dp[i][j - 2] ||
						(i > 0 && dp[i - 1][j] && (s[i - 1] == p[j - 2] || p[j - 2] == '.'));
				}
				else {
					if (i > 0 && (s[i-1] == p[j-1] || p[j-1] == '.')) {
						dp[i][j] = dp[i - 1][j - 1];
					}
				}
			}
		}
		return dp[m][n];
    }
};

91. Roman to Integer(LeetCode-13)

  题意: 罗马数字转换成十进制整数
  解题思路: 用哈希表

class Solution {
public:
    int romanToInt(string s) {
        unordered_map<char, int> mp = {{'M', 1000}, {'D', 500}, {'C', 100}, {'L', 50}, {'X', 10}, {'V', 5}, {'I', 1}};
        int res = mp[s.back()];
        for(int i = 0; i < s.size() - 1; i++) {
            if(mp[s[i]] < mp[s[i + 1]]) res -= mp[s[i]];
		    else res += mp[s[i]];
		}
		return res;
    }
};

92. Integer to Roman(LeetCode-12)

  题意: 十进制整数转换成罗马数字
  解题思路:

class Solution {
public:
    string intToRoman(int num) {
        string res = "";
        while (num >= 1000) {
            num -= 1000;
            res.push_back('M');
        }
        if (num >= 900) {
            num -= 900;
            res.append("CM");
        }
        if (num >= 500) {
            num -= 500;
            res.push_back('D');
        }
        if (num >= 400) {
            num -= 400;
            res.append("CD");
        }
        while (num >= 100) {
            num -= 100;
            res.push_back('C');
        }
        if (num >= 90) {
            num -= 90;
            res.append("XC");
        }
        if (num >= 50) {
            num -= 50;
            res.push_back('L');
        }
        if (num >= 40) {
            num -= 40;
            res.append("XL");
        }
        while (num >= 10) {
            num -= 10;
            res.push_back('X');
        }
        if (num >= 9) {
            num -= 9;
            res.append("IX");
        }
        if (num >= 5) {
            num -= 5;
            res.push_back('V');
        }
        if (num >= 4) {
            num -= 4;
            res.append("IV");
        }
        while (num > 0) {
            num -= 1;
            res.push_back('I');
        }
        return res;
        
    }
};

93. Longest Common Prefix(LeetCode-14)

  题意: 字符串数组中最长的公共前缀
  解题思路: 按照矩阵的思路来进行考虑

class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        if(strs.size() == 0) return "";
        int i = 0;
        for (i = 0; strs[0][i] != NULL; i++) {          
            for (int j = 1;j < strs.size(); j++) {      
                if (strs[j][i] != strs[0][i]) {         
                    return strs[0].substr(0,i);       
                }                
            }
        }
        return strs[0];            
    }
};

94. Implement strStr()(LeetCode-28)

  题意: Implement strStr().Return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.
  解题思路:

class Solution {
public:
    int strStr(string haystack, string needle) {
        if (needle.size() == 0) return 0;
        if (haystack.size() < needle.size()) return -1;
        for (int i = 0; i <= haystack.size() - needle.size(); ++i) {
            if(check(haystack.substr(i),needle))
                return i;
        }
        return -1;
    }
    bool check(string p,string s) {
        for (int i = 0; i < s.size(); ++i) {
            if (s[i] != p[i]) return false;
        }
        return true;
    }
    
};

95. Count and Say(LeetCode-38)

  题意: The count-and-say sequence is the sequence of integers with the first five terms as following:

  1. 1
  2. 11
  3. 21
  4. 1211
  5. 111221
      解题思路:
class Solution {
public:
    string countAndSay(int n) {
        string result;
        if(n <= 0) return result;
        
        result.push_back('1');
        if(n == 1) return result;
        for (int i = 2; i <= n; i++) {
            string temp;
            string::iterator it = result.begin();
            while(it != result.end()) {
                char temp_char =  (char)(*it);
                int count = 0;
                while(*it == temp_char && it != result.end()) {
                    it++;
                    count++;
                }
                temp += to_string(count);
                temp.push_back(temp_char);
            }
            result = temp;
        }
        return result;
    }
};

96. Valid Sudoku(LeetCode-38)

  题意: 九宫格
Determine if a 9x9 Sudoku board is valid. Only the filled cells need to be validated according to the following rules:

Each row must contain the digits 1-9 without repetition.
Each column must contain the digits 1-9 without repetition.
Each of the 9 3x3 sub-boxes of the grid must contain the digits 1-9 without repetition.
  解题思路: 用哈希表,一次遍历就可

class Solution {
public:
    bool isValidSudoku(vector<vector<char>>& board) {
        
        for(int i = 0; i < 9; i ++) {
            unordered_map<char, bool> m1;   //check i_th row
            unordered_map<char, bool> m2;   //check i_th column
            unordered_map<char, bool> m3;   //check i_th subgrid
            for(int j = 0; j < 9; j ++) {
                if(board[i][j] != '.') {
                    if(m1[board[i][j]] == true)
                        return false;
                    m1[board[i][j]] = true;
                }
                if(board[j][i] != '.') {
                    if(m2[board[j][i]] == true)
                        return false;
                    m2[board[j][i]] = true;
                }
                if(board[i/3*3+j/3][i%3*3+j%3] != '.') {
                    if(m3[board[i/3*3+j/3][i%3*3+j%3]] == true)
                        return false;
                    m3[board[i/3*3+j/3][i%3*3+j%3]] = true;
                }
            }
        }
        return true;
    }
};

97. Group Anagrams(LeetCode-49)

  题意: 相同字母异序词;
Input: [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”],
Output:
[
[“ate”,“eat”,“tea”],
[“nat”,“tan”],
[“bat”]
]
  解题思路: 用哈希表

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        map<string, vector<string>> mp;
        vector<vector<string>> result;
        for (auto str: strs) {
            string tem = str;
            sort(tem.begin(), tem.end());
            mp[tem].push_back(str);
        }
        for(auto val: mp) {
            sort(val.second.begin(), val.second.end());
            result.push_back(val.second);
        }
        return result;
    }
};

98. Valid Anagram(LeetCode-242)

  题意: 判断两个字符串是否是相同字母异序词;
  解题思路: 用哈希表

class Solution {
public:
    bool isAnagram(string s, string t) {
        
        if(s.size() != t.size())
            return false;
        vector<int> count_s(26,0);
        vector<int> count_f(26,0);
        
        string::iterator it;
        for(it = s.begin(); it != s.end(); it++)
            count_s[*it - 'a']++;
        
        for(it = t.begin(); it != t.end(); it++)
            count_f[*it - 'a']++;
        
        if(count_s == count_f)
            return true;
        else
            return false; 
    }
};

99. First Unique Character in a String(LeetCode-387)

  题意: 找到字符串中的第一个只出现一次的字符
  解题思路: 用哈希表

class Solution {
public:
    int firstUniqChar(string s) {
        if(s.size() == 0)
            return -1;
        vector<int> hashmap(26,0);
        
        for(auto m:s)
            hashmap[m - 'a']++;
        
        int index = 0;
        for(auto m:s) {
            if(hashmap[m -'a'] == 1)
                return index;
            index++;
        }
        return -1;
    }
};

100. Basic Calculator II(LeetCode-227)

  题意: 根据字符串内容,写出计算式的答案
Input: “3+2*2”
Output: 7
  解题思路: 用栈来实现,和逆波兰表达式很像

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

101. Word Search(LeetCode-79)

  题意:
board =
[
[‘A’,‘B’,‘C’,‘E’],
[‘S’,‘F’,‘C’,‘S’],
[‘A’,‘D’,‘E’,‘E’]
]

Given word = “ABCCED”, return true.
Given word = “SEE”, return true.
Given word = “ABCB”, return false.

  解题思路: DFS,回溯法

class Solution {
public:
    bool exist(vector<vector<char>>& board, string word) {
        
        int row = board.size();
        int col = board[0].size();
        vector<vector<bool>> visited(row, vector<bool>(col, false));
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (dfs(board, word, 0, i, j, visited)) {
                    return true;
                }
            }
        }
        return false;

        
    }
    
    bool dfs(vector<vector<char>>& board, string word, int index, int x, int y, vector<vector<bool>>& visited) {
        //终止条件
        if (index == word.size()) {
            return true;
        }
        //越界
        if (x < 0 || y < 0 || x >= board.size() || y >= board[0].size()) {
            return false;
        }
        //已经访问
        if (visited[x][y]) {
            return false;
        }
        //不相等
        if (board[x][y] != word[index]) {
            return false;
        }
        visited[x][y] = true;
        bool result = dfs(board, word, index + 1, x - 1, y, visited) || dfs(board, word, index + 1, x + 1, y, visited) || dfs(board, word, index + 1, x, y - 1, visited) || dfs(board, word, index + 1, x, y + 1, visited);//分别为上下左右地搜索.
        visited[x][y] = false; //准备回溯,设置回未访问状态.
        return result;
    }

};

102. Decode Ways(LeetCode-91)

  题意: 根据给定的只包含数字的字符串,判断有多少中解码方式来表示字母
Input: “12”
Output: 2
Explanation: It could be decoded as “AB” (1 2) or “L” (12).
  解题思路: 动态规划

class Solution {
public:
    int numDecodings(string s) {
        int n=s.size();
        if(n == 0) return 0;
        vector<int> nums(n,0);
        for(int i = 0;i < n;i++) {
            
            if(s[i]=='0') {
                
                if(i == 0) return 0;
                else if (s[i-1] == '0'||s[i-1] > '2') return 0;
                else nums[i] = i-2 >= 0 ? nums[i - 2] : 1;
                
            } else {
                if (i == 0) nums[i] = 1;
                
                else if (s[i - 1] == '1'||(s[i - 1] == '2'&&s[i] <= '6')) nums[i] = nums[i - 1] + (i - 2 >= 0 ? nums[i - 2] : 1);
                else nums[i] = nums[i - 1];
            }

        }
        return nums[n-1];
    }
};

103. Decode String(LeetCode-394)

  题意: 根据给定的只包含数字的字符串,判断有多少中解码方式来表示字母
s = “3[a]2[bc]”, return “aaabcbc”.
s = “3[a2[c]]”, return “accaccacc”.
s = “2[abc]3[cd]ef”, return “abcabccdcdcdef”.
  解题思路: DFS

class Solution {
public:
    string decodeString(string s) {
        string result;
        if(s.size() == 0)
            return result;
        int k = 0;
        return decodeString_core(s,k);  
    }
    string decodeString_core(string s,int& k) {
        string ans;
        int count = 0;
        while ( k < s.size() ) {
            if(isdigit(s[k]))  
                count = count*10 + int(s[k++] - '0');
            else if(s[k] == '[') {
                k++;
                string str = decodeString_core(s,k);
                for(int i = 0 ; i < count; i++)
                    ans += str;
                count = 0;
            } else if(s[k] == ']') {
                k++;
                return ans;
            } else
                ans += s[k++];
        }
        return ans;
    }
};

104.Longest Substring with At Least K Repeating Characters(LeetCode-395)

  题意: Find the length of the longest substring T of a given string (consists of lowercase letters only) such that every character in T appears no less than k times.
  解题思路:

class Solution {
public:
    int longestSubstring(string s, int k) {
        return helper(s, k, 0, s.size() - 1);
    }
    int helper(string s, int k, int left, int right) {
        int len = right - left + 1;
        if (len <= 0) return 0;
        int i, j;
        int maxlen = 0;
        vector<int> count(26, 0);
        for (i = left; i <= right; i++) {
            count[s[i] - 'a']++;
        }
        for (i = left, j = left; i <= right; i++) {
            if (count[s[i] - 'a'] < k) {
                maxlen = max(maxlen, helper(s, k, j, i - 1));
                j = i + 1;
            }
        }
        if (j == left) return len;
        else return max(maxlen, helper(s, k, j, i - 1));
    }
};

105.Word Ladder(LeetCode-127)

  题意:
Input:
beginWord = “hit”,
endWord = “cog”,
wordList = [“hot”,“dot”,“dog”,“lot”,“log”,“cog”]

Output: 5

Explanation: As one shortest transformation is “hit” -> “hot” -> “dot” -> “dog” -> “cog”,
return its length 5.
  解题思路: BFS

class Solution {
public:
    int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
        int n = beginWord.size(), ret = 1;
        unordered_set<string> wordSet(wordList.begin(), wordList.end()), 
                              beginSet{beginWord}, endSet{endWord}, nextSet;
        if(wordSet.erase(endWord) == 0){
            return 0;
        }
        while(!beginSet.empty() && !endSet.empty()) {
            ++ret;
            if(beginSet.size() > endSet.size()){
                swap(beginSet, endSet);
            }
            for(string word: beginSet){
                for(int i = 0; i < n; ++i){
                    for(char j = 'a'; j <= 'z'; ++j) {
                        char ch = word[i];
                        word[i] = j;
                        if(endSet.count(word) != 0) {
                            return ret;
                        }
                        if(wordSet.count(word) != 0) {
                            wordSet.erase(word);
                            nextSet.insert(word);
                        }
                        word[i] = ch;
                    }
                }
            }
            beginSet = nextSet;
            nextSet.clear();   
        }
        return 0;     
    }
};

106.Container With Most Water(LeetCode-11)

  题意:
Given n non-negative integers a1, a2, …, an , where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.
  解题思路:

class Solution {
public:
    int maxArea(vector<int>& height) {
        int l = 0, r = height.size() - 1;
        int ans = INT_MIN;
        while(l < r) {
            int area = min(height[l],height[r]) * (r - l);
            ans = max(area,ans);
            if (height[l] <= height[r]) 
                l++;
            else                        
                r--;
        }
        return ans;
    }
};

107.Remove Duplicates from Sorted Array(LeetCode-26)

  题意:
给定一个排序好的数组,将其中的重复元素去掉只保留一个,返回最后数组的长度。
  解题思路:

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int i = 0;
        for(auto num : nums)
            if (i < 1 || nums[i - 1] < num)
                nums[i++] = num;
        return i;
    }
};

108.Spiral Matrix(LeetCode-54)

  题意: 给定一个矩阵,螺旋方式打印出来
  解题思路:

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        vector<int> res;
	    if(matrix.empty()) return res;
	    int l = 0, r = matrix[0].size() - 1, u = 0, d = matrix.size() - 1;
	    while(true) {
		    for(int i = l; i <= r; i++) res.push_back(matrix[u][i]);
		    if(++u > d) break;
            
		    for(int i = u; i <= d; i++) res.push_back(matrix[i][r]);
		    if(--r < l) break;
            
		    for(int i = r; i >= l; i--) res.push_back(matrix[d][i]);
		    if(--d < u) break;
            
		    for(int i = d; i >= u; i--) res.push_back(matrix[i][l]);
		    if(++l > r) break;
	    }
        return res;
    }
};

109.Merge Intervals(LeetCode-56)

  题意: 给定一系列的区间,将其合并
  解题思路: 先排序,然后比较结果中的最后一个元素和选定区间中的最后一个元素

class Solution {
public:
    vector<Interval> merge(vector<Interval>& intervals) {
        vector<Interval> ans;
        sort(intervals.begin(),intervals.end(),[](const Interval &t1,const Interval &t2){return t1.start < t2.start;});
        for (auto interval:intervals) {
            if (ans.empty() || ans.back().end < interval.start)
                ans.push_back(interval);
            else
                ans.back().end = max(ans.back().end,interval.end);
        }
        return ans;
    }
};

110.Set Matrix Zeroes(LeetCode-73)

  题意: 将矩阵中为零的元素的那一行和一列全部置为零
  解题思路: 可以将空间复杂度设置为O(m+n)

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        vector<bool> row_mark(matrix.size(),false);
        vector<bool> column_mark(matrix[0].size(),false);
        for (int i = 0; i < matrix.size(); ++i) {
            for (int j = 0; j < matrix[0].size(); ++j) {
                if (matrix[i][j] == 0) {
                    row_mark[i] = true;
                    column_mark[j] = true;
                }
            }
        }
        for (int i = 0; i < matrix.size(); ++i) {
            for (int j = 0; j < matrix[0].size(); ++j) {
               if (row_mark[i] == true) {
                   for (int k = 0; k < matrix[0].size(); ++k)
                       matrix[i][k] = 0;
               }
               if (column_mark[j] == true) {
                   for (int k = 0; k < matrix.size(); ++k)
                       matrix[k][j] = 0;
               }
            }
        }
        
    }
};

111.Sort Colors(LeetCode-75)

  题意: Given an array with n objects colored red, white or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white and blue.
Input: [2,0,2,1,1,0]
Output: [0,0,1,1,2,2]
  解题思路: 三色旗问题

class Solution {
public:
    void sortColors(vector<int>& nums) {
        if (nums.size() == 0) return;
        int i = -1,j = -1,k = -1;
        for (int m = 0; m < nums.size(); ++m) {
            if (nums[m] == 0) {
                
                nums[++k] = 2;
                nums[++j] = 1;
                nums[++i] = 0;
                
            } else if (nums[m] == 1) {
                
                nums[++k] = 2;
                nums[++j] = 1;
                
            } else if (nums[m] == 2) {
                
                nums[++k] = 2;
                
            } else break;
        }
    }
};

112.Merge Sorted Array(LeetCode-88)

  题意: 将两个排序好的数组合并成一个排序好的数组,将num2融入num1中,假设num1的空间足够大。
Input:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3

Output: [1,2,2,3,5,6]
  解题思路:

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
    
        int k;
        int i = m - 1, j = n - 1;
        for (k= m + n - 1; k >= 0;k--)
        {
            if ((j < 0 || nums1[i] > nums2[j]) && i >= 0)
                nums1[k] = nums1[i--];
            else
                nums1[k] = nums2[j--];
        }
    }
};

113.Pascal’s Triangle(LeetCode-118)

  题意: 杨辉三角
Given a non-negative integer numRows, generate the first numRows of Pascal’s triangle.
Input: 5
Output:
[
[1],
[1,1],
[1,2,1],
[1,3,3,1],
[1,4,6,4,1]
]
  解题思路:

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

114.Best Time to Buy and Sell Stock(LeetCode-121)

  题意:
Input: [7,1,5,3,6,4]
Output: 5
Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
Not 7-1 = 6, as selling price needs to be larger than buying price.
  解题思路:

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        if(prices.size() <= 1)
            return 0;
        
        int min_val = prices[0];
        int profit = 0;
        for(int i = 1; i < prices.size();i++) {
            min_val = min(min_val,prices[i]);
            profit = max(profit,(prices[i] - min_val));
        }
        return profit;   
    }
};

115.Majority Element(LeetCode-169)

  题意: 找出数组中出现次数大于n/2的那个数
  解题思路:

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int ans = nums.front();
        int count = 0;
        for (const auto& num:nums) {
            if (num == ans) count++;
            else if (--count == 0) {
                ans = num;
                count = 1;
            }
        }
        return ans;
    }
};

116.Largest Number(LeetCode-179)

  题意: 给定一些列的正整数,将其排序合并生成最大的一个正整数
  解题思路: 排序

class Solution {
public:
    string largestNumber(vector<int>& nums) {
        
        int n = nums.size();
        vector<string> strnums(n);
        
        for(int i=0;i<n;++i)
            strnums[i] = to_string(nums[i]);
        
        sort(strnums.begin(), strnums.end(), cmp);
        string res = "";
        for(int i = 0;i < n;++i)
           res += strnums[i];
        
        if(res[0] == '0') return "0";
        return res;

    }
    
      static bool cmp(string strnum1, string strnum2) {
        string str1 = strnum1+strnum2;
        string str2 = strnum2+strnum1;
        return str1>str2;
    }
};

117.Rotate Array(LeetCode-189)

  题意: 移位数组
  解题思路:
Input: [1,2,3,4,5,6,7] and k = 3
Output: [5,6,7,1,2,3,4]
Explanation:
rotate 1 steps to the right: [7,1,2,3,4,5,6]
rotate 2 steps to the right: [6,7,1,2,3,4,5]
rotate 3 steps to the right: [5,6,7,1,2,3,4]

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        if(k > nums.size())
            k = k % (nums.size());
        reverse(nums.begin(),nums.end() - k);
        reverse(nums.end() - k,nums.end());
        reverse(nums.begin(),nums.end());
    }
};

118.Product of Array Except Self(LeetCode-238)

  题意:
Given an array nums of n integers where n > 1, return an array output such that output[i] is equal to the product of all the elements of nums except nums[i].不能用除法
  解题思路:

class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
       
        int len = nums.size();
        vector<int> result(len);
        result[0] = 1;
        
        for(int i = 1; i < len; i++)
            result[i] = (result[i - 1] * nums[i - 1]);
        
        int temp = 1;
        for(int i = len - 2; i >= 0; --i) {
            temp *= nums[i + 1];
            result[i] *= temp;
        }
        return result;
    }
};

119.Move Zeroes(LeetCode-238)

  题意: 将数组中的零元素后移到尾端,并且保证非零元素的顺序不变
Input: [0,1,0,3,12]
Output: [1,3,12,0,0]
  解题思路:

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

120.Wiggle Sort II(LeetCode-324)

  题意:
Given an unsorted array nums, reorder it such that nums[0] < nums[1] > nums[2] < nums[3]…
  解题思路:

class Solution {
public:
    void wiggleSort(vector<int>& nums) {
        if(nums.size() <= 1) return;
        sort(nums.begin(), nums.end());
        int len = nums.size();
        int k = 1; 
        int high = (len % 2) ? len - 1:len - 2;
        int mid = nums[len / 2];
        vector<int> ans(len, mid);
        for(int i = len-1; i >= 0 && nums[i] > mid; i--, k += 2)
            ans[k] = nums[i];
        for(int i = 0; i < len && nums[i] < mid; i++, high -= 2)
            ans[high] = nums[i];
        nums = ans;
    }
};

121.Increasing Triplet Subsequence(LeetCode-334)

  题意: 数组中是否存在递增的三个子序列
  解题思路:

class Solution {
public:
    bool increasingTriplet(vector<int>& nums) {
        
        int n = nums.size();
        if (n < 3) return false;
        int a = INT_MAX, b = INT_MAX;
        for (int i = 0; i < n; ++i) {
            
            if (nums[i] <= a) 
                a = nums[i];
            
            else if (nums[i] <= b) 
                b = nums[i];
            
            else 
                return true;
        }
        return false;
    }
};

122.Intersection of Two Arrays(LeetCode-349)

  题意: 两个数组中的交集
Input: nums1 = [1,2,2,1], nums2 = [2,2]
Output: [2]
  解题思路:

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        set<int> s(nums1.begin(), nums1.end()), res;
        for (auto a : nums2) {
            if (s.count(a)) res.insert(a);
        }
        return vector<int>(res.begin(), res.end());
    }
};

123.Intersection of Two ArraysII(LeetCode-350)

  题意: 两个数组中的交集
Input: nums1 = [1,2,2,1], nums2 = [2,2]
Output: [2,2]
  解题思路:

class Solution {
public:
    vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
          
        sort(nums1.begin(), nums1.end());
        sort(nums2.begin(), nums2.end());
        vector<int> result;
        for (int i = 0, j = 0; i < nums1.size() && j < nums2.size(); ) {
            if (nums1[i] == nums2[j]) {
                result.push_back(nums1[i]);
                i++;
                j++;
            }
            else if (nums1[i] < nums2[j])
                i++;
            else if (nums1[i] > nums2[j])
                j++;
        }
        return result;
    }
};

124.Find All Duplicates in an Array(LeetCode-442)

  题意: 数组中所有重复出现的数字
  解题思路:

class Solution {
public:
    vector<int> findDuplicates(vector<int>& nums) {
        unordered_map<int ,int> count;
        
        for(int i = 0; i < nums.size() ;i++)
            count[nums[i]]++;
        
        vector<int> result;
        unordered_map<int ,int>::iterator it;
        for(it = count.begin(); it != count.end(); it++) {
            if(it->second == 2)
                result.push_back(it->first);
        }
        return result; 
    }
};
class Solution {
public:
    vector<int> findDuplicates(vector<int>& nums) {
        vector<int> res;
        for (auto n: nums) {
            n = abs(n);
            nums[n - 1] = -nums[n - 1];
            if (nums[n - 1] > 0)
                res.push_back(n);
        }
        return res;
    }
};

125.Find All Numbers Disappeared in an Array(LeetCode-448)

  题意:
Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.

Find all the elements of [1, n] inclusive that do not appear in this array.

Could you do it without extra space and in O(n) runtime? You may assume the returned list does not count as extra space.
Input:
[4,3,2,7,8,2,3,1]

Output:
[5,6]
  解题思路:

class Solution {
public:
    vector<int> findDisappearedNumbers(vector<int>& nums) {
        
        vector<int> res;
        for (int i = 0; i < nums.size(); ++i) {
            
            if (nums[i] != nums[nums[i] - 1]) {
                
                swap(nums[i], nums[nums[i] - 1]);
                --i;
            }
        }
        for (int i = 0; i < nums.size(); ++i) {
            if (nums[i] != i + 1) {
                res.push_back(i + 1);
            }
        }
        return res;
    }
};

126.Shortest Unsorted Continuous Subarray(LeetCode-581)

  题意:

  解题思路:

class Solution {
public:
    int findUnsortedSubarray(vector<int>& nums) {
        int start = -1;
        int end = -2;
        int max_value = nums[0];
        int min_value = nums[nums.size() - 1];
        int len = nums.size();
        
        for(int i = 0; i < len; i++) {
            max_value = max(max_value,nums[i]);
            min_value = min(min_value,nums[len - 1 - i]);
            if (max_value > nums[i])
                end = i;
            if (min_value < nums[len - 1 - i])
                start = len - 1 - i;
        }
        return end - start + 1;
    }
};

127.Degree of an Array(LeetCode-697)

  题意:

  解题思路:

class Solution {
public:
    int findShortestSubArray(vector<int>& nums) {
     int size = nums.size();
        int res = INT_MAX;
        int degree = 0;

        unordered_map<int, int> m, startIdx;

        for (int i = 0; i < size; i++) {
            m[nums[i]]++; // 次数更新
            if (m[nums[i]] == 1) {
                // 第一次出现,建立起始位置和数字的映射
                startIdx[nums[i]] = i;
            }
            if(m[nums[i]]==degree) {
                // 等于degree,则得到了最远的距离
                // 则需要计算最小的长度
                res = min(res,i - startIdx[nums[i]] + 1);
            }
            else if(m[nums[i]]>degree) {
                // 出现次数更多.则需要更新 res成为最高次数对应的长度;
                res = i - startIdx[nums[i]] + 1;
                degree = m[nums[i]];
            }
        }
        return res;
    }
};

128.Maximum Product Subarray(LeetCode-152)

  题意: 连续子数组中最大的乘积

  解题思路:

class Solution {
public:
    int maxProduct(vector<int>& nums) {
        
        int res = nums[0], n = nums.size();
        vector<int> f(n, 0), g(n, 0);
        f[0] = nums[0];
        g[0] = nums[0];
        for (int i = 1; i < n; ++i) {
            f[i] = max(max(f[i - 1] * nums[i], g[i - 1] * nums[i]), nums[i]);
            g[i] = min(min(f[i - 1] * nums[i], g[i - 1] * nums[i]), nums[i]);
            res = max(res, f[i]);
        }
        return res;
        
    }
};

129.Longest Increasing Subsequence(LeetCode-300)

  题意: 在无序的数组中找到最长的递增子序列

  解题思路: 动态规划

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        if (nums.size() == 0) return 0;
        if (nums.size() == 1) return 1;
        int ans = 1;
        vector dp(nums.size(),1);
        for (int i = 0; i < nums.size(); ++i) {
            for (int j = 0; j < i; ++j) {
                if (nums[i] > nums[j]) {
                    dp[i] = max(dp[i],dp[j] + 1);
                    ans = max(dp[i],ans);
                }
            }
        }
        return ans;
    }
};

130.Factorial Trailing Zeroes(LeetCode-172)

  题意: 给定一个正整数n,找到n!的末尾有几个零
  解题思路:
这道题并没有什么难度,是让求一个数的阶乘末尾0的个数,也就是要找乘数中10的个数,而10可分解为2和5,而我们可知2的数量又远大于5的数量,那么此题即便为找出5的个数。仍需注意的一点就是,像25,125,这样的不只含有一个5的数字需要考虑进去。代码如下:

class Solution {
public:
    int trailingZeroes(int n) {
        int ret = 0;
        while(n) {
            ret += n/5;
            n /= 5;
        }
        return ret;
    }
};

131.Power of Three(LeetCode-326)

  题意: 判断一个数n是够为3的幂
  解题思路: 迭代法和数学方法

class Solution {
public:
    bool isPowerOfThree(int n) {
        if (n <= 0) return false;
         while (n != 1) {
             if (n % 3 != 0) break;
             n /= 3;
         }
        return n==1;
    }
};
class Solution {
public:
    bool isPowerOfThree(int n) {
        return fmod(log10(n)/log10(3), 1)==0;
    }
};

132.Queue Reconstruction by Height(LeetCode-406)

  题意:
Suppose you have a random list of people standing in a queue. Each person is described by a pair of integers (h, k), where h is the height of the person and k is the number of people in front of this person who have a height greater than or equal to h. Write an algorithm to reconstruct the queue.
Input:
[[7,0], [4,4], [7,1], [5,0], [6,1], [5,2]]

Output:
[[5,0], [7,0], [5,2], [6,1], [4,4], [7,1]]
  解题思路:

class Solution {
public:
    static bool cmp(pair<int,int>a,pair<int,int>b) {
        if(a.first != b.first)   return a.first > b.first;
        else                     return a.second < b.second;
    }
    vector<pair<int, int>> reconstructQueue(vector<pair<int, int>>& people) {
        if(people.size() == 0) 
            return people;
        sort(people.begin(), people.end(), cmp);
        vector<pair<int, int>>::iterator it = people.begin() + 1;
        while(it != people.end()) {
            pair<int, int> temp= *it;
            people.erase(it,it + 1);
            people.insert(people.begin() + temp.second,temp);
            it++;
        }
        return people; 
    }
};

133.Binary Tree Inorder Traversal(LeetCode-94)

  题意: 二叉树中序遍历

  解题思路:

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        if (root == nullptr) return {};
        vector<int> ans;
        stack<TreeNode*> st;
        TreeNode* node = root;
        while (!st.empty() || node != nullptr) {
            while (node != nullptr) {
                st.push(node);
                node = node->left;
            }
            if (!st.empty()) {
                node = st.top();
                ans.push_back(node->val);
                st.pop();
                node = node->right;
            }
        }
        return ans;
    }
};

134.Binary Tree Preorder Traversal(LeetCode-144)

  题意: 二叉树前序遍历

  解题思路:

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        if (root == nullptr) return{};
        vector<int> ans;
        stack<TreeNode*> st;
        TreeNode* Node = root;
        while (Node != nullptr || !st.empty()) {
            while (Node != nullptr) {
                ans.push_back(Node->val);
                st.push(Node);
                Node = Node->left;
            }
            if (!st.empty()) {
                Node = st.top();
                st.pop();
                Node = Node->right;
            } 
        }
        return ans;
    }
};

135.Binary Tree Postorder Traversal(LeetCode-145)

  题意: 二叉树后序遍历

  解题思路:

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        if(root == nullptr) return {};
        vector<int> ans;
        TreeNode* prev_ = root;
        stack<TreeNode*> st{{root}};
        while(!st.empty()) {
            auto curr = st.top();
            if ((!curr->left && !curr->right) || curr->left == prev_ || curr->right == prev_) {
                ans.push_back(curr->val);
                st.pop();
                prev_ = curr;
            } else {
                if (curr->right != nullptr) st.push(curr->right);
                if (curr->left != nullptr) st.push(curr->left);
            }
            
        }
        return ans;
    }
};

136.Unique Binary Search Trees(LeetCode-96)

  题意: 给定正整数n,判断能生成多少颗节点值为1…n的二叉搜索树
  解题思路:

class Solution {
public:
    int numTrees(int n) {
        if(n == 0) return 1;
        if(n == 1) return 1;
        
        int ans = 0;
        for(int i = 0; i < n ; i++) {
            ans += numTrees(i) * numTrees(n - i - 1);
        }
        return ans;
    }
};

137.Unique Binary Search TreesII(LeetCode-96)

  题意: 给定正整数n,生成所有颗节点值为1…n的二叉搜索树
  解题思路:

class Solution {
public:
    vector<TreeNode*> generateTrees(int n) {
        if(n == 0) return{};
        return generateTrees(n,1);
        
    }
    vector<TreeNode*> generateTrees(int n,int start) {
        vector<TreeNode*> ans;
        if(n == 0) {
            ans.push_back(nullptr);
            return ans;
        }
        if(n == 1) {
            ans.push_back(new TreeNode(start));
            return ans;
        }
        for(int i = 0; i < n; ++i) {
            for(TreeNode* left_Node:generateTrees(i,start)) {
                for(TreeNode* right_Node:generateTrees(n - i - 1,start + i + 1)) {
                    TreeNode* root = new TreeNode(start + i);
                    root->left = left_Node;
                    root->right = right_Node;
                    ans.push_back(root);
                } 
            } 
        }
        return ans;
    }            
};

138.Validate Binary Search Tree(LeetCode-98)

  题意: 验证所给定的二叉树是否为二叉搜索树
  解题思路:

class Solution {
public:
    bool isValidBST(TreeNode* root) {
        prev_ = nullptr;
        return inorder(root);
    }
private:
    TreeNode* prev_;
    bool inorder(TreeNode* root) {
        if(root == nullptr) return true;
        if(!inorder(root->left)) return false;
        if(prev_ && prev_->val >= root->val) 
            return false;
        prev_ = root;
        return inorder(root->right);
        
    }
};
class Solution {
public:
    bool isValidBST(TreeNode* root) {
        return isValidBST(root, LLONG_MIN, LLONG_MAX);
    }
private:
    bool isValidBST(TreeNode* root, long min_val, long max_val) {
        if (!root) return true;
        if (root->val <= min_val || root->val >= max_val)
            return false; 
        return isValidBST(root->left, min_val, root->val)
            && isValidBST(root->right, root->val, max_val);
    }
};

139.Same Tree(LeetCode-100)

  题意: 判断两颗树是否为相同
  解题思路:

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

140.Symmetric Tree(LeetCode-101)

  题意: 判断所给定的二叉树是否为对称的二叉树
  解题思路:

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        return isSymmetric_core(root,root);
    }
    bool isSymmetric_core(TreeNode* p1,TreeNode* p2) {
        if(p1 == nullptr && p2 == nullptr) return true;
        else if(p1 == nullptr || p2 == nullptr) return false;
        
        if(p1->val != p2->val) return false;
        
        return isSymmetric_core(p1->left,p2->right)&&isSymmetric_core(p1->right,p2->left);
    }
    
};

141.Maximum Depth of Binary Tree(LeetCode-104)

  题意: 所给定的二叉树的最大深度
  解题思路:

class Solution {
public:
    int maxDepth(TreeNode* root) {
        if(root == nullptr) return 0;
        int left = maxDepth(root->left);
        int right = maxDepth(root->right);
        return max(left + 1,right + 1);
    }
};

142.Minimum Depth of Binary Tree(LeetCode-111)

  题意: 所给定的二叉树的最小深度
  解题思路:

class Solution {
public:
    int minDepth(TreeNode* root) {
        if (root == nullptr) return 0;
        int ans = INT_MAX;
        dfs(root,ans,0);
        return ans + 1;
        
    }
    void dfs(TreeNode* root,int& ans,int depth) {
        if (root == nullptr) return;
        if (root->left == nullptr && root->right == nullptr) {
            ans = min(ans,depth);
            return;
        }
        dfs(root->left,ans,depth + 1);
        dfs(root->right,ans,depth + 1);
    }
};

143.Balanced Binary Tree(LeetCode-110)

  题意: 所给定的二叉树是否为平衡二叉树
a height-balanced binary tree is defined as:
a binary tree in which the depth of the two subtrees of every node never differ by more than 1.
  解题思路:

class Solution {
public:
    bool isBalanced(TreeNode* root) {
        bool flag = true;
        DFS(root,flag);
        return flag;
    }
    int DFS(TreeNode* root,bool& flag) {
        if(root == nullptr) return 0;
        int l = DFS(root->left,flag);
        int r = DFS(root->right,flag);
        if(abs(l - r) > 1) flag = false;
        return max(l,r) + 1;
    }
};

144.Construct Binary Tree from Preorder and Inorder Traversal(LeetCode-105)

  题意: 根据给定的前序遍历和中旬遍历来构建二叉树
  解题思路:

class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        return buildTree(cbegin(preorder),cend(preorder),cbegin(inorder),cend(inorder)); 
    }
private:
    typedef vector<int>::const_iterator VIT;
    TreeNode* buildTree(VIT pre_l,VIT pre_r,VIT in_l,VIT in_r) {
        if(pre_l == pre_r || in_l == in_r)
            return nullptr;
        TreeNode* root = new TreeNode(*pre_l);
        VIT in_m = next(find(in_l,in_r,*pre_l));
        VIT pre_m = pre_l + (in_m - in_l);
        root->left = buildTree(next(pre_l),pre_m,in_l,prev(in_m));
        root->right = buildTree(pre_m,pre_r,in_m,in_r);
        return root;    
    }
};

145.Construct Binary Tree from Inorder and Postorder Traversal(LeetCode-106)

  题意: 根据给定的中序遍历和后序遍历来构建二叉树
  解题思路:

class Solution {
public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        return buildTree(cbegin(inorder),cend(inorder),cbegin(postorder),cend(postorder));
    } 
private:
    typedef vector<int>:: const_iterator VIT;
    TreeNode* buildTree(VIT in_l,VIT in_r,VIT post_l,VIT post_r) {
        if(in_r == in_l || post_l == post_r)
            return nullptr;
        TreeNode* root = new TreeNode(*prev(post_r));
        VIT in_m = next(find(in_l,in_r,*prev(post_r)));
        VIT post_m = post_l + (in_m - in_l) - 1;
        root->left = buildTree(in_l,prev(in_m),post_l,post_m);
        root->right = buildTree(in_m,in_r,post_m,prev(post_r));
        return root;
    }
};

146.Construct Binary Tree from Preorder and Postorder Traversal(LeetCode-889)

  题意: 根据给定的前序遍历和后序遍历来构建二叉树
  解题思路:

class Solution {
public:
    TreeNode* constructFromPrePost(vector<int>& pre, vector<int>& post) {
        return constructFromPrePost(cbegin(pre),cend(pre),cbegin(post),cend(post));
    }
private:
    typedef vector<int>:: const_iterator VIT;
    TreeNode* constructFromPrePost(VIT pre_l,VIT pre_r,VIT post_l,VIT post_r) {
        if(pre_l == pre_r || post_l == post_r)
            return nullptr;
        TreeNode* root = new TreeNode(*pre_l);
        pre_l++;
        post_r--;
        if(pre_l == pre_r) return root;
        VIT post_m = next(find(post_l,post_r,*pre_l));
        VIT pre_m = pre_l + (post_m - post_l);
        root->left = constructFromPrePost(pre_l,pre_m,post_l,post_m);
        root->right = constructFromPrePost(pre_m,pre_r,post_m,post_r);
        return root;
    } 
};

147.Convert Sorted Array to Binary Search Tree(LeetCode-108)

  题意: 根据给定的排序数组生成二叉搜索树,且为高度平衡的二叉搜索树
  解题思路:

class Solution {
public:
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        if(nums.size() == 0) return nullptr;
        return sortedArrayToBST(cbegin(nums),prev(cend(nums)));
    }
private:
    typedef vector<int>::const_iterator VIT;
    TreeNode* sortedArrayToBST(VIT left,VIT right) {
        if(left > right) return nullptr;
        VIT mid = left + (right - left) / 2;
        TreeNode* root = new TreeNode(*mid);
        root->left = sortedArrayToBST(left,mid - 1);
        root->right = sortedArrayToBST(mid + 1,right);
        return root;
    }
    
};

148.Convert Sorted List to Binary Search Tree(LeetCode-109)

  题意: 根据给定的排链表生成二叉搜索树,且为高度平衡的二叉搜索树
  解题思路:

class Solution {
public:
    TreeNode* sortedListToBST(ListNode* head) {
        if(head == nullptr) return nullptr;
        if(head->next == nullptr) return new TreeNode(head->val);
        
        ListNode* mid_prev = getMiddle(head);
        if(mid_prev == nullptr) return nullptr;
        if(mid_prev->next == nullptr) return new TreeNode(mid_prev->val);
        ListNode* mid = mid_prev->next;
        ListNode* mid_next = mid_prev->next->next;
        
        mid_prev->next = nullptr;
        TreeNode* root = new TreeNode(mid->val);
        root->left = sortedListToBST(head);
        root->right = sortedListToBST(mid_next);
        return root;
    }
    ListNode* getMiddle(ListNode* head) {
        if(head == nullptr) return nullptr;
        ListNode* slow = head;
        ListNode* prev_ = slow;
        ListNode* fast = head->next;
        while(fast != nullptr && fast->next != nullptr) {
            prev_ = slow;
            slow = slow->next;
            fast = fast->next->next;
        }
        return prev_;
    }
};

149.Path Sum(LeetCode-112)

  题意: 判断所给定的二叉树由根节点到叶节点的路径和是否与给定的target相等
  解题思路:

class Solution {
public:
    bool hasPathSum(TreeNode* root, int sum) {
        if(root == nullptr) return false;
        if(root->left == nullptr && root->right == nullptr) {
            if(sum - root->val == 0) return true;
            else return false;
        }
        return hasPathSum(root->left,sum - root->val)||hasPathSum(root->right,sum - root->val);
    }  
};

150.Path SumII(LeetCode-113)

  题意: 判断所给定的二叉树由根节点到叶节点的路径和是否与给定的target相等,把所有的符合规定的路径保存下来
  解题思路:

class Solution {
public:
    vector<vector<int>> pathSum(TreeNode* root, int sum) {
        if(root == nullptr) return{};
        vector<vector<int>> ans;
        vector<int> cur;
        DFS(root,sum,cur,ans);
        return ans;
    }
    void DFS(TreeNode* root,int sum,vector<int>& cur,vector<vector<int>>& ans) {
      if(root == nullptr) return;
      if(root->left == nullptr && root->right == nullptr) {
          if (sum - root->val == 0) {
              ans.push_back(cur);
              ans.back().push_back(root->val);
              return;
          } else
              return;
      }
      cur.push_back(root->val);
      DFS(root->left,sum - root->val,cur,ans);
      DFS(root->right,sum - root->val,cur,ans);
      cur.pop_back();
    }
};

151.Flatten Binary Tree to Linked List(LeetCode-114)

  题意: 将二叉树变成单链表
  解题思路:

class Solution {
public:
    void flatten(TreeNode* root) {
        if(root == nullptr) return;
        flatten(root->left);
        if(root->left != nullptr) {
            TreeNode* Node = root->left;
            while(Node->right != nullptr) Node = Node->right;
            TreeNode* temp = root->right;
            root->right = root->left;
            Node->right = temp; 
            root->left = nullptr;
        }
        flatten(root->right);
    }
};

152.Populating Next Right Pointers in Each Node(LeetCode-116)

  题意: 二叉树为perfect二叉树
  解题思路:

class Solution {
public:
    Node* connect(Node* root) {
        if(root == nullptr) return nullptr;
        
        if(root->left != nullptr)
           root->left->next = root->right;
        if(root->right != nullptr)
           root->right->next = root->next == nullptr ? nullptr:root->next->left;
            
        
        root->left = connect(root->left);
        root->right = connect(root->right);
        return root;
        
    }
};

153.Populating Next Right Pointers in Each NodeII(LeetCode-117)

  题意: 为普通二叉树
  解题思路:

class Solution {
public:
    Node* connect(Node* root) {
        if (!root) return nullptr;
        Node *p = root->next;
        while (p) {
            if (p->left) {
                p = p->left;
                break;
            }
            if (p->right) {
                p = p->right;
                break;
            }
            p = p->next;
        }
        if (root->right) root->right->next = p; 
        if (root->left) root->left->next = root->right ? root->right : p; 
        root->right = connect(root->right);
        root->left= connect(root->left);
        
        return root;
        
    }
};

154.Binary Tree Maximum Path Sum(LeetCode-124)

  题意: 二叉树最大路径和
  解题思路:

class Solution {
public:
    int maxPathSum(TreeNode* root) {
        int ans = INT_MIN;
        dfs(root,ans);
        return ans;
    }
    int dfs(TreeNode* root,int& ans) {
        if (root == nullptr) return 0;
        int l = max(dfs(root->left,ans),0);
        int r = max(dfs(root->right,ans),0);
        ans = max(ans,l + r + root->val);
        return max(l,r) + root->val;
    }
};

155.Sum Root to Leaf Numbers(LeetCode-129)

  题意:
Input: [4,9,0,5,1]
4
/
9 0
/
5 1
Output: 1026
Explanation:
The root-to-leaf path 4->9->5 represents the number 495.
The root-to-leaf path 4->9->1 represents the number 491.
The root-to-leaf path 4->0 represents the number 40.
Therefore, sum = 495 + 491 + 40 = 1026.
  解题思路:

    int sumNumbers(TreeNode* root) {
        return DFS(root,0);
    }
    int DFS(TreeNode* root,int sum) {
        if(root == nullptr) return 0;
        sum = sum * 10 + root->val;
        if(root->left == nullptr && root->right == nullptr) return sum;
        int l = DFS(root->left,sum) ;
        int r = DFS(root->right,sum) ;
        
        return l + r;
    }
       

156.Count Complete Tree Nodes(LeetCode-222)

  题意:
对于一颗二叉树,假设其深度为d(d>1)。除了第d层外,其它各层的节点数目均已达最大值,且第d层所有节点从左向右连续地紧密排列,这样的二叉树被称为完全二叉树;换句话说,完全二叉树从根结点到倒数第二层满足完美二叉树,最后一层可以不完全填充,其叶子结点都靠左对齐。
  解题思路:
通过上面对完全二叉树跟完美二叉树的定义比较,可以看出二者的关系是,完美二叉树一定是完全二叉树,而完全二叉树不一定是完美二叉树。那么这道题给的完全二叉树就有可能是完美二叉树,若是完美二叉树,节点个数很好求,为2的h次方减1,h为该完美二叉树的高度。若不是的话,只能老老实实的一个一个数结点了。思路是由 root 根结点往下,分别找最靠左边和最靠右边的路径长度,如果长度相等,则证明二叉树最后一层节点是满的,是满二叉树,直接返回节点个数,如果不相等,则节点个数为左子树的节点个数加上右子树的节点个数再加1(根节点),其中左右子树节点个数的计算可以使用递归来计算,

  class Solution {
public:
    int countNodes(TreeNode* root) {
       if(root == nullptr) return 0;
       int l = 0, r = 0;
       TreeNode* left = root;
       TreeNode* right = root;
       while(left) {
           left = left->left;
           l++;
       }
       while(right) {
           right = right->right;
           r++;
       }
        if(r == l) return pow(2,l) - 1;
        return countNodes(root->left) + countNodes(root->right) + 1;
    }
};

157.Invert Binary Tree(LeetCode-226)

  题意: 将一个二叉树交换节点
  解题思路:

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if(root == nullptr) return nullptr;
        TreeNode* temp = root->left;
        root->left = root->right;
        root->right = temp;
        root->left = invertTree(root->left);
        root->right = invertTree(root->right);
        return root;
    }
  
};

158.Kth Smallest Element in a BST(LeetCode-230)

  题意: 在二叉搜索树中找到第K小的节点
  解题思路:

class Solution {
public:
    int kthSmallest(TreeNode* root, int k) {
        int ans = 0;
        DFS(root,k,ans);
        return ans;
    }
    void DFS(TreeNode* root,int& k,int& ans) {
        if (root == nullptr) return;
        DFS(root->left,k,ans);
        if (--k == 0) ans = root->val;
        DFS(root->right,k,ans);
    }
};

159.Lowest Common Ancestor of a Binary Search Tree(LeetCode-235)

  题意: 在二叉搜索树中找到两个节点的最低公共祖先
  解题思路:

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if (root == nullptr) return nullptr;
        
        if (root->val > max(p->val,q->val))
            return lowestCommonAncestor(root->left,p,q);
        else if (root->val < min(p->val,q->val))
            return lowestCommonAncestor(root->right,p,q);
        else 
            return root;
    }
};

160.Lowest Common Ancestor of a Binary Tree(LeetCode-236)

  题意: 在二叉树中找到两个节点的最低公共祖先
  解题思路:

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if (root == nullptr || root == p || root == q) return root;
        auto l = lowestCommonAncestor(root->left,p,q);
        auto r = lowestCommonAncestor(root->right,p,q);
        if (l != nullptr && r != nullptr) return root;
        return l == nullptr ? r:l;
    }
};

161.Binary Tree Paths(LeetCode-257)

  题意: 保存二叉树的路径
  解题思路:

class Solution {
public:
    vector<string> binaryTreePaths(TreeNode* root) {
        if(root == nullptr) return{};
        vector<string> ans;
        DFS(root,ans,"");
        return ans;
        
    }
    void DFS(TreeNode* root,vector<string>& ans,string curr) {
        if(root == nullptr) return;
        if(root->left == nullptr && root->right == nullptr) {
            curr += to_string(root->val);
            ans.push_back(curr);
            return;
        }
        curr += to_string(root->val) + "-" + ">";
        DFS(root->left,ans,curr);
        DFS(root->right,ans,curr);
    }
};

162.Sum of Left Leaves(LeetCode-404)

  题意: 二叉树所有左子节点的值的和
  解题思路:

class Solution {
public:
    int sumOfLeftLeaves(TreeNode* root) {
        if(root == nullptr) return 0;
        int val = 0;
        if(root->left != nullptr && root->left->left == nullptr && root->left->right == nullptr) val = root->left->val;
        return val + sumOfLeftLeaves(root->left) + sumOfLeftLeaves(root->right);
    }
};

163.Path Sum III(LeetCode-404)

  题意: 保存二叉树中所有路径和为sum的路径总数

  解题思路:

class Solution {
public:
    int pathSum(TreeNode* root, int sum) {
        unordered_map<int,int> map;
        map[0] = 1;
        return DFS(root,sum,map,0);
        
    }
    int DFS(TreeNode* root,int sum,unordered_map<int,int> &map,int curr_sum) {
        if(root == nullptr) return 0;
        curr_sum += root->val;
        int ans = map[curr_sum - sum];
        map[curr_sum]++;
        ans += DFS(root->left,sum,map,curr_sum) + DFS(root->right,sum,map,curr_sum);
        map[curr_sum]--;
        return ans;
    }
};

164.Delete Node in a BST(LeetCode-450)

  题意: 删除二叉搜索树种的一个节点

  解题思路:

class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if (root == nullptr) return root;
        if (root->val > key)
            root->left = deleteNode(root->left,key);
        else if (root->val < key)
            root->right = deleteNode(root->right,key);
        else {
            TreeNode* new_root = nullptr;
            if (root->left == nullptr)
                new_root = root->right;
            else if (root->right == nullptr)
                new_root = root->left;
            else {
                TreeNode* parent_ = root;
                new_root = root->right;
                while (new_root->left != nullptr) {
                    parent_ = new_root;
                    new_root = new_root->left;
                }
                if (parent_ != root) {
                    parent_->left = new_root->right;
                    new_root->right = root->right;
                }
                new_root->left = root->left;
            }
            delete root;
            return new_root;
        }
        return root;
    }
};

165.Find Mode in Binary Search Tree(LeetCode-501)

  题意:
Given a binary search tree (BST) with duplicates, find all the mode(s) (the most frequently occurred element) in the given BST.
  解题思路:

class Solution {
public:
    vector<int> findMode(TreeNode* root) {
       vector<int> ans;
       int freq = 1;
       int count = 0;
       DFS(root,ans);
       return ans;
    }
    
    int max_count = 0,curr_count = 0,prev_val = INT_MAX;
    void DFS(TreeNode* root,vector<int>& ans) {
        if(root == nullptr) return;
        DFS(root->left,ans);
        
        curr_count++;
        if(root->val != prev_val) {
            prev_val = root->val;
            curr_count = 1;
        }
        if(curr_count > max_count) {
            max_count = curr_count;
            ans.clear();
            ans.push_back(root->val);
        } else if(curr_count == max_count) {
            ans.push_back(root->val);
        }
            
        DFS(root->right,ans);
    }
};

166.Most Frequent Subtree Sum(LeetCode-508)

  题意:
Given the root of a tree, you are asked to find the most frequent subtree sum. The subtree sum of a node is defined as the sum of all the node values formed by the subtree rooted at that node (including the node itself). So what is the most frequent subtree sum value? If there is a tie, return all the values with the highest frequency in any order.
Given a binary search tree (BST) with duplicates, find all the mode(s) (the most frequently occurred element) in the given BST.
  解题思路:

class Solution {
public:
    
    vector<int> findFrequentTreeSum(TreeNode* root) {
        if(root == nullptr) return{};
        unordered_map<int,int> sum_count;
        DFS(root,sum_count);
        auto cmp = [](const auto &p1, const auto &p2){return p1.second < p2.second;};
        int max = max_element(sum_count.begin(), sum_count.end(),cmp)->second;
        vector<int> ans;
        for(auto m:sum_count) {
            if(m.second == max) 
                ans.push_back(m.first);
        }
        return ans;
    }
    int DFS(TreeNode* root,unordered_map<int,int>& sum_count) {
        if(root == nullptr) return 0;
        int sum = root->val + DFS(root->left,sum_count) + DFS(root->right,sum_count);
        sum_count[sum]++;
        return sum;
    }
};

167.Minimum Absolute Difference in BST(LeetCode-508)

  题意:
Given a binary search tree with non-negative values, find the minimum absolute difference between values of any two nodes.
  解题思路:

class Solution {
public:
    int getMinimumDifference(TreeNode* root) {
        int ans = INT_MAX;
        DFS(root,ans);
        return ans;
    }
    TreeNode* prev_ = nullptr;
    void DFS(TreeNode* root,int& ans) {
        if(root == nullptr) return;
        DFS(root->left,ans);
        if(prev_ != nullptr) {
            ans = min(ans,abs(prev_->val - root->val));
        }
        prev_ = root;
        DFS(root->right,ans);
    }
};

168.Convert BST to Greater Tree(LeetCode-538)

  题意:
Given a Binary Search Tree (BST), convert it to a Greater Tree such that every key of the original BST is changed to the original key plus sum of all keys greater than the original key in BST.
  解题思路:

class Solution {
public:
    int sum = 0;
    TreeNode* convertBST(TreeNode* root) {
      if(root == nullptr) 
          return nullptr;
      root->right = convertBST(root->right);
      root->val += sum;
      sum = root->val;
      root->left = convertBST(root->left);
      return root;
    }   
};

169.Diameter of Binary Tree(LeetCode-543)

  题意:
Given a binary tree, you need to compute the length of the diameter of the tree. The diameter of a binary tree is the length of the longest path between any two nodes in a tree. This path may or may not pass through the root.
  解题思路:

class Solution {
public:
    int diameterOfBinaryTree(TreeNode* root) {
        int ans = 0;
        DFS(root,ans);
        return ans;
    }
    int DFS(TreeNode* root,int& ans) {
        if(root == nullptr) return 0;
        int l = DFS(root->left,ans);
        int r = DFS(root->right,ans);
        ans = max(ans,l + r);
        return max(l,r) + 1;
    }
};

170.Binary Tree Tilt(LeetCode-563)

  题意:
Given a binary tree, return the tilt of the whole tree.

The tilt of a tree node is defined as the absolute difference between the sum of all left subtree node values and the sum of all right subtree node values. Null node has tilt 0.

The tilt of the whole tree is defined as the sum of all nodes’ tilt.
  解题思路:

class Solution {
public:
    int findTilt(TreeNode* root) {
        int ans = 0;
        findTilt(root,ans);
        return ans;
    }
    int findTilt(TreeNode* root,int& ans) {
        if(root == nullptr) return 0;
        int left = findTilt(root->left,ans);
        int right = findTilt(root->right,ans);
        ans += abs(left - right);
        return left + right + root->val;
    }
};

171.Subtree of Another Tree(LeetCode-572)

  题意: 判断t是否为s的子树
  解题思路:

class Solution {
public:
    bool isSubtree(TreeNode* s, TreeNode* t) {
        if(s == nullptr) return false;
        if(t == nullptr) return true;
        
        if(isMatch(s,t))
            return true;
        return isSubtree(s->left,t) || isSubtree(s->right,t);
        
    }
    bool isMatch(TreeNode* s1,TreeNode* s2) {
        if(s1 == nullptr && s2 == nullptr)
            return true;
        if(s1 == nullptr || s2 == nullptr) 
            return false;
        if(s1->val != s2->val)
            return false;
        return isMatch(s1->left,s2->left) && isMatch(s1->right,s2->right);
    }
};

172.Construct String from Binary Tree(LeetCode-606)

  题意: 根据二叉树前序遍历构建由节点值和括号组成的字符串
  解题思路:

class Solution {
public:
    string tree2str(TreeNode* t) {
        if(t == nullptr) return "";
        if(t->left == nullptr&& t->right != nullptr)
            return to_string(t->val) + "()" + "(" + tree2str(t->right) + ")";
        if(t->left == nullptr && t->right == nullptr)
            return to_string(t->val);
        if(t->left != nullptr && t->right == nullptr)
            return to_string(t->val) +  "(" + tree2str(t->left) + ")";
        else
            return to_string(t->val) +  "(" + tree2str(t->left) + ")"+"(" + tree2str(t->right) + ")";
    }
};

173.Merge Two Binary Trees(LeetCode-617)

  题意: 将两个二叉树合并
You need to merge them into a new binary tree. The merge rule is that if two nodes overlap, then sum node values up as the new value of the merged node. Otherwise, the NOT null node will be used as the node of new tree.
  解题思路:

class Solution {
public:
    TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
        if(t1 == nullptr) return t2;
        if(t2 == nullptr) return t1;
        
        t1->val += t2->val;
        t1->left = mergeTrees(t1->left,t2->left);
        t1->right = mergeTrees(t1->right,t2->right);
        return t1;  
    }
};

174.Find Duplicate Subtrees(LeetCode-652)

  题意:
Given a binary tree, return all duplicate subtrees. For each kind of duplicate subtrees, you only need to return the root node of any one of them.
Two trees are duplicate if they have the same structure with same node values.
  解题思路:

class Solution {
public:
    vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
        if(root == nullptr) return{};
        unordered_map<string,int> count;
        vector<TreeNode*> ans;
        DFS(root,count,ans);
        return ans;
    }
    string DFS(TreeNode* root,unordered_map<string,int>& count,vector<TreeNode*>& ans) {
        if(root == nullptr) return "#";
        string s = to_string(root->val) + "," + DFS(root->left,count,ans) + "," + DFS(root->right,count,ans);
        if(++count[s] == 2)  
            ans.push_back(root);
        return s;
    }
};

175.Two Sum IV - Input is a BST(LeetCode-653)

  题意:
Given a Binary Search Tree and a target number, return true if there exist two elements in the BST such that their sum is equal to the given target.
  解题思路:

class Solution {
public:
    bool findTarget(TreeNode* root, int k) {
        unordered_set<int> count;
        return DFS(root,count,k);
    }
    bool DFS(TreeNode* root,unordered_set<int>& count,int k) {
        if(root == nullptr) return false;
        if(count.find(k - root->val) != count.end()) return true;
        count.insert(root->val);
        return DFS(root->left,count,k) || DFS(root->right,count,k);
    }
};

176.Maximum Binary Tree(LeetCode-654)

  题意:
Given an integer array with no duplicates. A maximum tree building on this array is defined as follow:

The root is the maximum number in the array.
The left subtree is the maximum tree constructed from left part subarray divided by the maximum number.
The right subtree is the maximum tree constructed from right part subarray divided by the maximum number.

Construct the maximum tree by the given array and output the root node of this tree.
  解题思路:

class Solution {
public:
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        return DFS(cbegin(nums),cend(nums));
    }
private:
    typedef vector<int>::const_iterator VIT;
    TreeNode* DFS(VIT l,VIT r) {
        if(l >= r) return nullptr;
        VIT m = max_element(l,r);
        TreeNode* root = new TreeNode(*m);
        root->left = DFS(l,m);
        root->right = DFS(next(m),r);
        return root;
    }
};

177.Print Binary Tree(LeetCode-655)

  题意: 矩阵方式打印二叉树
  解题思路:

class Solution {
public:
    vector<vector<string>> printTree(TreeNode* root) {
        int h = get_height(root);
        int w = (1 << h) - 1;
        vector<vector<string>> ans(h,vector<string>(w,""));
        fill(root,ans,0,w - 1,0);
        return ans;
        
    }
    int get_height(TreeNode* root) {
        if(root == nullptr) return 0;
        return max(get_height(root->left),get_height(root->right)) + 1;
    }
    void fill(TreeNode* root,vector<vector<string>>& ans,int l,int r,int h) {
        if(root == nullptr) return;
        int m = (l + r) >> 1;
        ans[h][m] = to_string(root->val);
        fill(root->left,ans,l,m - 1, h + 1);
        fill(root->right,ans,m + 1,r, h + 1);
    }
};

178.Maximum Width of Binary Tree(LeetCode-662)

  题意: 二叉树的最大宽度
  解题思路: DFS或BFS都可以

class Solution {
public:
    int widthOfBinaryTree(TreeNode* root) {
        unordered_map<int, unsigned long> map;
        int ans = 0;
        DFS(root,map,0,0,ans);
        return ans;
    }
    void DFS(TreeNode* root,unordered_map<int,unsigned long>& map,int depth,unsigned long pos,int& ans) {
        if (root == nullptr) return;
        if (map.find(depth) == map.end()) {
            map[depth] = pos;
        }
        ans = max(ans,int(pos - map[depth]) + 1);
        DFS(root->left,map,depth + 1,2 * pos,ans);
        DFS(root->right,map,depth + 1,2 * pos + 1,ans);
    }
};

179.Trim a Binary Search Tree(LeetCode-669)

  题意:
Given a binary search tree and the lowest and highest boundaries as L and R, trim the tree so that all its elements lies in [L, R] (R >= L). You might need to change the root of the tree, so the result should return the new root of the trimmed binary search tree.
  解题思路:

class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int L, int R) {
        if(root == nullptr) return nullptr;
        if(root->val < L) return trimBST(root->right,L,R);
        else if(root->val > R) return trimBST(root->left,L,R);
        else {
            root->left = trimBST(root->left,L,R);
            root->right = trimBST(root->right,L,R);
        }
    }
};

180.Second Minimum Node In a Binary Tree(LeetCode-671)

  题意:
Given a non-empty special binary tree consisting of nodes with the non-negative value, where each node in this tree has exactly two or zero sub-node. If the node has two sub-nodes, then this node’s value is the smaller value among its two sub-nodes. More formally, the property root.val = min(root.left.val, root.right.val) always holds.

Given such a binary tree, you need to output the second minimum value in the set made of all the nodes’ value in the whole tree.

If no such second minimum value exists, output -1 instead.
  解题思路:

class Solution {
public:
    int findSecondMinimumValue(TreeNode* root) {
        return DFS(root,root->val);
    }
    int DFS(TreeNode* root,int small_est) {
        if(root == nullptr) return -1;
        if(root->val > small_est) return root->val;
        
        int l = DFS(root->left,small_est);
        int r = DFS(root->right,small_est);
        
        if(l == -1 ) return r;
        if(r == -1 ) return l;
        return min(l,r);
    } 
};

181.Longest Univalue Path(LeetCode-671)

  题意:
Given a binary tree, find the length of the longest path where each node in the path has the same value. This path may or may not pass through the root.
The length of path between two nodes is represented by the number of edges between them.
  解题思路:

class Solution {
public:
    int longestUnivaluePath(TreeNode* root) {
        int ans = 0;
        DFS(root,ans);
        return ans;
    }
    int DFS(TreeNode* root,int& ans) {
        if(root == nullptr) return 0;
        int l = DFS(root->left,ans);
        int r = DFS(root->right,ans);
        if(root->left != nullptr && root->left->val == root->val)
            l++;
        else
            l = 0;
        if(root->right != nullptr && root->right->val == root->val)
            r++;
        else
            r = 0;
        ans = max(l + r,ans);
        return max(l,r);
    }
};

182.Insert into a Binary Search Tree(LeetCode-701)

  题意: 在二叉搜索树中插入一个节点
  解题思路:

class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        if (root == nullptr) {
            root = new TreeNode(val);
        }
        if (root->val > val) 
            root->left = insertIntoBST(root->left,val);
        if (root->val < val)
            root->right = insertIntoBST(root->right,val);
        
        return root;
    }
};

183.Binary Tree Pruning(LeetCode-814)

  题意: We are given the head node root of a binary tree, where additionally every node’s value is either a 0 or a 1.Return the same tree where every subtree (of the given tree) not containing a 1 has been removed.
  解题思路:

class Solution {
public:
    TreeNode* pruneTree(TreeNode* root) {
        if(root == nullptr) return nullptr;
        root->left = pruneTree(root->left);
        root->right = pruneTree(root->right);
        if(root->left == nullptr && root->right == nullptr && root->val == 0)
            return nullptr;
        return root;
    }
};

184.All Nodes Distance K in Binary Tree(LeetCode-863)

  题意:
We are given a binary tree (with root node root), a target node, and an integer value K.Return a list of the values of all nodes that have a distance K from the target node. The answer can be returned in any order.
  解题思路: DFS或者图的BFS都可以

class Solution {
public:
    vector<int> distanceK(TreeNode* root, TreeNode* target, int K) {
        build_graph(nullptr,root);
        vector<int> ans;
        unordered_set<TreeNode*> seen;
        queue<TreeNode*> q;
        seen.insert(target);
        q.push(target);
        int k = 0;
        while (!q.empty() && k <= K) {
            int s = q.size();
            while (s--) {
                auto node = q.front();
                q.pop();
                if (k == K) ans.push_back(node->val);
                for (auto child : g[node]) {
                    if (seen.count(child)) continue;
                    q.push(child);
                    seen.insert(child);
                }
            }
            ++k;
        }
        return ans;
    }
    
private:
    unordered_map<TreeNode*,vector<TreeNode*>> g;
    void build_graph(TreeNode* parent,TreeNode* child) {
        if (parent) {
            g[parent].push_back(child);
            g[child].push_back(parent);
        }
        if (child->left) build_graph(child,child->left);
        if (child->right) build_graph(child,child->right);
    }
};
class Solution {
public:
    vector<int> distanceK(TreeNode* root, TreeNode* target, int K) {
        ans.clear();
        dis(root,target,K);
        return ans;
    }
private:
    vector<int> ans;
    int dis(TreeNode* root, TreeNode* target, int K) {
        if (root == nullptr) return -1;
        if (root == target) {
            collect(target,K);
            return 0;
        }
        int l = dis(root->left,target,K);
        int r = dis(root->right,target,K);
        
        if (l >= 0) {
            if (l + 1 == K) ans.push_back(root->val);
            collect(root->right, K - l - 2);
            return l + 1;
        }
        if (r >= 0) {
            if (r + 1 == K) ans.push_back(root->val);
            collect(root->left, K - r - 2);
            return r + 1;
        }
        
        return -1;
        
    }
    void collect(TreeNode* root,int d) {
        if (root == nullptr || d < 0) return;
        if (d == 0) ans.push_back(root->val);
        collect(root->left, d - 1);
        collect(root->right, d - 1);
    }
};

185.Smallest Subtree with all the Deepest Nodes(LeetCode-865)

  题意:
Given a binary tree rooted at root, the depth of each node is the shortest distance to the root.

A node is deepest if it has the largest depth possible among any node in the entire tree.

The subtree of a node is that node, plus the set of all descendants of that node.

Return the node with the largest depth such that it contains all the deepest nodes in its subtree.
  解题思路:

class Solution {
public:
    TreeNode* subtreeWithAllDeepest(TreeNode* root) {
        TreeNode* ans;
        DFS(root,&ans);
        return ans;
        
    }
    int DFS(TreeNode* Node,TreeNode** ans) {
        if (Node == nullptr) return 0;
        TreeNode* node_l;
        TreeNode* node_r;
        int l = DFS(Node->left,&node_l);
        int r = DFS(Node->right,&node_r);
        
        if (l == r) *ans = Node;
        if (l > r) *ans = node_l;
        if (l < r) *ans = node_r;
        
        return max(l,r) + 1;
        
    }
};

186.Leaf-Similar Trees(LeetCode-872)

  题意: 判断两个二叉树的叶子节点是否一致
  解题思路:

public:
    bool leafSimilar(TreeNode* root1, TreeNode* root2) {
        
       vector<int> result1 =  GetLeafNodes(root1);
       vector<int> result2 =  GetLeafNodes(root2);
       
      return result1 == result2;
        
    }
    vector<int> GetLeafNodes(TreeNode* root) {
        vector<int> result;
        if (root->left == NULL && root->right == NULL) {
            result.push_back(root->val);
            return result;
        }
        if(root->left != NULL)
            result = GetLeafNodes(root->left);
        
        if(root->right != NULL) {
            vector<int> result1 = GetLeafNodes(root->right);
            result.insert(result.end(),result1.begin(),result1.end());
        }
        return result;
        
    }
};

187.All Possible Full Binary Trees(LeetCode-894)

  题意: A full binary tree is a binary tree where each node has exactly 0 or 2 children.给定一个正整数N,生成所有的满二叉树
  解题思路:

class Solution {
public:
    vector<TreeNode*> allPossibleFBT(int N) {
        if(N % 2 == 0) return{};
        vector<TreeNode*> ans;
        if(N == 1) {
            ans.push_back(new TreeNode(0));
            return ans;
        }
        for(int i = 1; i < N; i += 2) {
            for(TreeNode* left_Node:allPossibleFBT(i)) {
                for(TreeNode* right_Node:allPossibleFBT(N - i - 1)) {
                    TreeNode* root = new TreeNode(0);
                    root->left = left_Node;
                    root->right = right_Node;
                    ans.push_back(root);   
                }
            }
        }
        return ans;
    }
};

188.Increasing Order Search Tree(LeetCode-897)

  题意: Given a binary search tree, rearrange the tree in in-order so that the leftmost node in the tree is now the root of the tree, and every node has no left child and only 1 right child.
  解题思路:

class Solution {
public:
    TreeNode* curr = nullptr;
    TreeNode* increasingBST(TreeNode* root) {
        if(root == nullptr) return nullptr;
        TreeNode* ans = new TreeNode(0);
        curr = ans;
        inorder(root);
        return ans->right;
    }
    void inorder(TreeNode* root) {
        if(root == nullptr) return;
        inorder(root->left);
        root->left = nullptr;
        curr->right = root;
        curr = curr->right;
        inorder(root->right);
    }
};

189.Flip Equivalent Binary Trees(LeetCode-951)

  题意:
For a binary tree T, we can define a flip operation as follows: choose any node, and swap the left and right child subtrees.
A binary tree X is flip equivalent to a binary tree Y if and only if we can make X equal to Y after some number of flip operations.
Write a function that determines whether two binary trees are flip equivalent. The trees are given by root nodes root1 and root2.
  解题思路:

class Solution {
public:
    bool flipEquiv(TreeNode* root1, TreeNode* root2) {
        if(root1 == nullptr && root2 == nullptr)
            return true;
        if(root1 != nullptr && root2 == nullptr)
            return false;
        if(root1 == nullptr && root2 != nullptr)
            return false;
        if(root1->val != root2->val)
            return false;
        return  (flipEquiv(root1->left,root2->right) && flipEquiv(root1->right,root2->left)) ||
                (flipEquiv(root1->left,root2->left) && flipEquiv(root1->right,root2->right));
    }
};

190.Univalued Binary Tree(LeetCode-965)

  题意: 判断二叉树中的所有节点值是否为一个值
  解题思路:

class Solution {
public:
    bool isUnivalTree(TreeNode* root) {
        if (root == nullptr) return true;
        auto l = isUnivalTree(root->left);
        auto r = isUnivalTree(root->right);
        bool flag1 = true;
        if (root->left != nullptr && root->left->val != root->val)
            flag1 = false;
        bool flag2 = true;
        if (root->right != nullptr && root->right->val != root->val)
            flag2 = false;
        return flag1 && flag2 && l && r;
    }
};

191.Construct Binary Search Tree from Preorder Traversal(LeetCode-1008)

  题意: 根据二叉搜索树的前序遍历来构建二叉树
  解题思路:

class Solution {
public:
    
    typedef vector<int>::const_iterator VIT;
    TreeNode* bstFromPreorder(vector<int>& preorder) {
        return bstFromPreorder(cbegin(preorder),cend(preorder));
    }
    
    TreeNode* bstFromPreorder(VIT pre_l,VIT pre_r) {
        if(pre_l >= pre_r) return nullptr;
        TreeNode* root = new TreeNode(*pre_l);
        VIT m = pre_r;
        for(VIT temp = next(pre_l); temp < pre_r;temp++) {
            if(*temp > root->val) {
                m = temp;
                break;
            }
        }
        root->left = bstFromPreorder(next(pre_l),m);
        root->right = bstFromPreorder(m,pre_r); 
        
        return root;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值