第五週LeetCode算法題兩道

第一道

題目名稱:4. Median of Two Sorted Arrays

題目難度:Hard

題目描述:There are two sorted arrays nums1 and nums2 of size m and n respectively.

Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

Example 1:

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

Example 2:

nums1 = [1, 2]
nums2 = [3, 4]
The median is (2 + 3)/2 = 2.5

題目分析:
第一個思路是使用兩個指針和一個計數器,一個指向數組1一個指向數組2,每次移動指針1或者指針2一個單位,計數器記錄總移動步數。當計數器到達總數組的中點時,就是想要的結果。使用這種方法所需的總時間複雜度不會超過O(m+n),但是這種方法需要考慮的情況太多。所以實現起來比較麻煩。故先不做考慮。

第二種思路是將兩個數組排序合併成一個數組,然後直接在這個數組中取得中位數即可。但是排序算法最快也需要O(nlogn),無法滿足題意。觀察題目要求的複雜度O(m+n)想到了桶排序。桶排序的時間複雜度剛好是O(m+n)。所以本題使用桶排序即可。

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int max, min;
        if (nums1.size() == 0 && nums2.size() == 0) {
            return 0;
        } else if (nums1.size() == 0) {
            max = nums2[nums2.size() - 1];
            min = nums2[0];
        } else if (nums2.size() == 0) {
            max = nums1[nums1.size() - 1];
            min = nums1[0];
        } else {
            max = (nums1[nums1.size()-1] > nums2[nums2.size()-1]) ? nums1[nums1.size()-1] : nums2[nums2.size()-1];
            min = (nums1[0] < nums2[0]) ? nums1[0] : nums2[0];
        }
        int arr[max + 1];
        double result = 0;
        for (int i = min; i <= max; ++i) {
            arr[i] = 0;
        }
        for (int i = 0; i < nums1.size(); ++i) {
            arr[nums1[i]]++;
        }
        for (int i = 0; i < nums2.size(); ++i) {
            arr[nums2[i]]++;
        }
        bool odd;
        if ((nums1.size() + nums2.size()) % 2 == 1) {
            odd = true;
        } else {
            odd = false;
        }
        if (odd) {
            int count = (nums1.size() + nums2.size()) / 2 + 1;
            for (int i = min; i <= max; ++i) {
                if (count > 0) {
                    count -= arr[i];
                }
                if (count <= 0) {
                    result = i;
                    return result;
                }
            }
        } else {
            int midR = (nums1.size() + nums2.size()) / 2 + 1;
            int minL = (nums1.size() + nums2.size()) / 2;
            double result1, result2;
            bool stopL = false, stopR = false;
            for (int i = min; i <= max; ++i) {
                if (minL > 0) {
                    minL -= arr[i];
                }
                if (minL <= 0 && !stopL) {
                    result1 = i;
                    stopL = true;
                }
                if (midR > 0) {
                    midR -= arr[i];
                }
                if (midR <= 0 && !stopR) {
                    result2 = i;
                    stopR = true;
                }
                if (stopL && stopR)
                    break;
            }
            result = double(result1 + result2) / 2;
            return result;
        }
        return result;
    }
};




第二道

題目名稱:3. Longest Substring Without Repeating Characters

題目難度:Medium

題目描述:Given a string, find the length of the longest substring without repeating characters.

Examples:

Given "abcabcbb", the answer is "abc", which the length is 3.

Given"bbbbb", the answer is "b", with the length of 1.

Given"pwwkew", the answer is "wke", with the length of 3. Note that the answer must be a substring, "pwke" is a subsequence and not a substring.

題目分析:
本題有一個很直接暴力的解法,也是很容易第一個想到的解法就是直接遍歷。考慮所有可能性:

int lengthOfLongestSubstring(string s) {
    int max = 0, count = 0;
    string substr = "";
    for (int i = 0; i < s.size(); ++i) {
        for (int j = i; j < s.size(); ++j) {
            if (isNotIn(substr, s[j])) {
                count++;
                substr += s[j];
            } else {
                if (count > max) {
                    max = count;
                }
                count = 0;
                substr = "";
                break;
            }
        }
    }
    if (count > max) {
        max = count;
    }
    return max;
}

這種做法雖然很明顯能直接AC,但是效率太低(O(n^2))。於是考慮另一種解法:
準備一個哈希表,還有左右兩個指針,分別表示當前檢測的子串的上界和下界。首先移動右界,每次檢測新的字符是否在哈希表中,如果有,則檢查它是否在當前檢測的子串中,如果是,則子串從這個符號的右邊重新開始,因爲我們讓左指針表示當前檢測的子串的左邊,所以將左指針的值改變就行。如果不在子串中,說明當前子串中還沒有重複的字符,不需要改變左指針的值,繼續掃描。每次做完這個檢查之後,將當前字符插入哈希表中。哈希表的格式是hashmap[char] = int
最後代碼如下:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        if (s == "") return 0;
        int max = 0;
        std::map<char, int> m;
        int leftPointer = 0;
        for (int i = 0; i < s.size(); ++i) {
            map<char, int>::iterator it= m.find(s[i]);
            if (it != m.end()) {
                leftPointer = leftPointer > (it->second+1) ? leftPointer : (it->second+1);
            }
            m[s[i]] = i;
            max = max > (i - leftPointer + 1) ? max : (i - leftPointer + 1);
        }
        return max;
    }
};

因爲哈希表的查找是O(n)複雜度的,所以算法的效率是O(n)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章