被迫重操旧业(?)
再不刷题面试就真要翻车了。。。。
好在medium题难度还比较水,幸亏它不考什么神DP或数据结构或blabla不然我还面个锤子(x)
但是现场写代码还不准出错ATP顶8住啊所以还是练练手感叭。。。。
就,按顺序随便做几个。点中等难度然后按题号排序这样。
2. 两数相加
高精度但是用单向链表。
一开始ATP写的很麻烦,基本思路是先把两个数字重叠的部分相加,然后再单独处理较长的数字多出来的那部分,然后再处理进位这样。一共三个while循环。
但是后来发现好像直接改一下判断条件,如果其中一个数字链表到头了就不要管它,这样就只用一个while就能解决。
(果然年纪大了哭哭)
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode *Answer, *now, *newnode;
int tmp, carrybit = 0;
Answer = new ListNode(0);
now = Answer;
while (l1 != NULL || l2 != NULL){
tmp = carrybit;
if (l1 != NULL) tmp += l1->val;
if (l2 != NULL) tmp += l2->val;
carrybit = tmp / 10; tmp = tmp % 10;
now->val = tmp;
if (l1 != NULL) l1 = l1->next;
if (l2 != NULL) l2 = l2->next;
if (l1 != NULL || l2 != NULL || carrybit != 0) {
newnode = new ListNode(0);
now->next = newnode; now = newnode;
}
}
if (carrybit != 0) {
now->val = carrybit;
}
return Answer;
}
};
3.无重复字符的最长子串
\(O(n^2)\)的很好想嘛就直接暴力枚举了。
但是其实显然应该还有更优的做法。。。ATP一开始想对每个字符处理它能延伸的最长区间,但是这样没法很好地处理包含的问题。。。
其实two pointers扫一遍就可以了。每次加入一个新字符的时候移动左端点即可。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int Answer = 0, len = s.size(), ext[200], L = 0;
memset(ext, -1, sizeof(ext));
for (int i = 0; i < len; i ++) {
L = max(L, ext[s[i]] + 1);
ext[s[i]] = i;
Answer = max(Answer, i - L + 1);
}
return Answer;
}
};
5. 最长回文子串
manacher板子题。。。(但是我忘了manacher怎么写所以抄的zyf2000的板子1551)
细节问题就是两个字符中间要加分隔符来处理回文中心不在字符上的情况,然后最开头的位置要放一个特殊字符这样就可以避免while循环的时候越界。
之前都是用&#@这样的字符来着但是考虑到LeetCode的尿性,它没说全是小写字母还是不用这些字符了。。于是ATP就把它很麻烦地倒腾到数组里用数字来做了。
最后那个输出结果按理说是可以算一下然后直接用string的substr函数搞的,但是ATP懒得动脑子所以就使用脑死亡做法——一个一个把字符加进去。。。
边界卡了半天。我好菜(
class Solution {
public:
string longestPalindrome(string s) {
int len = s.size(), *p, *arr, id = 1, mx = 1;
string Answer = "";
arr = new int[2 * len + 10];
p = new int[2 * len + 10];
arr[0] = -2;
for (int i = 0; i < len; i ++) {
arr[i * 2 + 1] = s[i];
arr[i * 2 + 2] = -1;
}
for (int i = 1; i < 2 * len; i ++) {
if (mx > i) p[i] = min(p[2 * id - i], mx - i);
else p[i] = 1;
while (arr[i - p[i]] == arr[i + p[i]])
++ p[i];
if (i + p[i] > mx) {
mx = i + p[i]; id = i;
}
}
mx = 0; id = 1;
for (int i = 1; i < 2 * len; i ++) {
int val = p[i];
if (arr[i - p[i]] == -1) val = p[i] - 1;
if (val > mx){mx = val; id = i;}
}
for (int i = id - mx + 1; i <= id + mx - 1; i ++)
if (arr[i] > 0) Answer.push_back((char)(arr[i]));
return Answer;
}
};
6. Z字形变换
我的做法是先算出要用几行几列的数组,然后再一个个填字(究极脑死做法
但是实际上应该可以直接构造答案字符串。只要知道现在正在读第几个Z字形的第几个字符,就可以算出它对应原字符串的哪个位置。这样应该会更快一点。。。
class Solution {
public:
string convert(string s, int numRows) {
int cycle = numRows * 2 - 2, len = s.size();
int numCols, p1, p2;
bool flag = false;
string Answer = "";
if (numRows == 1) return s;
numCols = len / cycle;
numCols *= numRows - 1;
if (len % cycle > 0) numCols += 1;
if (len % cycle > numRows) numCols += len % cycle - numRows;
char arr[numRows][numCols];
p1 = p2 = 0;
for (int i = 0; i < numRows; i ++)
for (int j = 0; j < numCols; j ++)
arr[i][j] = 0;
for (int i = 0; i < len; i ++) {
arr[p2][p1] = s[i];
if (flag == false) {
if (p2 + 1 < numRows) p2 ++;
else {p1 ++; p2 --; flag = true;}
}else {
if (p2 - 1 >= 0) {p1 ++; p2 --;}
else {p2 ++; flag = false;}
}
}
for (int i = 0; i < numRows; i ++)
for (int j = 0; j < numCols; j ++)
if (arr[i][j] > 0) Answer.push_back(arr[i][j]);
return Answer;
}
};
8. 字符串转换整数(atoi)
注意判一下开头的正负号就行了。。越界问题ATP直接用long long搞的(又是脑死做法)
class Solution {
public:
int myAtoi(string str) {
int ptr = 0;
long long Answer = 0, sign = 1;
const long long MAX = 2147483648LL;
while (str[ptr] == ' ') ptr ++;
if (str[ptr] != '+' && str[ptr] != '-' && (str[ptr] < '0' || str[ptr] > '9'))
return 0;
if (str[ptr] == '+') {sign = 1; ptr ++;}
else if (str[ptr] == '-') {sign = -1; ptr ++;}
while (str[ptr] <= '9' && str[ptr] >= '0') {
Answer = Answer * 10 + str[ptr] - '0';
ptr ++;
if (Answer > MAX) Answer = MAX;
}
Answer = Answer * sign;
if (Answer == MAX) Answer = MAX - 1;
return (int)Answer;
}
};
11. 盛水最多的容器
two pointers扫一遍即可。第一个指针在开头,第二个指针在结尾。因为如果缩短x轴长度能增大总容量就一定得排除短板,所以两个指针指向的位置哪个短就先移动哪个。
但是严格证明我不会。。。看了一下别人的题解,大致思路是说排除短板以后不会被扫到的那些解一定不可能是最优解。
class Solution {
public:
#include <algorithm>
int maxArea(vector<int>& height) {
int p1 = 0, p2 = height.size() - 1;
int Answer = 0;
while (p1 != p2) {
Answer = max(Answer, (p2 - p1) * min(height[p2], height[p1]));
if (height[p2] < height[p1]) p2 --;
else p1 ++;
}
return Answer;
}
};
12. 整数转罗马数字
这题的关键是总结出整数转罗马数字的规则(x
LeetCode上有人说实际上目标是使用的字母最少,听起来好像有道理。
规则是能用大的就用大的,包括40、90这些特殊数字。但是10,100这些数字可以连续使用多次,40,90这种的就不可以。
class Solution {
public:
string intToRoman(int num) {
string Answer = "";
int ww[13] = {1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000};
string st[13] = {"I", "IV", "V", "IX", "X", "XL", "L", "XC", "C", "CD", "D", "CM", "M"};
for (int i = 12; i >= 0; i --) {
if (i % 2 == 1){
if (num - ww[i] >= 0) {
num -= ww[i]; Answer += st[i];
}
}else {
while (num - ww[i] >= 0) {
num -= ww[i]; Answer += st[i];
}
}
}
return Answer;
}
};
原文地址:https://www.cnblogs.com/FromATP/p/12262984.html