LeetCode using C++ and Java (keep updating ...)

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;
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容

  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,723评论 0 33
  • **2014真题Directions:Read the following text. Choose the be...
    又是夜半惊坐起阅读 9,380评论 0 23
  • 2017年6月8号下午考完试高三就解放了吧 也许9号早上你会睡到10点 也许你会急急忙忙穿上校服冲到客厅问妈妈怎么...
    一手先生阅读 157评论 0 0
  • 窗外又是一阵忽如其来的大暴雨。天黑得像是深夜两三点。连日来,在立夏期间,这个南方小城,雨水来得又多又急,让人措手不...
    TRaCY_Z阅读 231评论 0 0
  • 今天听了十点读书BOBO读的一篇冰心的《我的老师》,突然很想写一写我的老师。 从幼儿园到大学遇到过很多老师,但是印...
    安尔馨阅读 338评论 0 0