LeetCode with C++ and Java and little Scala (持续更新)

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.

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.

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)).

Example 1: nums1 = [1, 3] nums2 = [2] The median is 2.0

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.

Example: Input: “babad” Output: “bab” Note: “aba” is also a valid answer.

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.

**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.

The matching should cover the entire input string (not partial).
The function prototype should be:
bool isMatch(const char *s, const char *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.

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;
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值