作者学习算法的教材是LeetCode 101
有需要的同学直接GitHub搜索LeetCode 101即可
**
双指针问题
167. 两数之和 II - 输入有序数组(难度:简单)
- 本题过于简单,直接贴代码:
class Solution {
public:
vector<int> twoSum(vector<int>& numbers, int target) {
vector<int> back;
int start = 0;
int end = numbers.size()-1;
int sum;
while (start != end) {
sum = numbers[start]+numbers[end];
if (sum == target) {
back.push_back(start+1);
back.push_back(end+1);
break;
}
else if (sum < target) {
start++;
}
else if (sum > target) {
end--;
}
}
return back;
}
};
88.合并两个有序数组(难度:简单)
- 本题由于两个数组有序,于是可以设定两个指针分别在两个数组的末尾,再设置一个pos指针指向要复制的位置,每次将较大的数字复制到nums1的后边,然后pos指针向前移动一位;
- 若nums1数组全部复制完,则将nums2中的数字继续复制,若nums2数组全部复制完,则直接结束,因为此时nums1数组必然是有序的;
- 代码如下:
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int pos = m-- + n-- -1;
while (m >= 0 && n >= 0) {
nums1[pos--] = nums1[m] > nums2[n] ? nums1[m--] : nums2[n--];
}
while (n >= 0) {
nums1[pos--] = nums2[n--];
}
}
};
142.环形链表Ⅱ(难度:中等)
- 本题用到快慢指针(Floyd判圈法);
- 定义两个指针low和fast,首先low向前一次,fast向前两次,如果fast可以和low相遇,代表有回路,如果fast可以走完整个链表,说明没有回路;
- 当fast和low第一次相遇时,将fast重新移动到链表开头,并且每次只前进一次,当low和fast第二次相遇时,相遇点即为环路的开始点;
- 代码如下:
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *low = head , *fast = head;
do {
if (fast == NULL || fast->next == NULL) {
return NULL;
}
fast = fast->next->next;
low = low->next;
} while (fast != low);
fast = head;
while (fast != low) {
fast = fast->next;
low = low->next;
}
return fast;
}
};
76.最小覆盖子串(难度:困难)
- 本题用到快慢指针(Floyd判圈法);
- 代码如下:
633.平方数之和(难度:中等)
- 思路与167相同,注意定义变量为长整型即可;
- 代码如下:
class Solution {
public:
bool judgeSquareSum(int c) {
long long min = 0,max = sqrt(c);
while (min*min + max*max != c && max >= min) {
if (min*min + max*max > c) {
max -= 1;
}
else {
min += 1;
}
}
if (min*min + max*max == c) {
return true;
}
else {
return false;
}
}
};
680.验证回文字符串Ⅱ(难度:简单)
- 思路与167、633相似;
- 重点是递归函数中的++min以及第二个递归函数中的–min和–max,使用–min的原因是需要先计算,再代入;第二个–min的原因是前一个递归函数已经++,所以要先–;
- 代码如下:
class Solution {
public:
int flag = 0;
bool isPalindrome(string s, int min, int max) {
while (max >= min) {
if (s[min] == s[max]) {
min++;
max--;
}
else {
if (flag == 0) {
flag = 1;
if (isPalindrome(s, ++min, max) == false && isPalindrome(s, --min, --max) == false) {
return false;
}
else
return true;
}
else {
return false;
}
}
}
return true;
}
bool validPalindrome(string s) {
int min = 0, max = s.length() - 1;
if (isPalindrome(s, min, max)) {
return true;
}
return false;
}
};
524.通过删除字母匹配到字典里最长单词(难度:中等)
- 本题代码比较复杂,但是思路清晰;
- 首先用和字典一样大小的num数组,存储给定数组中每个字符串是否可通过给定字符串删除字母得到,若可以,用num数组记录给定数组中每个字符串的长度,若匹配不到,该长度为0;
- 之后通过*max_element()函数找到num数组中的最大值,然后遍历给定数组,若某字符串长度是最大值,则用max_return、dictionary_return记录该点,并用first记录第一个遍历到的最长单词,之后跳出循环;
- 接着从该点的下一点开始,继续便利给定数组,如果再次找到相同长度的单词,就用strcmp()函数进行比较,如果已记录的单词字典序大于这次找到的单词字典序,则将dictionary_return更新为这次找到的单词的下标,然后first更新为这次找到的单词,继续遍历;
- 最后判断如果num记录的最大值大于0,说明匹配到了单词,可以返回dictionary_return记录的下标,否则返回空;
- 代码如下:
class Solution {
public:
string findLongestWord(string s, vector<string>& dictionary) {
vector<int> num(dictionary.size(),0);
for (int i = 0;i < dictionary.size();i++) {
int j = 0,first = 0;
while (j < dictionary[i].length() && first < s.length()) {
if (s[first] != dictionary[i][j]) {
first++;
}
else {
first++;
j++;
num[i]++;
}
}
if (j < dictionary[i].length()) {
num[i] = 0;
}
}
int max = *max_element (num.begin() , num.end());
string first,sencend;
int i = 0,dictionary_return;
int max_return;
for (i = 0;i < dictionary.size(); i++) {
if (num[i] == max) {
max_return = i;
dictionary_return = i;
first = dictionary[i];
break;
}
}
while (i < dictionary.size()) {
if (num[i] == max) {
sencend = dictionary[i];
if (strcmp(first.c_str() , sencend.c_str()) > 0) {
dictionary_return = i;
first = dictionary[i];
}
}
i++;
}
if (num[max_return] > 0) {
return dictionary[dictionary_return];
}
return "";
}
};
340.最多包含K个不同字符的最长字串(难度:中等)
- 这题需LeetCode会员才可做,等我改天办个会员再更;