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