第五周LeetCode算法题两道

来源:互联网 发布:网王之驯养玫瑰的知世 编辑:程序博客网 时间:2024/04/28 17:33

第一道

题目名称: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)。

原创粉丝点击