马上要面试了,把前些天在LeetCode上刷的题再看一遍。
写上注释,算复习了,也方便以后复习。
带 * 号的为忘记怎么做的。
1. 5. 最长回文子串(动态规划)
class Solution {
public:
string longestPalindrome(string s) {
int len = s.length();
int dp[1005][1005];
// 记录最长回文串的开始位置及长度
int index = 0, max = 1;
for (int i = 0; i < len; i++) {
for (int j = i; j < len; j++) {
// 初始认为[i,j]不是回文串
dp[i][j] = 0;
// 单个字符一定是回文串
if (i == j) dp[i][j] = 1;
// 两个字符组成的串是不是回文串取决于这两个字符是否相等
if (j == i + 1) {
dp[i][j] = (s[i] == s[j]);
// 这里一定要更新,否则会出错
if (dp[i][j]) {
index = i;
max = 2;
}
}
}
}
// 最外层循环为长度才可满足最优子结构
for (int l = 3; l <= len; l++) {
for (int i = 0; i < len - l + 1; i++) {
int j = i + l - 1;
// i为串的起点,j为串的终点
dp[i][j] = (dp[i+1][j-1] && (s[i] == s[j]));
if (dp[i][j]) {
max = l;
index = i;
}
}
}
// 注意用法
return s.substr(index, max);
}
};
2. 11. 盛最多水的容器(对撞指针)
class Solution {
public:
int maxArea(vector<int>& height) {
int max = -1;
int n = height.size();
int start = 0, end = n - 1;
// start和end分别指向左右两个板子,因为必须有两个板子,所以结束条件为start < end
while (start < end) {
int temp;
// 将高的向中间移,不可能让面积增大,所以下面两种情况分别是让end--和start++
if (height[start] > height[end]) {
temp = height[end] * (end - start);
end --;
}
else {
temp = height[start] * (end - start);
start ++;
}
if (max < temp) max = temp;
}
return max;
}
};
3*. 31. 下一个排列(脑门题)
class Solution {
public:
void nextPermutation(vector<int>& nums) {
int n = nums.size();
int flag = 1;
int i;
// 从后向前,找到第一对相邻的两个数,满足后面的数大于前面的数
// 因为对于一个本身递增的序列没有办法再找到比它更大的了
for (i = n - 1; i > 0; i--) {
if (nums[i] > nums[i-1]) {
flag = 0;
break;
}
}
// 如果没找到,什么也不做
if (flag) {
}
// 如果找到了,i指向两数中靠后的,例如右方例子中,i指向6: 1 2 6 5 4 2 2 2 1 1
else {
// [i...n-1](自右向左是递增的)中找到第一个比i-1位置处值大的,交换
// 这样才有可能变得更大,变化后为 -> 1 4 6 5 2 2 2 2 1 1
for (int j = n - 1; j >= i; j--) {
if (nums[j] > nums[i-1]) {
swap(nums[j], nums[i-1]);
break;
}
}
}
// 对[i...n-1]范围做个镜像 -> 1 4 1 1 2 2 2 2 5 6
// 这个循环如果没找到后数大于前数的,i为0,也满足
for (int j = 0; j < (n - i) / 2; j++) {
swap(nums[j+i], nums[n-j-1]);
}
}
};
4. 3. 无重复字符的最长子串(哈希表+滑动窗口)
class Solution {
public:
int lengthOfLongestSubstring(string s) {
// 因为键有限,所以用一个数组模拟哈希表,存的是最后一次出现的位置
int hash[256];
for (int i = 0; i < 256; i++) hash[i] = -1;
int n = s.length();
// 滑动窗口的边界
int left = 0, right = 0;
int m = -1;
// 窗口每次无论如何都向右扩展,不行再缩小左边界
while (right < n) {
// 当前窗口中没有当前纳入的字符的情况,尝试更新最值
if (hash[s[right]] == -1 || hash[s[right]] < left) {
m = max(m, right - left + 1);
}
// 当前窗口中有当前纳入字符,缩小左边界
else {
left = hash[s[right]] + 1;
// 这种情况不用更新最值,因为不可能有最值产生,因为右侧扩展1,左侧至少缩小1
}
// 更新字符位置
hash[s[right]] = right;
right ++;
}
return m == -1 ? 0 : m;
}
};
5. 75. 颜色分类(对撞指针)
class Solution {
public:
void sortColors(vector<int>& nums) {
int n = nums.size();
int left = 0;
int right = n - 1;
// 遍历一遍数组
for (int i = 0; i <= right; i++) {
// 为0则换到左边,left处的值一定是1,不用i--
if (nums[i] == 0) {
swap(nums[left], nums[i]);
left ++;
}
// 为2则换到右边,下次还要再检测i处的值,所以再i--
else if (nums[i] == 2){
swap(nums[right], nums[i]);
right --;
i --;
}
}
}
};