第一道
題目名稱: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)。