Leetcode刷题笔记 1
1. Two Sum🔗
Q: Given an array of integers nums
and an integer target
, return indices
of the two numbers such that they add up to target
.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
You can return the answer in any order.
第一反应自然是暴力
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> res;
for (int i = 0; i < nums.size(); i++) {
for (int j = i + 1; j < nums.size(); j++) {
if (nums[i] + nums[j] == target) {
return {i, j};
}
}
}
return {-1, -1};
}
但这样做显然不够好,我们可以使用键值对来存储<<value, index>>对,一边遍历一边查找键值对内是否有匹配的值。具体的数据结构可以选择哈希表,因为哈希表的插入/查找都是o(1)操作,因此我们可以将总体的复杂度降至o(n)
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> res;
unordered_map<int, int> indices;
for (auto it = nums.begin(); it != nums.end(); ++it) {
if (indices.find(target - *it) != indices.end()) {
res.push_back(indices[target - *it]);
res.push_back(it - nums.begin());
break;
}
indices[*it] = it - nums.begin();
}
return res;
}
2. Add Two Numbers🔗
Q: 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 contains a single digit. Add the two numbers and return the sum as a linked list.
You may assume the two numbers do not contain any leading zero, except the number 0 itself.
这个题不算难,就是写起来有点别扭,我自己写的非常丑,贴一个别人写的吧。
ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) {
ListNode dummy(0), *p = &dummy;
int carry = 0;
while (l1 || l2 || carry) {
int sum = (l1 ? l1->val : 0) + (l2 ? l2->val : 0) + carry;
carry = sum / 10;
p->next = new ListNode(sum % 10);
p = p->next;
l1 = l1 ? l1->next : l1;
l2 = l2 ? l2->next : l2;
}
return dummy.next;
}
3. Longest Substring without Repeating Characters🔗
Q: Given a string s
, find the length of the longest substring without repeating characters.
简单的思路自然还是o(n^2)的,写起来也很简单
int lengthOfLongestSubstring(string s) {
int ans = 0;
for (int first = 0, last = 0; last < s.length(); last++) {
for (int i = last - 1; i >= first; i--) {
if (s[i] == s[last]) {
first = i + 1;
break;
}
}
ans = max(res, last - first + 1);
}
return ans;
}
但是效率堪忧,容易想到保存字母最后出现的位置,在遍历的同时即可判断当前范围内是否有重复字符,因而只需要遍历一次即可解决,时间复杂度为o(n),本题只有字母,因而使用数组就可以保存下标,如果碰到数字等范围较大的数据,则可以考虑哈希表,下面的代码是别人的实现,index
数组里实际存储的不是最后出现的位置,而是最后出现的位置+1,每次遇到重复字符时,将first设置为该重复字符最后出现的位置+1,即可使范围内不再存在重复字符。只能说这个实现实在是非常精炼。
int lengthOfLongestSubstring(string s) {
int ans = 0, index[256] = {0};
for (int first = 0, last = 0; last < s.length(); last++) {
first = max(index[s[last]], first);
ans = max(ans, last - first + 1);
index[s[last]] = last + 1; //index + 1, because index[] is init'd to all 0.
}
return ans;
}
5. Longest Palindrome Substring🔗
Q: Given a string s
, return the longest palindromic substring in s
.
给一个字符串s,返回该字符串的最长回文子字符串。同样可以笨办法解决,思路也很简单,遍历所有可能的情况。对于每一个位置,都考虑奇数/偶数长度回文字符串向两个方向搜索,直到碰到不匹配的字符或者到达字符串边缘。
string longestPalindrome(string s) {
int len = s.length(), max_len = 0, first = 0;
for (int i = 0; i < len; i++) {
//odd length
for (int j = i, k = i; j < len && k >= 0 && s[j] == s[k]; j++, k--) {
if (j - k + 1 > max_len) {
max_len = j - k + 1;
first = k;
}
}
//even length
for (int j = i + 1, k = i; j < len && k >= 0 && s[j] == s[k]; j++, k--) {
if (j - k + 1 > max_len) {
max_len = j - k + 1;
first = k;
}
}
}
return s.substr(first, max_len);
}
这个问题有个o(n)的算法Manacher's Algorithm,不过比较复杂,我就不献丑了。
6. ZigZag Conversion🔗
Q: 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 s, int numRows);
这题要求实现一个字符串转换的函数,也是写起来比较烦的类型。总之我就不献丑了,抄了一个别人的代码。
string convert(string s, int numRows) {
if (numRows == 1) return s;
vector<string> rows(numRows);
int curRow = 0, delta = -1;
for (char c : s) {
rows[curRow] += c;
(curRow == 0 || curRow == numRows - 1) && (delta = -delta);
curRow += delta;
}
string ret;
for (string row : rows) {
ret += row;
}
return ret;
}
7. Reverse Integer🔗
Q: Given a signed 32-bit integer x, return x with its digits reversed. If reversing x causes the value to go outside the signed 32-bit integer range $[-2^{31}, 2^{31} - 1]$, then return 0.
Assume the environment does not allow you to store 64-bit integers (signed or unsigned).
这是个有点意思也有点烦的题目,要求在不支持64位int的条件下实现翻转int的十进制位,如果可以使用64位整数,这个题目其实非常基础。
int reverse(int x) {
long long res = x < 0 ? -1 : 1;
long long sum = 0, tmp = labs(x);
if (x == 0) return 0;
while (tmp) {
sum *= 10;
sum += tmp % 10;
tmp /= 10;
}
if (INT_MIN <= res * sum && res * sum <= INT_MAX)
return res * sum;
return 0;
}
如果限制64位数据,则需要仔细考虑溢出的问题,举个例子,一个8bit整数127翻转会变为721,原本不会溢出翻转之后就溢出了。本身这个题目就比较烦,主要考察的是底层的int范围,这里贴一个当时抄的代码。
int reverse(int x) {
int rev = 0;
while (x != 0) {
int pop = x % 10;
x /= 10;
if (rev > INT_MAX/10 || (rev == INT_MAX / 10 && pop > 7)) return 0;
if (rev < INT_MIN/10 || (rev == INT_MIN / 10 && pop < -8)) return 0;
rev = rev * 10 + pop;
}
return rev;
}
8. String to Integer (atoi)🔗
Q: Implement the myAtoi(string s) function, which converts a string to a 32-bit signed integer (similar to C/C++'s atoi function).
The algorithm for myAtoi(string s) is as follows:
- Read in and ignore any leading whitespace.
- Check if the next character (if not already at the end of the string) is '-' or '+'. Read this character in if it is either. This determines if the final result is negative or positive respectively. Assume the result is positive if neither is present.
- Read in next the characters until the next non-digit charcter or the end of the input is reached. The rest of the string is ignored.
- Convert these digits into an integer (i.e. "123" -> 123, "0032" -> 32). If no digits were read, then the integer is 0. Change the sign as necessary (from step 2).
- If the integer is out of the 32-bit signed integer range $[-2^{31}, 2^{31} - 1]$, then clamp the integer so that it remains in the range. Specifically, integers less than $-2^{31}$ should be clamped to $-2^{31}$, and integers greater than $2^{31} - 1$ should be clamped to $2^{31} - 1$.
- Return the integer as the final result.
Note:
- Only the space character ' ' is considered a whitespace character.
- Do not ignore any characters other than the leading whitespace or the rest of the string after the digits.
这题要求实现自己的atoi函数,比较麻烦,所以也不多说了,直接贴代码吧。
int myAtoi(string str) {
int idx = 0, sign = 1, res = 0, tmp;
while (str[idx] == ' ') { idx++; }
if (str[idx] == '-' || str[idx] == '+') {
if (str[idx] == '-') {
sign = -1;
}
idx++;
}
if (!isdigit(str[idx])) { return 0; }
while (isdigit(str[idx])) {
tmp = str[idx] - '0';
if (res > INT_MAX / 10) {
return sign == 1 ? INT_MAX : INT_MIN;
}
if (res == INT_MAX / 10) {
if (sign == 1 && tmp > 6) return INT_MAX;
if (sign == -1 && tmp > 7) return INT_MIN;
}
res = res * 10 + tmp;
idx++;
}
return sign * res;
}