美文网首页我爱编程C++
LeetCode using C++ and Java (kee

LeetCode using C++ and Java (kee

作者: mengduan | 来源:发表于2017-12-30 16:05 被阅读0次

    LeetCode的题目非常是碎片化时间来做,而且可以尝试最新的C++标准和多种语言, 正好要学习Java,就C++和Java两种语言来做题,如果碰到可以用immutable方式的题目就再用Scala做一下。

    1. Two Sum

    Given an array of integers, return indices of the two numbers such that they add up to a specific target.You may assume that each input would have exactly one solution, and you may not use the same element twice.
    <p>Example:
    Given nums = [2, 7, 11, 15], target = 9, Because nums[0] + nums[1] = 2 + 7 = 9, return [0, 1].

    Tags: Array, HashTable

    C++

    class Solution { // (both index1 and index2) are not zero-based.
    public:
        vector<int> twoSum(vector<int>& nums, int target) {
            unordered_map<int, size_t> umap;
            for (size_t i = 0; i < nums.size(); ++i) {
                auto item = nums[i];
                if (umap.find(target - item) == umap.end()) {
                    umap[item] = i;
                } else {
                    return vector<int>{umap[target - item], i};
                }
            }
            return vector<int>{-1, -1};
        }
    };
    

    Java

    public class Solution {
        public int[] twoSum(int[] nums, int target) {
            Map<Integer, Integer> hm = new HashMap<>();
            for (int i = 0; i != nums.length; ++i) {
                int complement = target - nums[i];
                if (hm.get(complement) != null) {
                    return new int[] {hm.get(complement), i};
                } else {
                    hm.put(nums[i], i);
                }
            }
            return null;
        }
    }
    

    Scala

    object Solution {
        def twoSum(nums: Array[Int], target: Int): Array[Int] = {
            var ht = collection.mutable.Map.empty[Int, Int]
            for (i <- 0 until nums.size) {
                val tmp = target - nums(i)
                if (ht.contains(tmp)) {
                    return Array(ht(tmp), i)
                } else {
                    ht(nums(i)) = i
                }
            }
            Array(-1, -1)
        }
    }
    

    2. Add Two Numbers

    You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.You may assume the two numbers do not contain any leading zero, except the number 0 itself.
    Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
    Output: 7 -> 0 -> 8

    Tags: Linked List, Math

    C++

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
            ListNode dummy(-1);
            ListNode* ptr = &dummy;
            int carry = 0;
            while (l1 != nullptr || l2 != nullptr) {
                int a = 0;
                if (l1 != nullptr) {
                    a = l1->val;
                    l1 = l1->next;
                }
                int b = 0;
                if (l2 != nullptr) {
                    b = l2->val;
                    l2 = l2->next;
                }
                int sum = a + b + carry;
                carry = sum / 10;
                ptr->next = new ListNode(sum % 10);
                ptr = ptr->next;
            }
            if (carry > 0) {
                ptr->next = new ListNode(carry);
            }
            return dummy.next;
        }
    
    };
    

    Java

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    public class Solution {
        public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
            int carrier = 0;
            ListNode dummy = new ListNode(0);
            ListNode cur = dummy;
            while (l1 != null || l2 != null) {
                int x = l1 == null ? 0 : l1.val;
                int y = l2 == null ? 0 : l2.val;
                int val = x + y + carrier;
                carrier = val / 10;
                cur.next = new ListNode(val % 10);
                cur = cur.next;
                if (l1 != null) {
                    l1 = l1.next;
                }
                if (l2 != null) {
                    l2 = l2.next;
                }
            }
            if (carrier > 0) {
                cur.next = new ListNode(carrier);
            }
            return dummy.next;
        }
    }
    

    Scala

    /**
     * Definition for singly-linked list.
     * class ListNode(var _x: Int = 0) {
     *   var next: ListNode = null
     *   var x: Int = _x
     * }
     */
    object Solution {
        def addTwoNumbers(l1: ListNode, l2: ListNode): ListNode = {
            var dummyNode = new ListNode(0)
            var cur = dummyNode
            var carry = 0
            def addInternal(l1: ListNode, l2: ListNode): Unit = {
                if (l1 != null || l2 != null) {
                    var a = if (l1 != null) l1.x else 0
                    var b = if (l2 != null) l2.x else 0
                    var sum = a + b + carry
                    cur.next = new ListNode(sum % 10)
                    cur = cur.next
                    carry = sum / 10
                    addInternal(if (l1 != null) l1.next else null, if(l2 != null) l2.next else null)
                }
            }
            addInternal(l1, l2)
            if (carry > 0) {
                cur.next = new ListNode(carry)
            }
            dummyNode.next
        }
    }
    

    3. Longest Substring Without Repeating Characters

    Given a string, find the length of the longest substring without repeating characters.
    <p>Examples:
    Given "abcabcbb", the answer is "abc", which the length is 3.
    Given "bbbbb", the answer is "b", with the length of 1.
    Given "pwwkew", the answer is "wke", with the length of 3. Note that the answer must be a substring, "pwke" is a subsequence and not a substring.

    Tags: Hash Table, Two Pointers, String

    C++

    class Solution {
    public:
        int lengthOfLongestSubstring(string s) {
            int ret = 0;
            vector<int> ht(256, -1);
            int i = 0;
            for (int j = 0; j < s.size(); ++j) {
                auto k = ht[s[j]];
                if (k >= i) {
                    i = k + 1;
                } else {
                    ret = std::max(ret, j - i + 1);
                }
                ht[s[j]] = j;
            }
            return ret;
        }
    };
    

    Java

    public class Solution {
        public int lengthOfLongestSubstring(String s) {
            int ret = 0;
            Map<Character, Integer> hm = new HashMap<>();
            int i = 0;
            for (int j = 0; j < s.length(); ++j) {
                int k = hm.getOrDefault(s.charAt(j), -1);
                if (k >= i) {
                    i = k + 1;
                } else {
                    ret = Math.max(ret, j - i + 1);
                }
                hm.put(s.charAt(j), j);
            }
            return ret;
        }
    }
    

    4. Median of Two Sorted Arrays

    There are two sorted arrays nums1 and nums2 of size m and n respectively.
    Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
    <p>Example 1:
    nums1 = [1, 3]
    nums2 = [2]
    The median is 2.0
    <p>Example 2:
    nums1 = [1, 2]
    nums2 = [3, 4]
    The median is (2 + 3)/2 = 2.5

    Tags: Divide and Conquer, Binary Search, Array

    C++

    class Solution {
    public:
        double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
            auto sz = nums1.size() + nums2.size();
            if (sz & 0x01) {
                auto ret = findKthElement(begin(nums1), nums1.size(), begin(nums2), nums2.size(), sz / 2 + 1);
                //auto ret = findKthElement(nums1.data(), nums1.size(), nums2.data(), nums2.size(), sz / 2 + 1);
                return static_cast<double>(ret);
            } else {
                auto ret1 = findKthElement(begin(nums1), nums1.size(), begin(nums2), nums2.size(), sz / 2);
                auto ret2 = findKthElement(begin(nums1), nums1.size(), begin(nums2), nums2.size(), sz / 2 + 1);
                //auto ret1 = findKthElement(nums1.data(), nums1.size(), nums2.data(), nums2.size(), sz / 2);
                //auto ret2 = findKthElement(nums1.data(), nums1.size(), nums2.data(), nums2.size(), sz / 2 + 1);
                return (static_cast<double>(ret1) + static_cast<double>(ret2)) / 2.0;
            }
        }
        
    private:
        int findKthElement(const int* nums1, size_t len1, const int* nums2, size_t len2, size_t k) {
            if (len1 > len2) {
                return findKthElement(nums2, len2, nums1, len1, k);
            }
            if (len1 == 0) {
                return nums2[k - 1];
            }
            if (k == 1) {
                return min(nums1[k - 1], nums2[k - 1]);
            }
            auto dis1 = min(k / 2, len1);
            auto dis2 = k - dis1;
            if (nums1[dis1 - 1] < nums2[dis2 - 1]) {
                return findKthElement(nums1 + dis1, len1 - dis1, nums2, len2, k - dis1);
            } else if (nums1[dis1 - 1] > nums2[dis2 - 1]) {
                return findKthElement(nums1, len1, nums2 + dis2, len2 - dis2, k - dis2);
            } else {
                return nums1[dis1 - 1];
            }
            return -1;
        }
        
        int findKthElement(vector<int>::const_iterator begin_1, 
                           size_t len_1,
                           vector<int>::const_iterator begin_2, 
                           size_t len_2, 
                           size_t k) {
            if (len_1 > len_2) {
                return findKthElement(begin_2, len_2, begin_1, len_1, k);
            }
            if (len_1 == 0) {
                return *(begin_2 + k - 1);
            }
            if (k == 1) {
                return std::min(*begin_1, *begin_2);
            }
            auto dis_1 = std::min(k / 2, len_1);
            auto dis_2 = k - dis_1;
            if (*(begin_1 + dis_1 - 1) < *(begin_2 + dis_2 - 1)) {
                return findKthElement(begin_1 + dis_1, len_1 - dis_1, begin_2, len_2, k - dis_1);
            } else if (*(begin_1 + dis_1 - 1) > *(begin_2 + dis_2 - 1)) {
                return findKthElement(begin_1, len_1, begin_2 + dis_2, len_2 - dis_2, k - dis_2);
            } else {
                return *(begin_1 + dis_1 - 1);
            }
            return -1;
        }
    
    };
    

    Java

    public class Solution {
        public double findMedianSortedArrays(int[] nums1, int[] nums2) {
            int len = nums1.length + nums2.length;
            if ((len & 0x01) == 0x01) {
                return findKthElement(nums1, 0, nums2, 0, len / 2 + 1);
            } else {
                double left = findKthElement(nums1, 0, nums2, 0, len / 2);
                double right = findKthElement(nums1, 0, nums2, 0, len / 2 + 1);
                return (left + right) / 2.0;
            }
        }
        
        private double findKthElement(int[] nums1, int start1, int[] nums2, int start2, int k) {
            if ((nums1.length - start1) > (nums2.length - start2)) {
                return findKthElement(nums2, start2, nums1, start1, k);
            }
            if ((nums1.length - start1) <= 0) {
                return (double) nums2[start2 + k - 1];
            }
            if (k == 1) {
                return Math.min((double) nums1[start1], (double) nums2[start2]);
            }
            int dis1 = Math.min(k / 2, nums1.length - start1);
            int dis2 = k - dis1;
            if (nums1[start1 + dis1 - 1] < nums2[start2 + dis2 - 1]) {
                return findKthElement(nums1, start1 + dis1, nums2, start2, k - dis1);
            } else if (nums1[start1 + dis1 - 1] > nums2[start2 + dis2 - 1]) {
                return findKthElement(nums1, start1, nums2, start2 + dis2, k - dis2);
            } else {
                return (double) nums1[start1 + dis1 - 1];
            }
        }
    }
    

    5. Longest Palindromic Substring

    Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
    <p>Example:
    Input: "babad"
    Output: "bab"
    Note: "aba" is also a valid answer.
    <p>Example:
    Input: "cbbd"
    Output: "bb"

    Tags String

    注意C++的substr和Java的substring的区别

    C++

    class Solution {
    public:
        string longestPalindrome(string s) {
            int start = 0;
            int len = 1;
            for (int i = 0; i < s.length(); ++i) {
                auto cur = _getLongestPalindromeLength(s, i);
                if (cur > len) {
                    len = cur;
                    start = i - (len - 1) / 2;
                }
            }
            return s.substr(start, len);
        }
        
    private:
        inline int _getLongestPalindromeLength(const string &s, int i) {
            return max(_getLongestPalindromeLength(s, i, i), _getLongestPalindromeLength(s, i, i + 1));
        }
        
        inline int _getLongestPalindromeLength(const string &s, int left, int right) {
            while (left >= 0 && right < static_cast<int>(s.length()) && s[left] == s[right]) {
                --left;
                ++right;
            }
            return right - left - 1;
        }
        
    };
    

    Java

    public class Solution {
        public String longestPalindrome(String s) {
            int len = 1;
            int start = 0;
            for (int i = 0; i < s.length(); ++i) {
                int cur = getLongestPalindromeLength(s, i);
                if (cur > len) {
                    len = cur;
                    start = i - (len - 1) / 2;
                }
            }
            return s.substring(start, start + len);
        }
        
        private int getLongestPalindromeLength(String s, int i) {
            return Math.max(getLongestPalindromeLength(s, i, i), getLongestPalindromeLength(s, i, i + 1));
        }
        
        private int getLongestPalindromeLength(String s, int left, int right) {
            while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
                --left;
                ++right;
            }
            return right - left - 1;
        }
    }
    

    6. ZigZag Conversion

    The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)
    P A H N
    A P L S I I G
    Y I R
    And then read line by line: "PAHNAPLSIIGYIR"
    Write the code that will take a string and make this conversion given a number of rows:
    string convert(string text, int nRows);
    convert("PAYPALISHIRING", 3) should return "PAHNAPLSIIGYIR".

    Tags: string

    C++

    class Solution {
    public:
        string convert(string s, int numRows) {
            if (numRows <= 1 || numRows >= static_cast<int>(s.size())) {
                return s;
            }
            vector<string> ret(numRows, "");
            int row_cursor = 0;
            int step = 0;
            for (size_t idx = 0; idx != s.size(); ++idx) {
                ret[row_cursor].push_back(s[idx]);
                if (row_cursor == 0) {
                    step = 1;
                } else if (row_cursor == numRows - 1) {
                    step = -1;
                }
                row_cursor += step; // update row_cursor
            }
            string result;
            result.reserve(numRows);
            for_each(ret.begin(), ret.end(), [&result](string& item) { result += std::move(item); });
            return result;
        }
    };
    

    Java

    public class Solution {
        public String convert(String s, int numRows) {
            if (s.isEmpty() || numRows ==1 || numRows >= s.length()) {
                return s;
            }
            ArrayList<StringBuilder> ret = new ArrayList<>(Collections.nCopies(numRows, null));
            int idx = 0;
            int step = 0;
            for (int i = 0; i < s.length(); ++i) {
                if (ret.get(idx) == null) {
                    ret.set(idx, new StringBuilder());
                }
                ret.get(idx).append(s.charAt(i));
                if (idx == numRows - 1) {
                    step = -1;
                } else if (idx == 0) {
                    step = 1;
                }
                idx += step;
            }
            for (int i = 1; i < ret.size(); ++i) {
                ret.get(0).append(ret.get(i));
            }
            return ret.get(0).toString();
        }
    }
    

    7. Reverse Integer

    Reverse digits of an integer.
    Example1: x = 123, return 321
    Example2: x = -123, return -321

    Tags: Math

    C++

    class Solution {
    public:
        int reverse(int x) {
            int ret = 0;
            for ( ; x != 0; x /= 10) {
                int tail = x % 10;
                int tmp = ret * 10 + tail;
                if ((tmp - tail) / 10 != ret) { // overflow
                    return 0;
                }
                ret = tmp;
            }
            return ret;
        }
    };
    
    class Solution {
    public:
        int reverse(int x) {
            int flag = x < 0 ? -1 : 1;
            int ret = 0;
            while (x != 0) {
                int cur = (x % 10) * flag;
                if (ret > INT_MAX / 10 || (ret == INT_MAX / 10 && cur > INT_MAX % 10)) {
                    return 0;
                }
                ret = 10 * ret + cur;
                x /= 10;
            }
            return flag * ret;
        }
    };
    

    Java

    public class Solution {
        public int reverse(int x) {
            int ret = 0;
            for ( ; x != 0; x /= 10) {
                int tail = x % 10;
                int tmp = ret * 10 + tail;
                if ((tmp - tail) / 10 != ret) {
                    return 0;
                }
                ret = tmp;
            }
            return ret;
        }
    }
    
    public class Solution {
        public int reverse(int x) {
            int ret = 0;
            int flag = x < 0 ? -1 : 1;
            while (x != 0) {
                int cur = (x % 10) * flag;
                if (ret > Integer.MAX_VALUE / 10 || (ret == Integer.MAX_VALUE / 10 && cur > Integer.MAX_VALUE % 10)) {
                    return 0;
                }
                ret = 10 * ret + cur;
                x /= 10;
            }
            return flag * ret;
        }
    }
    

    8. String to Integer (atoi)

    Implement atoi to convert a string to an integer.
    Hint: Carefully consider all possible input cases. If you want a challenge, please do not see below and ask yourself what are the possible input cases.
    <p>Notes: It is intended for this problem to be specified vaguely (ie, no given input specs). You are responsible to gather all the input requirements up front.

    Tags: Math, String

    C++

    class Solution {
    public:
        int myAtoi(string str) {
            int ret = 0;
            auto int_max = std::numeric_limits<int>::max();
            auto int_min = std::numeric_limits<int>::min();
            auto iter = std::begin(str);
            while (*iter == ' ') {
                ++iter;
            }
            bool negative = false;
            if (*iter == '-' || *iter == '+') {
                if(*iter == '-') {
                    negative = true;
                }
                ++iter;
            }
            for ( ; iter != std::end(str) && std::isdigit(*iter); ++iter) {
                int cur = *iter - '0';
                if (ret > int_max / 10 || (ret == int_max / 10 && cur > int_max % 10)) {
                    return negative ? int_min : int_max;
                }
                ret = ret * 10 + cur;
            }
            return negative ? -ret : ret;
        }
    };
    

    Java

    public class Solution {
        public int myAtoi(String str) {
            int ret = 0;
            boolean negative = false;
            int idx = 0;
            // deal empty string which not the same as C++ and String is iteratable (java Collections)
            if (str.isEmpty()) {
                return ret;
            }
            // remove leading space
            for ( ; str.charAt(idx) == ' '; ++idx) {}
            // get flag
            if (str.charAt(idx) == '+' || str.charAt(idx) == '-') {
                negative = (str.charAt(idx) == '-' ? true : false);
                ++idx;
            }
            // parsing digit chars
            for ( ; idx < str.length(); ++idx) {
                int cur = str.charAt(idx) - '0';
                if (cur < 0 || cur > 9) {
                    break;
                }
                if (ret > Integer.MAX_VALUE / 10 || (ret == Integer.MAX_VALUE / 10 && Integer.MAX_VALUE % 10 < cur)) {
                    return negative ? Integer.MIN_VALUE : Integer.MAX_VALUE;
                }
                ret = ret * 10 + cur;
            }
            return negative ? -ret : ret;
        }
    }
    

    9. Palindrome Number

    Tags: String

    Cpp

    class Solution {
    public:
        bool isPalindrome(int x) {
            string s1 = std::move(std::to_string(x));
            string s2(s1);
            reverse(s1.begin(), s1.end());
            return s1 == s2;
        }
    };
    

    Java

    public class Solution {
        public boolean isPalindrome(int x) {
            String a = String.valueOf(x);
            String b = (new StringBuilder(a)).reverse().toString();
            return a.equals(b);
        }
    }
    

    10. Regular Expression Matching

    Implement regular expression matching with support for '.' and '*'.
    '.' Matches any single character.
    '*' Matches zero or more of the preceding element.<p>The matching should cover the entire input string (not partial).
    The function prototype should be:
    bool isMatch(const char s, const char p)
    <p>Some examples:
    isMatch("aa","a") ? false
    isMatch("aa","aa") ? true
    isMatch("aaa","aa") ? false
    isMatch("aa", "a
    ") ? true
    isMatch("aa", ".
    ") ? true
    isMatch("ab", ".") ? true
    isMatch("aab", "c
    a*b") ? true

    Tag: String, Dynamic Programming, Backtracking

    Use Dynamic Programming

    Cpp

    class Solution {
    public:
        bool isMatch(string s, string p) {
            // last char is the key postion, which may be '*' or not
            // match[i][j] record the s[0 : i - 1] matched p[0 : j - 1] so
            // match[0][0] = true, match[1 : ][0] = false, match[0][1 : ] = (j > 1 && match[0][j - 2] && p[j - 1] == '*')
            // match[i][j] = p[j - 1] != '*' && (match[i - 1][j - 1] && (s[i - 1] == p[j - 1] || p[j - 1] == '.'))
            // match[i][j] = p[j - 1] == '*' && (match[i][j - 2] || (match[i - 1][j] && (s[i - 1] == p[j - 2] || p[j - 1] == '.')))
            vector<vector<bool>> match(s.length() + 1, vector<bool>(p.length() + 1, false));
            match[0][0] = true;
            
            for (size_t i = 1; i < match.size(); ++i) {
                match[i][0] = false;
            }
            
            for (size_t j = 1; j < match[0].size(); ++j) {
                match[0][j] = (j > 1) && match[0][j - 2] && (p[j - 1] == '*');
            }
            
            for (size_t i = 1; i < match.size(); ++i) {
                for (size_t j = 1; j < match[0].size(); ++j) {
                    if (p[j - 1] != '*') {
                        match[i][j] = match[i - 1][j - 1] && (s[i - 1] == p[j - 1] || p[j - 1] == '.');
                    } else { // p[j - 1] is '*' so p[j - 2] must exist and match[i - 1][j] covers match[i - 1][j - 2]
                        match[i][j] = match[i][j - 2] || (match[i - 1][j] && (s[i - 1] == p[j - 2] || p[j - 2] == '.'));
                    }
                }
            }
            return match.back().back();
        }
    };
    

    Java

    public class Solution {
        public boolean isMatch(String s, String p) {
            // last char is the key postion, which may be '*' or not
            // match[i][j] record the s[0 : i - 1] matched p[0 : j - 1] so
            // match[0][0] = true, match[1 : ][0] = false, match[0][1 : ] = (j > 1 && match[0][j - 2] && p[j - 1] == '*')
            // match[i][j] = p[j - 1] != '*' && (match[i - 1][j - 1] && (s[i - 1] == p[j - 1] || p[j - 1] == '.'))
            // match[i][j] = p[j - 1] == '*' && (match[i][j - 2] || (match[i - 1][j] && (s[i - 1] == p[j - 2] || p[j - 1] == '.')))
            boolean[][] match = new boolean[s.length() + 1][p.length() + 1];
            match[0][0] = true;
            
            for (int i = 1; i < match.length; ++i) {
                match[i][0] = false;
            }
            
            for (int j = 1; j < match[0].length; ++j) {
                match[0][j] = (j > 1) && match[0][j - 2] && p.charAt(j - 1) == '*';
            }
            
            for (int i = 1; i < match.length; ++i) {
                for (int j = 1; j < match[0].length; ++j) {
                    if (p.charAt(j - 1) != '*') {
                        match[i][j] = match[i - 1][j - 1] && (s.charAt(i - 1) == p.charAt(j - 1) || p.charAt(j - 1) == '.');
                    } else { // p[j - 1] is '*' so p[j - 2] must exist and match[i - 1][j] covers match[i - 1][j - 2]
                        match[i][j] = match[i][j - 2] || (match[i - 1][j] && (s.charAt(i - 1) == p.charAt(j - 2) || p.charAt(j - 2) == '.'));
                    }
                }
            }
            return match[s.length()][p.length()];
        }
    }
    

    Use Backtracking

    class Solution {
    public:
        bool isMatch(string s, string p) {
            return isMatch(s.c_str(), p.c_str());
        }
    
    private:
        // use c++ string's feature (end with '\0') to avoid some condition check in java
        inline bool charMatch(const char *s, const char *p) {
            return (*s == *p || (*p == '.' && *s != '\0'));
        }
        bool isMatch(const char *s, const char *p) {
            if (*p == '\0') {
                return *s == '\0';
            }
            if (*(p + 1) != '*') {
                return charMatch(s, p) && isMatch(s + 1, p + 1);
            } else if (charMatch(s, p)) {
                return isMatch(s + 1, p) || isMatch(s, p + 2);
            } else {
                return isMatch(s, p + 2);
            }
        }
    };
    

    11. Container With Most Water

    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.
    Note: You may not slant the container and n is at least 2.

    Tags: two pointer

    Cpp

    class Solution {
    public:
        int maxArea(vector<int>& height) {
            int ret = 0;
            if (height.size() < 2) {
                return ret;
            }
            size_t left = 0;
            size_t right = height.size() - 1;
            while (left < right) {
                ret = max(ret, min(height[left], height[right]) * static_cast<int>(right - left));
                height[left] < height[right] ? ++left : --right;
            }
            return ret;
        }
    };
    

    Java

    public class Solution {
        public int maxArea(int[] height) {
            int ret = 0;
            if (height.length < 2) {
                return ret;
            }
            int left = 0;
            int right = height.length - 1;
            while (left < right) {
                ret = Math.max(ret, Math.min(height[left], height[right]) * (right - left));
                if (height[left] < height[right]) {
                    ++left;
                } else {
                    --right;
                }
            }
            return ret;
        }
    }
    

    12. Integer to Roman

    Cpp

    class Solution {
    public:
        string intToRoman(int num) {
            vector<string> symbol{"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
            vector<int> value{1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
            string ret;
            for (int i = 0; num > 0; ++i) {
                while (num >= value[i]) {
                    num -= value[i];
                    ret += symbol[i];
                }
            }
            return ret;
        }
    };
    

    Java

    public class Solution {
        public String intToRoman(int num) {
            String ret = "";
            ArrayList<String> symbol = new ArrayList(
                Arrays.asList("M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"));
            ArrayList<Integer> value = new ArrayList(
                Arrays.asList(1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1));
            for (int i = 0; num > 0; ++i) {
                while (num >= value.get(i)) {
                    num -= value.get(i);
                    ret = ret + symbol.get(i);
                }
            }
            return ret;
        }
    }
    

    13. Roman to Integer

    Cpp

    class Solution {
    public:
        int romanToInt(string s) {
            int ret = 0;
            int pre = 0;
            unordered_map<char, int> umap {
                make_pair('I', 1), make_pair('V', 5), make_pair('X', 10), \
                make_pair('L', 50), make_pair('C', 100), make_pair('D', 500), \
                make_pair('M', 1000)};
            for (const auto& c : s) {
                int cur = umap.at(c);
                if (cur <= pre) {
                    ret += cur;
                } else {
                    ret += cur - 2 * pre; // ret = ret - pre + cur - pre
                }
                pre = cur;
            }
            return ret;
        }
    };
    

    Java

    public class Solution {
        public int romanToInt(String s) {
            HashMap<Character, Integer> hmap = new HashMap<>();
            hmap.put('I', 1);
            hmap.put('V', 5);
            hmap.put('X', 10);
            hmap.put('L', 50);
            hmap.put('C', 100);
            hmap.put('D', 500);
            hmap.put('M', 1000);
            int ret = 0;
            int pre = 0;
            for (int i = 0; i < s.length(); ++i) {
                int cur = hmap.get(s.charAt(i));
                if (cur <= pre) {
                    ret += cur;
                } else {
                    ret = ret - 2 * pre + cur;
                }
                pre = cur;
            }
            return ret;
        }
    }
    

    14. Longest Common Prefix

    Cpp

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

    Java

    public class Solution {
        public String longestCommonPrefix(String[] strs) {
            if (strs.length <= 0) {
                return "";
            }
            for (int cursor = 0; cursor < strs[0].length(); ++cursor) {
                char pre = strs[0].charAt(cursor);
                for (int i = 1; i < strs.length; ++i) {
                    if (cursor >= strs[i].length() || strs[i].charAt(cursor) != pre) {
                        return strs[0].substring(0, cursor);
                    }
                }
            }
            return strs[0];
        }
    }
    

    15. 3Sum

    Cpp

    class Solution {
    public:
        vector<vector<int>> threeSum(vector<int>& nums) {
            vector<vector<int>> ret;
            int len = static_cast<int>(nums.size());
            
            std::sort(nums.begin(), nums.end());
            for (int i = 0; i < len - 2 && nums[i] <= 0; ++i) {
                // remove possible duplicate results
                if (i > 0 && nums[i] == nums[i -1 ]) {
                    continue;
                }   
                int left = i + 1;
                int right = len - 1;
                while (left < right) {
                    auto sum = nums[i] + nums[left] + nums[right];
                    if (sum == 0) {
                        ret.push_back(vector<int>{nums[i], nums[left++], nums[right--]});
                        // remove possible duplicate results
                        while (left < right && nums[left] == nums[left - 1]) {
                            ++left;
                        }
                        while (left < right && nums[right] == nums[right + 1]) {
                            --right;
                        }
                    } else if (sum > 0) {
                        --right;
                    } else {
                        ++left;
                    }
                    
                }
            }
            return ret;
        }
    };
    

    Java

    public class Solution {
        public List<List<Integer>> threeSum(int[] nums) {
            List<List<Integer>> ret = new ArrayList<>();
            int len = nums.length;
            
            Arrays.sort(nums);
            for (int i  = 0; i < len - 2 && nums[i] <= 0; ++i) {
                // remove possible duplicate results
                if (i > 0 && nums[i] == nums[i - 1]) {
                    continue;
                }
                
                int left = i + 1;
                int right = len - 1;
                while (left < right) {
                    int sum = nums[i] + nums[left] + nums[right];
                    if (sum == 0) {
                        ret.add(new ArrayList(Arrays.asList(nums[i], nums[left], nums[right])));
                        ++left;
                        --right;
                        // remove possible duplicate results
                        while (left < right && nums[left] == nums[left - 1]) {
                            ++left;
                        }
                        while (left < right && nums[right] == nums[right + 1]) {
                            --right;
                        }
                    } else if (sum > 0) {
                        --right;
                    } else {
                        ++left;
                    }
                }
            }
            return ret;
        }
    }
    

    16. 3sum closet

    Cpp

    class Solution {
    public:
        int threeSumClosest(vector<int>& nums, int target) {
            int len = nums.size();
            assert(len >= 3);
            int min_diff = INT_MAX;
            std::sort(nums.begin(), nums.end());
            
            for (int i = 0; i < (len - 2); ++i) {
                if (i > 0 && nums[i] == nums[i - 1]) {
                    continue;
                }
                int left = i + 1;
                int right = len - 1;
                while (left < right) {
                    int cur_diff = nums[i] + nums[left] + nums[right] - target;
                    if (cur_diff == 0) {
                        return target;
                    } else if (cur_diff > 0) {
                        right--;
                    } else {
                        left++;
                    }
                    min_diff = abs(cur_diff) < abs(min_diff) ? cur_diff : min_diff;
                }
            }
            return min_diff + target;
        }
    };
    

    Java

    public class Solution {
        public int threeSumClosest(int[] nums, int target) {
            int len = nums.length;
            int minDiff = Integer.MAX_VALUE;
            
            Arrays.sort(nums);
            for (int i = 0; i < len - 2; ++i) {
                // avoid duplicate calc
                if (i > 0 && nums[i] == nums[i - 1]) {
                    continue;
                }
                int left = i + 1;
                int right = len - 1;
                while (left < right) {
                    int curDiff = nums[i] + nums[left] + nums[right] - target;
                    if (curDiff == 0) {
                        return target;
                    } else if (curDiff > 0) {
                        --right;
                    } else {
                        ++left;
                    }
                    if (Math.abs(curDiff) < Math.abs(minDiff)) {
                        minDiff = curDiff;
                    }
                }
            }
            return minDiff + target;
        }
    }
    

    17. Letter Combinations of a Phone Number

    Given a digit string, return all possible letter combinations that the number could represent.
    A mapping of digit to letters (just like on the telephone buttons) is given below.

    Tags: backtracking, string

    Cpp

    class Solution {
    public:
        vector<string> letterCombinations(string digits) {
            vector<string> ret;
            if (digits.empty()) {
                return ret;
            }
            vector<string> keyboard{" ", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
            // return letterCombinationsIterative(digits, keyboard);
            letterCombinations(ret, "", 0, digits, keyboard);
            return ret;
        }
    
    private:
        void letterCombinations(vector<string> &ret, const string &cur, size_t idx, 
                                const string &digits, const vector<string> &keyboard) {
            if (idx >= digits.size()) {
                ret.push_back(cur);
            } else {
                for (auto c : keyboard[digits[idx] - '0']) {
                    letterCombinations(ret, cur + c, idx + 1, digits, keyboard);
                }
            }
            
        }
        
        vector<string> letterCombinationsIterative(const string &digits, const vector<string> &keyboard) {
            vector<string> ret{""};
            for (auto d : digits) {
                vector<string> tmp;
                for (auto r : ret) {
                    for (auto c : keyboard[d - '0']) {
                        tmp.push_back(r + c);
                    }
                }
                ret.swap(tmp);
            }
            return ret;
        }
    };
    

    Java

    public class Solution {
        public List<String> letterCombinations(String digits) {
            List<String> ret = new ArrayList<>();
            if (digits.isEmpty()) {
                return ret;
            }
            ArrayList<String> keyboard = new ArrayList(
                Arrays.asList(" ", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"));
            // return letterCombinationsIterative(digits, keyboard);
            letterCombinationsRecursive(ret, "", 0, digits, keyboard);
            return ret;
        }
        
        private void letterCombinationsRecursive(List<String> ret, String cur, int idx,
                                           String digits, List<String> keyboard) {
            if (idx >= digits.length()) {
                ret.add(cur);
            } else {
                String key = keyboard.get(digits.charAt(idx) - '0');
                for (int i = 0; i < key.length(); ++i) {
                    letterCombinationsRecursive(ret, cur + key.charAt(i), idx + 1, digits, keyboard);
                }
            }
        }
    
        private List<String> letterCombinationsIterative(String digits, List<String> keyboard) {
            List<String> ret = new ArrayList<>();
            ret.add("");
            for (int i = 0; i < digits.length(); ++i) {
                List<String> tmp = new ArrayList<>();
                for (String r : ret) {
                    int cur = digits.charAt(i) - '0';
                    for (int j = 0; j < keyboard.get(cur).length(); ++j) {
                        tmp.add(r + keyboard.get(cur).charAt(j));
                    }
                }
                ret = tmp;
            }
            return ret;
        }
    }
    

    Scala

    object Solution {
        def letterCombinations(digits: String): List[String] = {
            val ret = List[String]()
            val keyboard = Array(" ", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz")
            digits.isEmpty match {
                case true => ret
                case false => 
                    //letterCombinationsIterative(digits, keyboard)
                    letterCombinationsRecursive(0, digits, keyboard)
            }
        }
        
        private def letterCombinationsRecursive(start: Int, digits: String, keyboard: Array[String]): List[String] = {
            if (start >= digits.size) {
                List("")
            } else {
                val tmp = letterCombinationsRecursive(start + 1, digits, keyboard)
                (for {
                    k <- keyboard(digits(start) - '0')
                    t <- tmp
                } yield (k + t)).toList
            }
        }
        
        private def letterCombinationsIterative(digits: String, keyboard: Array[String]): List[String] = {
            digits.foldLeft(List("")) { (ret, d) => ret.flatMap { r => keyboard(d - '0').map { k => r + k } } }
        }
    }
    

    18. 4Sum

    Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
    Note: The solution set must not contain duplicate quadruplets.<p>For example, given array S = [1, 0, -1, 0, -2, 2], and target = 0.
    A solution set is:
    [
    [-1, 0, 0, 1],
    [-2, -1, 1, 2],
    [-2, 0, 0, 2]
    ]

    Tags: two pointer

    Cpp

    class Solution {
    public:
        vector<vector<int>> fourSum(vector<int>& nums, int target) {
            vector<vector<int>> ret;
            if (nums.size() < 4) {
                return ret;
            }
            sort(nums.begin(), nums.end());
            vector<int> cur;
            ksum(ret, 0, 4, cur, target, nums);
            return ret;
        }
    
    private:
        void ksum(vector<vector<int>> &ret, int start, int k, vector<int> &cur, 
                  int target, const vector<int> &nums) {
            if (k * nums.front() > target || k * nums.back() < target) {
                return;
            } else if (k == 2) {
                int left = start;
                int right = nums.size() - 1;
                while (left < right) {
                    auto sum = nums[left] + nums[right] - target;
                    if (sum == 0) {
                        auto tmp = cur;
                        tmp.push_back(nums[left]);
                        tmp.push_back(nums[right]);
                        ret.push_back(tmp);
                        ++left;
                        --right;
                        // avoid possible duplicates
                        while (left < right && nums[left] == nums[left - 1]) {
                            ++left;
                        }
                        while (left < right && nums[right] == nums[right + 1]) {
                            --right;
                        }
                    } else if (sum > 0) {
                        --right;
                    } else {
                        ++left;
                    }
                }
            } else {
                for (int i = start; i < nums.size() -k + 1; ++i) {
                    if (i > start && nums[i] == nums[i - 1]) {
                        continue;
                    }
                    cur.push_back(nums[i]);
                    ksum(ret, i + 1, k - 1, cur, target - nums[i], nums);
                    cur.pop_back();
                }
            }
        }
       
    };
    

    Java

    public class Solution {
        public List<List<Integer>> fourSum(int[] nums, int target) {
            List<List<Integer>> ret = new ArrayList<>();
            if (nums.length < 4) {
                return ret;
            }
            Arrays.sort(nums);
            List<Integer> cur = new ArrayList<>();
            ksum(ret, 0, 4, cur, target, nums);
            return ret;
        }
        
        private void ksum(List<List<Integer>> ret, int start, int k, 
                          List<Integer> cur, int target, int[] nums) {
            if (k * nums[0] > target || k * nums[nums.length - 1] < target) {
                return;
            } else if (k == 2) {
                int left = start;
                int right = nums.length - 1;
                while (left < right) {
                    int sum = nums[left] + nums[right] - target;
                    if (sum == 0) {
                        List<Integer> tmp = new ArrayList<>(cur);
                        tmp.add(nums[left]);
                        tmp.add(nums[right]);
                        ret.add(tmp);
                        ++left;
                        --right;
                        // avoid possible duplicates
                        while (left < right && nums[left] == nums[left - 1]) {
                            ++left;
                        }
                        while (left < right && nums[right] == nums[right + 1]) {
                            --right;
                        }
                    } else if (sum > 0) {
                        --right;
                    } else {
                        ++left;
                    }
                }
            } else {
                for (int i = start; i < nums.length - k + 1; ++i) {
                    if (i > start && nums[i] == nums[i - 1]) {
                        continue;
                    }
                    cur.add(nums[i]);
                    ksum(ret, i + 1, k - 1, cur, target - nums[i], nums);
                    cur.remove(cur.size() - 1);
                }
            }
        }
    }
    

    Scala

    object Solution {
        def fourSum(nums: Array[Int], target: Int): List[List[Int]] = {
            var ret: List[List[Int]] = List()
            if (nums.size < 4) return ret
            val sortedNums = nums.sorted
            var cur: List[Int] = List()
            
            def ksum(start: Int, k: Int, target: Int): Unit = {
                if (k == 2) {
                    var left = start;
                    var right = sortedNums.size - 1
                    while (left < right) {
                        var sum = sortedNums(left) + sortedNums(right) - target
                        if (sum == 0) {
                            var tmp = cur ::: List(sortedNums(left), sortedNums(right))
                            ret = ret ::: List(tmp)
                            left += 1
                            right -= 1
                            while (left < right && sortedNums(left) == sortedNums(left - 1)) left += 1
                            while (left < right && sortedNums(right) == sortedNums(right + 1)) right -= 1
                        } else if (sum > 0) {
                            right -= 1
                        } else left += 1
                    }
                } else {
                    for (i <- start until sortedNums.length - k + 1) {
                        if (i == start || sortedNums(i) != sortedNums(i - 1)) {
                            var tmp = cur
                            cur = cur ::: List(sortedNums(i))
                            ksum(i + 1, k - 1, target - sortedNums(i))
                            cur = tmp
                        }
                    }
                }
            }
            ksum(0, 4, target)
            ret
        }
    }
    

    19. Remove Nth Node From End of List

    Tags: List

    Cpp

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* removeNthFromEnd(ListNode* head, int n) {
            ListNode dummy = ListNode(0);
            dummy.next = head;
            ListNode *first = &dummy;
            
            for (int i = 0; i < n; ++i) {
                if (first == nullptr) {
                    return nullptr;
                } else {
                    first = first->next;
                }
            }
            
            ListNode *pre = &dummy;
            for (; first != nullptr && first->next != nullptr; first = first->next) {
                pre = pre->next;
            }
            
            auto tmp = pre->next->next;
            delete pre->next;
            pre->next = tmp;
            
            return dummy.next;
        }
    };
    

    Java

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    public class Solution {
        public ListNode removeNthFromEnd(ListNode head, int n) {
            ListNode dummy = new ListNode(0);
            dummy.next = head;
            ListNode first = dummy;
            
            for (int i = 0; i < n; ++i) {
                if (first == null) {
                    return null;
                } else {
                    first = first.next;
                }
            }
            
            ListNode ptr = dummy;
            for (; first != null && first.next != null; first = first.next) {
                ptr = ptr.next;
            }
            ListNode tmp = ptr.next.next;
            ptr.next = null;
            ptr.next = tmp;
            
            return dummy.next;
        }
    }
    

    20. Valid Parentheses

    Tags: Stack

    Cpp

    class Solution {
    public:
        bool isValid(string s) {
            stack<char> stc;
            for (auto c : s) {
                if (isLeft(c)) {      
                    stc.push(c);
                } else if (stc.empty()) {
                    return false;
                } else if (isMatch(stc.top(), c)) {
                    stc.pop();
                } else {
                    return false;
                }
            }
            return stc.empty();
        }
        
    private:
        bool isLeft(char c) {
            return (c == '(' || c == '{' || c == '[');
        }
        
        bool isMatch(char l, char r) {
            if (l == '(') {
                return r == ')';
            } else if (l == '{') {
                return r == '}';
            } else if (l == '[') {
                return r == ']';
            } else {
                return false;
            }
        }
        
    };
    

    Java

    public class Solution {
        public boolean isValid(String s) {
            Stack<Character> stc = new Stack<>();
            for (int i = 0; i < s.length(); ++i) {
                char c = s.charAt(i);
                if (isLeft(c)) {      
                    stc.push(c);
                } else if (stc.empty()) {
                    return false;
                } else if (isMatch(stc.peek(), c)) {
                    stc.pop();
                } else {
                    return false;
                }
            }
            return stc.empty();
        }
        
        private boolean isLeft(char c) {
            return (c == '(' || c == '{' || c == '[');
        }
        
        private boolean isMatch(char l, char r) {
            if (l == '(') {
                return r == ')';
            } else if (l == '{') {
                return r == '}';
            } else if (l == '[') {
                return r == ']';
            } else {
                return false;
            }
        }
        
    };
    

    Scala

    object Solution {
        def isValid(s: String): Boolean = {
            val parenthesesMap = Map('(' -> ')', '{' -> '}', '[' -> ']')
            val ret = s.foldLeft(List[Char]()) { (stc, c) =>
                c match {
                    case '(' | '{' | '[' => c :: stc
                    case ')' | '}' | ']' =>
                        if (stc.isEmpty) return false
                        else if (parenthesesMap.get(stc.head) != Some(c)) return false
                        else stc.tail
                }
            }
            ret.isEmpty
        }
    }
    

    21. Merge Two Sorted Lists

    Cpp

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
            if (l1 == nullptr) {
                return l2;
            } else if (l2 == nullptr) {
                return l1;
            } else if (l1->val < l2->val) {
                l1->next = mergeTwoLists(l1->next, l2);
                return l1;
            } else {
                l2->next = mergeTwoLists(l1, l2->next);
                return l2;
            }
        }
    };
    

    Java

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    public class Solution {
        public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
            if (l1 == null) {
                return l2;
            } else if (l2 == null) {
                return l1;
            } else if (l1.val < l2.val) {
                l1.next = mergeTwoLists(l1.next, l2);
                return l1;
            } else {
                l2.next = mergeTwoLists(l1, l2.next);
                return l2;
            }
        }
    }
    

    Scala

    /**
     * Definition for singly-linked list.
     * class ListNode(var _x: Int = 0) {
     *   var next: ListNode = null
     *   var x: Int = _x
     * }
     */
    object Solution {
        def mergeTwoLists(l1: ListNode, l2: ListNode): ListNode = {
            (l1, l2) match {
                case (null, _) => l2
                case (_, null) => l1
                case _ => (l1.x < l2.x) match {
                    case true => 
                        l1.next = mergeTwoLists(l1.next, l2)
                        l1
                    case false => 
                        l2.next = mergeTwoLists(l1, l2.next)
                        l2
                }
            }
        }
    }
    

    22. Generate Parentheses

    Cpp

    class Solution {
    public:
        vector<string> generateParenthesis(int n) {
            vector<string> ret;
            generateParenthesis(ret, "", n, n);
            return ret;
        }
    
    private:
        void generateParenthesis(vector<string> &ret, string cur, int curLeftNum, int curRightNum) {
            if (curLeftNum == 0 && curRightNum == 0) {
                ret.push_back(cur);
            }
            if (curLeftNum > 0) {
                generateParenthesis(ret, cur + '(', curLeftNum - 1, curRightNum);
            }
            if (curRightNum > curLeftNum) {
                generateParenthesis(ret, cur + ')', curLeftNum, curRightNum - 1);
            }
        }
    };
    

    Java

    public class Solution {
        public List<String> generateParenthesis(int n) {
            List<String> ret = new ArrayList<>();
            generateParenthesis(ret, "", n, n);
            return ret;
        }
        
        private void generateParenthesis(List<String> ret, String cur, int curLeftNum, int curRightNum) {
            if (curLeftNum == 0 && curRightNum == 0) {
                ret.add(cur);
            }
            if (curLeftNum > 0) {
                generateParenthesis(ret, cur + "(", curLeftNum - 1, curRightNum);
            }
            if (curRightNum > curLeftNum) {
                generateParenthesis(ret, cur + ")", curLeftNum, curRightNum - 1);
            }
        }
    }
    

    Scala

    object Solution {
        def generateParenthesis(n: Int): List[String] = {
            generateInternal(List[String](), "", n, n)
        }
        
        private def generateInternal(ret: List[String], cur: String, curLeftNum: Int, curRightNum: Int): List[String] = {
            if (curLeftNum == 0 && curRightNum == 0) {
                ret ::: List(cur)
            } else {
                val ret1 = {
                    if (curLeftNum > 0) 
                        generateInternal(ret, cur + "(", curLeftNum - 1, curRightNum) 
                    else 
                        ret
                }
                val ret2 = {
                    if (curRightNum > curLeftNum) 
                        generateInternal(ret1, cur + ")", curLeftNum, curRightNum - 1) 
                    else 
                        ret1
                }
                ret2
            }
        }
    }
    

    23. Merge k Sorted Lists

    Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

    Tags: Linked List, Divide and Conquer, Heap

    C++

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* mergeKLists(vector<ListNode*>& lists) {
            if (lists.empty()) {
                return nullptr;
            }
            for (int sz = static_cast<int>(lists.size()); sz > 1; ) {
                int offset = (sz + 1) / 2;
                for (int i = 0; i < sz / 2; ++i) {
                    lists[i] = mergeTwoLists(lists[i], lists[i + offset]);
                }
                sz = offset;
            }
            return lists.front();
        }
        
    private:
        ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
            if (l1 == nullptr) {
                return l2;
            } else if (l2 == nullptr) {
                return l1;
            } else if (l1->val < l2->val) {
                l1->next = mergeTwoLists(l1->next, l2);
                return l1;
            } else {
                l2->next = mergeTwoLists(l1, l2->next);
                return l2;
            }
        }
    };
    

    Java

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    public class Solution {
        public ListNode mergeKLists(ListNode[] lists) {
            if (lists.length == 0) {
                return null;
            }
            for (int sz = lists.length; sz > 1; ) {
                int offset = (sz + 1) / 2;
                for (int i = 0; i < sz / 2; ++i) {
                    lists[i] = mergeTwoLists(lists[i], lists[i + offset]);
                }
                sz = offset;
            }
            return lists[0];
        }
        
        private ListNode mergeTwoLists(ListNode l1, ListNode l2) {
            if (l1 == null) {
                return l2;
            } else if (l2 == null) {
                return l1;
            } else if (l1.val < l2.val) {
                l1.next = mergeTwoLists(l1.next, l2);
                return l1;
            } else {
                l2.next = mergeTwoLists(l1, l2.next);
                return l2;
            }
        }
    }
    

    24. Swap Nodes in Pairs

    Given a linked list, swap every two adjacent nodes and return its head.
    For example,
    Given 1->2->3->4, you should return the list as 2->1->4->3.
    Your algorithm should use only constant space. You may not modify the values in the list, only nodes itself can be changed.

    Tags: LinkedList

    C++

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* swapPairs(ListNode* head) {
            ListNode dummy(1);
            dummy.next = head;
            auto pre = &dummy;
            for (auto cur = head; cur != nullptr && cur->next != nullptr; cur = cur->next) {
                auto tmp = cur->next;
                cur->next = tmp->next;
                tmp->next = cur;
                pre->next = tmp;
                pre = cur;
            }
            return dummy.next;
        }
    };
    

    Java

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    class Solution {
        public ListNode swapPairs(ListNode head) {
            ListNode dummy = new ListNode(1);
            dummy.next = head;
            ListNode pre = dummy;
            for (ListNode cur = head; cur != null && cur.next != null; cur = cur.next) {
                ListNode tmp = cur.next;
                cur.next = tmp.next;
                tmp.next = cur;
                pre.next = tmp;
                pre = cur;
            }
            return dummy.next;
        }
    }
    

    25. Reverse Nodes in k-Group

    Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.

    k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.
    You may not alter the values in the nodes, only nodes itself may be changed.
    Only constant memory is allowed.

    For example,
    Given this linked list: 1->2->3->4->5
    For k = 2, you should return: 2->1->4->3->5
    For k = 3, you should return: 3->2->1->4->5

    Tags: Array, HashTable

    C++

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* reverseKGroup(ListNode* head, int k) {
            ListNode dummy = ListNode(0);
            dummy.next = head;
            auto pre = &dummy;
            auto ptr = &dummy;
            for (int i = 0; i < k && ptr != nullptr; ++i) {
                ptr = ptr->next;
            }
            while (ptr != nullptr) {
                auto nextDummy = pre->next;
                for (int i = 1; i < k; ++i) {
                    auto tmp = pre->next->next;
                    pre->next->next = ptr->next;
                    ptr->next = pre->next;
                    pre->next = tmp;
                }
                pre = nextDummy;
                ptr = nextDummy;
                for (int i = 0; i < k && ptr != nullptr; ++i) {
                    ptr = ptr->next;
                }
            }
            return dummy.next;
        }
    };
    

    Java

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    class Solution {
        public ListNode reverseKGroup(ListNode head, int k) {
            ListNode dummy = new ListNode(0);
            dummy.next = head;
            ListNode pre = dummy;
            ListNode ptr = dummy;
            for (int i = 0; i < k && ptr != null; ++i) {
                ptr = ptr.next;
            }
            while (ptr != null) {
                ListNode nextDummy = pre.next;
                for (int i = 1; i < k; ++i) {
                    ListNode tmp = pre.next.next;
                    pre.next.next = ptr.next;
                    ptr.next = pre.next;
                    pre.next = tmp;
                }
                pre = nextDummy;
                ptr = nextDummy;
                for (int i = 0; i < k && ptr != null; ++i) {
                    ptr = ptr.next;
                }
            }
            return dummy.next;
        }
    }
    

    26. Remove Duplicates from Sorted Array

    Cpp

    class Solution {
    public:
        int removeDuplicates(vector<int>& nums) {
            int pre = -1;
            for (int cur = 0; cur < static_cast<int>(nums.size()); ++cur) {
                if (pre == -1) {
                    ++pre;
                } else if (nums[cur] != nums[cur - 1]) {
                    nums[++pre] = nums[cur];
                }
            }
            return pre + 1;
        }
    };
    

    Java

    public class Solution {
        public int removeDuplicates(int[] nums) {
            int pre = -1;
            for (int cur = 0; cur < nums.length; ++cur) {
                if (pre == -1) {
                    ++pre;
                } else if (nums[cur] != nums[cur - 1]) {
                    nums[++pre] = nums[cur];
                }
            }
            return pre + 1;
        }
    }
    

    Scala

    object Solution {
        def removeDuplicates(nums: Array[Int]): Int = {
            var pre = -1
            for (cur <- 0 until nums.length) {
                if (pre == -1) {
                    pre += 1
                } else if (nums(cur) != nums(cur - 1)) {
                    pre += 1
                    nums(pre) = nums(cur)
                }
            }
            return pre + 1
        }
    }
    

    27. Remove Element

    C++

    class Solution {
    public:
        int removeElement(vector<int>& nums, int val) {
            int ret = 0;
            for (auto n : nums) {
                if (n != val) {
                    nums[ret++] = n;
                }
            }
            return ret;
        }
    };
    

    Java

    class Solution {
        public int removeElement(int[] nums, int val) {
            int ret = 0;
            for (int i = 0; i < nums.length; ++i) {
                if (nums[i] != val) {
                    nums[ret++] = nums[i];
                }
            }
            return ret;
        }
    }
    

    Scala

    object Solution {
        def removeElement(nums: Array[Int], v: Int): Int = {
            var ret = 0
            for (i <- 0 until nums.size) {
                if (nums(i) != v) {
                    nums(ret) = nums(i)
                    ret += 1
                }
            }
            return ret
        }
    }
    

    28. Implement strStr

    Tags: Two Pointers, String

    C++

    class Solution {
    public:
        int strStr(string haystack, string needle) {
            int ret1 = strStrBackoff(haystack, needle);
            int ret2 = strStrBruteForce(haystack, needle);
            int ret3 = strStrKMP(haystack, needle);
            cout << ret1 << " " << ret2 << " " << ret3 << endl;
            assert(ret1 == ret2 && ret2 == ret3);
            return ret1;
        }
        
    private:
        int strStrBruteForce(const string &source, const string &target) {
            int src_len = static_cast<int>(source.size());
            int tgt_len = static_cast<int>(target.size());
            for (int i = 0; i <= src_len - tgt_len; ++i) {
                int j = 0;
                for ( ; j < tgt_len && source[i + j] == target[j]; ++j) {}
                if (j == tgt_len) {
                    return i;
                }
            }
            return -1;
        }
        int strStrBackoff(const string &source, const string &target) {
            int src_len = static_cast<int>(source.size());
            int tgt_len = static_cast<int>(target.size());
            int i = 0;
            int j = 0;
            for ( ; i < src_len && j < tgt_len; ++i) {
                if (source[i] == target[j]) {
                    ++j;
                } else {
                    i -= j;
                    j = 0;
                }
            }
            if (j == tgt_len) {
                return i - tgt_len;
            }
            return -1;
        }
        int strStrKMP(string source, string target) {
            if (target.empty()) {
                return 0;
            }
            auto getPattern = [](const string& str) {
                vector<int> pattern(str.length(), 0);
                int k = 0;
                for (size_t i = 1; i < str.length(); ++i) {
                    while (k > 0 && str[k] != str[i]) {
                        k = pattern[k - 1];
                    }
                    if (str[k] == str[i]) {
                        ++k;
                    }
                    pattern[i] = k;
                }
                return pattern;
            };
            auto pattern = getPattern(target);
            int k = 0;
            for (size_t i = 0; i < source.length(); ++i) {
                while (k > 0 && source[i] != target[k]) {
                    k = pattern[k - 1];
                }
                if (source[i] == target[k]) {
                    ++k;
                }
                if (k == target.length()) {
                    return i - k + 1;
                }
            }
            return -1;
        }
    
    };
    

    Java

    class Solution {
        public int strStr(String haystack, String needle) {
            int ret1 = strStrBruteForce(haystack, needle);
            int ret2 = strKMP(haystack, needle);
            int ret3 = strStrBackoff(haystack, needle);
            System.out.println("ret1 = " + ret1 + " ret2 = " + ret2 + " ret3 = " + ret3);
            assert ret1 == ret2;
            assert ret2 == ret3;
            return ret2;
        }
        
        private int strStrBackoff(String source, String target) {
            int i = 0;
            int j = 0;
            for ( ; i < source.length() && j < target.length(); ) {
                if (source.charAt(i) == target.charAt(j)) {
                    ++j;
                } else {
                    i -= j;
                    j = 0;
                }
                ++i;
            }
            if (j == target.length()) {
                return i - j;
            }
            return -1;
        }
        
        private int strStrBruteForce(String source, String target) {
            for (int i = 0; i <= source.length() - target.length(); ++i) {
                int j = 0;
                for ( ; j < target.length() && source.charAt(i + j) == target.charAt(j); ++j) {}
                if (j == target.length()) {
                    return i;
                }
            }
            return -1;
        }
        
        private List<Integer> kmpPattern(String target) {
            List<Integer> pattern = new ArrayList<>(Collections.nCopies(target.length(), 0));
            int k = 0;
            for (int i = 1; i < target.length(); ++i) {
                while (k > 0 && target.charAt(k) != target.charAt(i)) {
                    k = pattern.get(k - 1);
                }
                if (target.charAt(k) == target.charAt(i)) {
                    ++k;
                }
                pattern.set(i, k);
            }
            return pattern;
        }
        private int strKMP(String source, String target) {
            if (target.isEmpty()) {
                return 0;
            }
            List<Integer> pattern = kmpPattern(target);
            int k = 0;
            for (int i = 0; i < source.length(); ++i) {
                while (k > 0 && source.charAt(i) != target.charAt(k)) {
                    k = pattern.get(k - 1);
                }
                if (source.charAt(i) == target.charAt(k)) {
                    ++k;
                }
                if (k == target.length()) {
                    return i - k + 1;
                }
            }
            return -1;
        }
    }
    

    33. Search in Rotated Sorted Array

    Tags: Binary Search

    Cpp

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

    Java

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

    34. Search for a Range

    Cpp

    class Solution {
    public:
        vector<int> searchRange(vector<int>& nums, int target) {
            vector<int> ret{-1, -1};
            ret[0] = findLowerBound(nums, target);
            ret[1] = findUpperBound(nums, target);
            return ret;
        }
    
    private:
        int findLowerBound(const vector<int>& nums, int target) {
            int left = 0;
            int right = static_cast<int>(nums.size()) - 1;
            while (left <= right) {
                int mid = (right - left) / 2 + left;
                // move left to get first greater or equal than target
                if (nums[mid] < target) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
            return nums[left] == target ? left : -1;
        }
        int findUpperBound(const vector<int>& nums, int target) {
            int left = 0;
            int right = static_cast<int>(nums.size()) - 1;
            while (left <= right) {
                int mid = (right - left) / 2 + left;
                // move right to get first less or equal than target
                if (nums[mid] > target) {
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }
            }
            return nums[right] == target ? right : -1;
        }
    
    };
    

    Java

    class Solution {
        public int[] searchRange(int[] nums, int target) {
            int[] ret = {-1, -1};
            ret[0] = lowerBound(nums, target);
            ret[1] = upperBound(nums, target);
            return ret;
        }
        
        private int lowerBound(int[] nums, int target) {
            int left = 0;
            int right = nums.length - 1;
            while (left <= right) {
                int mid = (right - left) / 2 + left;
                if (nums[mid] < target) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
            if (nums[left] == target) {
                return left;
            } else {
                return -1;
            }
        }
        
        private int upperBound(int[] nums, int target) {
            int left = 0;
            int right = nums.length - 1;
            while (left <= right) {
                int mid = (right - left) / 2 + left;
                if (nums[mid] > target) {
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }
            }
            if (nums[right] == target) {
                return right;
            } else {
                return -1;
            }
        }
    }
    

    46. Permutations

    Tags: Backtracking

    C++

    class Solution {
    public:
        vector<vector<int>> permute(vector<int>& nums) {
            vector<vector<int>> ret;
            permute(ret, nums, 0);
            return ret;
        }
    
    private:
        void permute(vector<vector<int>>& ret, vector<int>& nums, int start) {
            if (start == nums.size()) {
                ret.push_back(nums);
            } else {
                for (size_t i = start; i != nums.size(); ++i) {
                    swap(nums[start], nums[i]);
                    permute(ret, nums, start + 1);
                    swap(nums[start], nums[i]);
                }
            }
        }
    
    };
    

    Java

    class Solution {
        public List<List<Integer>> permute(int[] nums) {
            List<List<Integer>> ret = new ArrayList<>();
            List<Integer> numList = Arrays.stream(nums).boxed().collect(Collectors.toList());
            permute(ret, numList, 0);
            return ret;
        }
        
        private void permute(List<List<Integer>> ret, List<Integer> nums, int start) {
            if (start >= nums.size()) {
                ret.add(new ArrayList(nums));
            } else {
                for (int i = start; i < nums.size(); ++i) {
                    Collections.swap(nums, start, i);
                    permute(ret, nums, start + 1);
                    Collections.swap(nums, start, i);
                }
            }
        }
    }
    

    47. Permutations II

    Tags: Backtracking

    C++

    class Solution {
    public:
        vector<vector<int>> permuteUnique(vector<int>& nums) {
            vector<vector<int>> ret;
            permutation(ret, nums, 0);
            return ret;
        }
    
    private:
        void permutation(vector<vector<int>>& ret, vector<int>& nums, size_t start) {
            if (start >= nums.size()) {
                ret.push_back(nums);
            } else {
                for (size_t idx = start; idx != nums.size(); ++idx) {
                    if (std::find(nums.begin() + start, nums.begin() + idx, nums[idx]) == (nums.begin() + idx)) {
                        swap(nums[idx], nums[start]);
                        permutation(ret, nums, start + 1);
                        swap(nums[idx], nums[start]);
                    }
                }
            }
        }
    
    };
    

    Java

    class Solution {
        public List<List<Integer>> permuteUnique(int[] nums) {
            List<List<Integer>> ret = new ArrayList<>();
            List<Integer> numList = Arrays.stream(nums).boxed().collect(Collectors.toList());
            permute(ret, numList, 0);
            return ret;
        }
        
        private void permute(List<List<Integer>> ret, List<Integer> nums, int start) {
            if (start >= nums.size()) {
                ret.add(new ArrayList(nums));
            } else {
                for (int i = start; i < nums.size(); ++i) {
                    int idx = start;
                    for ( ; idx < i; ++idx) {
                        if (nums.get(idx) == nums.get(i)) {
                            break;
                        }
                    }
                    if (idx < i) {
                        continue;
                    }
                    Collections.swap(nums, start, i);
                    permute(ret, nums, start + 1);
                    Collections.swap(nums, start, i);
                }
            }
        }
    }
    

    94. Binary Tree Inorder Traversal

    Tags: Tree

    C++

    /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     * };
     */
    class Solution {
    public:
        vector<int> inorderTraversal(TreeNode* root) {
            // return inorderTraversalIterative(root);    
            return inorderTraversalMorris(root);
        }
    
    private:
        vector<int> inorderTraversalMorris(TreeNode* root) {
            vector<int> ret;
            if (root == nullptr) {
                return ret;
            }
            auto cur = root;
            while (cur != nullptr) {
                if (cur->left == nullptr) {
                    ret.push_back(cur->val);
                    cur = cur->right;
                } else {
                    auto pre = cur->left;
                    while (pre->right != nullptr && pre->right != cur) {
                        pre = pre->right;
                    }
                    if (pre->right == nullptr) {
                        pre->right = cur;
                        cur = cur->left;
                    } else {
                        ret.push_back(cur->val); // move to if would make this preorderTraversal
                        pre->right = nullptr;
                        cur = cur->right;
                    }
                }
            }
            return ret;
        }
        
        vector<int> inorderTraversalIterative(const TreeNode* root) {
            vector<int> ret;
            if (root == nullptr) {
                return ret;
            }
            stack<const TreeNode*> stc;
            auto ptr = root;
            while (ptr != nullptr || !stc.empty()) {
                if (ptr == nullptr) {
                    ptr = stc.top();
                    stc.pop();
                    ret.push_back(ptr->val);
                    ptr = ptr->right;
                } else {
                    stc.push(ptr);
                    ptr = ptr->left;
                }
            }
            return ret;
        }
    
    };
    

    Java

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    class Solution {
        public List<Integer> inorderTraversal(TreeNode root) {
            List<Integer> ret = new ArrayList<>();
            if (root == null) {
                return ret;
            }
            TreeNode cursor = root;
            Stack<TreeNode> stc = new Stack<>();
            while (cursor != null || !stc.empty()) {
                if (cursor == null) {
                    cursor = stc.peek();
                    stc.pop();
                    ret.add(cursor.val);
                    cursor = cursor.right;
                } else {
                    stc.push(cursor);
                    cursor = cursor.left;
                }
            }
            return ret;
        }
    }
    

    103. Binary Tree Zigzag Level Order Traversal

    Tags: Tree, BFS

    C++

    class Solution {
    public:
        vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
            vector<vector<int>> ret;
            if (root == nullptr) {
                return ret;
            }
            vector<TreeNode*> curLevel{root};
            bool flag = false;
            while (!curLevel.empty()) {
                vector<TreeNode*> nextLevel;
                vector<int> cur;
                cur.reserve(curLevel.size());
                if (flag) {
                    for (auto itr = curLevel.rbegin(); itr != curLevel.rend(); ++itr) {
                        cur.push_back((*itr)->val);
                    }
                } else {
                    for (auto itr = curLevel.begin();itr != curLevel.end(); ++itr) {
                        cur.push_back((*itr)->val);
                    }
                }
                for (auto node : curLevel) {
                    if (node->left != nullptr) {
                        nextLevel.push_back(node->left);
                    }
                    if (node->right != nullptr) {
                        nextLevel.push_back(node->right);
                    }
                }
                flag = !flag;
                std::swap(curLevel, nextLevel);
                ret.push_back(std::move(cur));
            }
            return ret;
        }
    };
    

    Java

    class Solution {
        public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
            List<List<Integer>> ret = new ArrayList<>();
            if (root == null) {
                return ret;
            }
            List<TreeNode> curLevel = new ArrayList<>();
            boolean flag = false;
            curLevel.add(root);
            while (!curLevel.isEmpty()) {
                List<TreeNode> nextLevel = new ArrayList<>();
                List<Integer> cur = new ArrayList<>();
                if (flag) {
                    for (int i = curLevel.size() - 1; i >= 0; --i) {
                        cur.add(curLevel.get(i).val);
                    }
                } else {
                    for (TreeNode n : curLevel) {
                        cur.add(n.val);
                    }
                }
                for (TreeNode node : curLevel) {
                    if (node.left != null) {
                        nextLevel.add(node.left);
                    }
                    if (node.right != null) {
                        nextLevel.add(node.right);
                    }
                }
                ret.add(new ArrayList<>(cur));
                flag = !flag;
                curLevel = nextLevel;
                nextLevel = null;
            }
            return ret;
        }
    }
    

    112. Path Sum

    Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum.
    For example:
    Given the below binary tree and sum = 22,
    5
    /
    4 8
    / /
    11 13 4
    / \
    7 2 1
    return true, as there exist a root-to-leaf path 5->4->11->2 which sum is 22.

    Tags: Tree, Backtracking

    C++

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

    Java

    class Solution {
        public boolean hasPathSum(TreeNode root, int sum) {
            if (root == null) {
                return false;
            }
            if (isLeaf(root)) {
                return sum == root.val;
            } else {
                return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val);
            }
        }
        
        private boolean isLeaf(TreeNode node) {
            return node.left == null && node.right == null;
        }
    }
    

    113. Path Sum II

    Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum.
    For example:
    Given the below binary tree and sum = 22,
    5
    /
    4 8
    / /
    11 13 4
    / \ /
    7 2 5 1
    return
    [
    [5,4,11,2],
    [5,8,4,5]
    ]

    Tags: Tree, Backtracking

    C++

    class Solution {
    public:
        vector<vector<int>> pathSum(TreeNode* root, int sum) {
            vector<vector<int>> ret;
            vector<int> path;
            pathSum(root, sum ,ret, path);
            return ret;
        }
        
    private:
        void pathSum(const TreeNode* root, int sum, vector<vector<int>>& ret, vector<int>& path) {
            if (root == nullptr) {
                return;
            }
            path.push_back(root->val);
            sum -= root->val;
            if (isLeaf(root) && sum == 0) {
                ret.push_back(path);
            } else {
                pathSum(root->left, sum, ret, path);
                pathSum(root->right, sum, ret, path);
            }
            path.pop_back();
        }
        
        inline bool isLeaf(const TreeNode* root) {
            return root != nullptr && root->left == nullptr && root->right == nullptr;
        }
    };
    

    Java

    class Solution {
        public List<List<Integer>> pathSum(TreeNode root, int sum) {
            List<List<Integer>> ret = new LinkedList<>();
            LinkedList<Integer> cur = new LinkedList<>();
            pathSum(ret, cur, root, sum);
            return ret;
        }
        
        private void pathSum(List<List<Integer>> ret, LinkedList<Integer> cur, TreeNode root, int sum) {
            if (root == null) {
                return;
            }
            sum -= root.val;
            cur.add(root.val);
            if (isLeaf(root) && sum == 0) {
                ret.add(new LinkedList<>(cur));
            } else {
                pathSum(ret, cur, root.left, sum);
                pathSum(ret, cur, root.right, sum);
            }
            cur.removeLast();
        }
        
        private boolean isLeaf(TreeNode root) {
            return root != null && root.left == null && root.right == null;
        }
            
    }
    

    121. Best Time to Buy and Sell Stock

    Say you have an array for which the ith element is the price of a given stock on day i.
    If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.

    Tags: Dynamic Programming

    C++

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

    Java

    class Solution {
        public int maxProfit(int[] prices) {
            if (prices.length <= 0) {
                return 0;
            }
            int ret = 0;
            int curMin = prices[0];
            for (int i = 1; i < prices.length; ++i) {
                ret = Math.max(ret, prices[i] - curMin);
                curMin = Math.min(prices[i], curMin);
            }
            return ret;
        }
    }
    

    122. Best Time to Buy and Sell Stock II

    Say you have an array for which the ith element is the price of a given stock on day i.
    Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times). However, you may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

    Tags: Greedy

    C++

    class Solution {
    public:
        int maxProfit(vector<int>& prices) {
            int ret = 0;
            for (size_t i = 1; i < prices.size(); ++i) {
                auto tmp = prices[i] - prices[i - 1];
                ret += (tmp > 0 ? tmp : 0);
            }
            return ret;
        }
    };
    

    Java

    class Solution {
        public int maxProfit(int[] prices) {
            if (prices.length <= 0) {
                return 0;
            }
            int ret = 0;
            for (int i = 1; i < prices.length; ++i) {
                ret += Math.max(prices[i] - prices[i - 1], 0);
            }
            return ret;
        }
    }
    

    144. Binary Tree Preorder Traversal

    Tags: Tree

    C++

    /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     * };
     */
    class Solution {
    public:
        vector<int> preorderTraversal(TreeNode* root) {
            //return preorderTraversalIterative(root);
            return preorderTraversalMorris(root);
        }
    
    private:
        vector<int> preorderTraversalMorris(TreeNode* root) {
            vector<int> ret;
            if (root == nullptr) {
                return ret;
            }
            // swap left and right and ret make it postorderTraversal
            auto cur = root;
            while (cur != nullptr) {
                if (cur->left == nullptr) {
                    ret.push_back(cur->val);
                    cur = cur->right;
                } else {
                    auto pre = cur->left;
                    while (pre->right != nullptr && pre->right != cur) {
                        pre = pre->right;
                    }
                    if (pre->right == nullptr) {
                        ret.push_back(cur->val); // move it to else make this inorderTraversa;
                        pre->right = cur;
                        cur = cur->left;
                    } else {
                        pre->right = nullptr;
                        cur = cur->right;
                    }
                }
            }
            return ret;
        }
        
        vector<int> preorderTraversalIterative(const TreeNode* root) {
            vector<int> ret;
            if (root == nullptr) {
                return ret;
            }
            stack<const TreeNode*> stc;
            auto ptr = root;
            while (ptr != nullptr || !stc.empty()) {
                if (ptr == nullptr) {
                    ptr = stc.top();
                    stc.pop();
                } 
                ret.push_back(ptr->val);
                if (ptr->right != nullptr) {
                    stc.push(ptr->right);
                }
                ptr = ptr->left;
            }
            return ret;
        }
    
    };
    

    Java

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    class Solution {
        public List<Integer> preorderTraversal(TreeNode root) {
            List<Integer> ret = new ArrayList<>();
            if (root == null) {
                return ret;
            }
            TreeNode cursor = root;
            Stack<TreeNode> stc = new Stack<>();
            while (cursor != null || !stc.empty()) {
                if (cursor == null) {
                    cursor = stc.peek();
                    stc.pop();
                }
                ret.add(cursor.val);
                if (cursor.right != null) {
                    stc.push(cursor.right);
                }
                cursor = cursor.left;
            }
            return ret;
        }
    }
    

    145. Binary Tree Postorder Traversal

    Tags: Tree

    C++

    /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     * };
     */
    class Solution {
    public:
        vector<int> postorderTraversal(TreeNode* root) {
            //return postorderTraversalIterative(root);
            return postorderTraversalMorris(root);
        }
    
    private:
        vector<int> postorderTraversalMorris(TreeNode* root) {
            vector<int> ret;
            if (root == nullptr) {
                return ret;
            }
            // swap preorder's left and right and reverse ret makes this postorderTraversal
            auto cur = root;
            while (cur != nullptr) {
                if (cur->right == nullptr) {
                    ret.push_back(cur->val);
                    cur = cur->left;
                } else {
                    auto pre = cur->right;
                    while (pre->left != nullptr && pre->left != cur) {
                        pre = pre->left;
                    }
                    if (pre->left == nullptr) {
                        ret.push_back(cur->val);
                        pre->left = cur;
                        cur = cur->right;
                    } else {
                        pre->left = nullptr;
                        cur = cur->left;
                    }
                }
            }
            reverse(ret.begin(), ret.end());
            return ret;
        }
    
        vector<int> postorderTraversalIterative(const TreeNode* root) {
            vector<int> ret;
            if (root == nullptr) {
                return ret;
            }
            // swap preorder's left and right and reverse ret makes this postorderTraversal
            stack<const TreeNode*> stc;
            auto ptr = root;
            while (ptr != nullptr || !stc.empty()) {
                if (ptr == nullptr) {
                    ptr = stc.top();
                    stc.pop();
                }
                ret.push_back(ptr->val);
                if (ptr->left != nullptr) {
                    stc.push(ptr->left);
                }
                ptr = ptr->right;
            }
            reverse(ret.begin(), ret.end());
            return ret;
        }
    
    };
    

    Java

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    class Solution {
        public List<Integer> postorderTraversal(TreeNode root) {
            List<Integer> ret = new ArrayList<>();
            if (root == null) {
                return ret;
            }
            // swap preorder's left and right and reverse ret makes this postorderTraversal
            TreeNode cursor = root;
            Stack<TreeNode> stc = new Stack<>();
            while (cursor != null || !stc.empty()) {
                if (cursor == null) {
                    cursor = stc.peek();
                    stc.pop();
                }
                ret.add(cursor.val);
                if (cursor.left != null) {
                    stc.push(cursor.left);
                }
                cursor = cursor.right;
            }
            Collections.reverse(ret);
            return ret;
        }
    }
    

    173. Binary Search Tree Iterator

    mplement an iterator over a binary search tree (BST). Your iterator will be initialized with the root node of a BST.
    Calling next() will return the next smallest number in the BST.
    Note: next() and hasNext() should run in average O(1) time and uses O(h) memory, where h is the height of the tree.

    Tags: Tree

    C++

    /**
     * Definition for binary tree
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     * };
     */
    class BSTIterator {
    public:
        BSTIterator(TreeNode *root) {
            for ( ; root != nullptr; root = root->left) {
                stc.push(root);
            }
        }
    
        /** @return whether we have a next smallest number */
        bool hasNext() {
            return !stc.empty();
        }
    
        /** @return the next smallest number */
        int next() {
            auto ret = stc.top()->val;
            auto ptr = stc.top()->right;
            stc.pop();
            for ( ; ptr != nullptr; ptr = ptr->left) {
                stc.push(ptr);
            }
            return ret;
        }
    
    private:
        stack<TreeNode*> stc;
    };
    
    

    Java

    /**
     * Definition for binary tree
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    
    public class BSTIterator {
    
        public BSTIterator(TreeNode root) {
            for ( ; root != null; root = root.left) {
                stc.push(root);
            }
        }
    
        /** @return whether we have a next smallest number */
        public boolean hasNext() {
            return !stc.empty();
        }
    
        /** @return the next smallest number */
        public int next() {
            int ret = stc.peek().val;
            TreeNode cursor = stc.peek().right;
            stc.pop();
            for ( ; cursor != null; cursor = cursor.left) {
                stc.push(cursor);
            }
            return ret;
        }
        
        private Stack<TreeNode> stc = new Stack<>();
    }
    

    236. Lowest Common Ancestor of a Binary Tree

    Tags: Tree

    C++

    class Solution {
    public:
        TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
            if (root == nullptr || root == p || root == q) {
                return root;
            }
            // find lca node or at least one of (p, q) in left and right subtree
            auto left = lowestCommonAncestor(root->left, p, q);
            auto right = lowestCommonAncestor(root->right, p, q);
            
            // if both left and right are not null (p, q) must exist in left and right that root 
            // is the lca; if left or right is null, lca is in another subtree (right or left). 
            if (left == nullptr) {
                return right;
            } else if (right == nullptr) {
                return left;
            } else {
                return root;
            }
        }
    };
    

    Java

    class Solution {
        public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
            if (root == null || root == p || root == q) {
                return root;
            }
            // find lca node or at least one of (p, q) in left and right subtree
            TreeNode left = lowestCommonAncestor(root.left, p, q);
            TreeNode right = lowestCommonAncestor(root.right, p, q);
            
            // if both left and right are not null (p, q) must exist in left and right that root 
            // is the lca; if left or right is null, lca is in another subtree (right or left). 
            if (left == null) {
                return right;
            } else if (right == null) {
                return left;
            } else {
                return root;
            }
        }
    }
    

    相关文章

      网友评论

        本文标题:LeetCode using C++ and Java (kee

        本文链接:https://www.haomeiwen.com/subject/yexngxtx.html