第10天
动态窗口 + 双指针
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int left = 0,right = 0;
int len = 0;
map<char,int> mp; //记录每个字符上一次出现的索引,最左边的索引为1
while(right < s.size())
{
if(mp.find(s[right]) != mp.end()) //如果在mp中查询到动态窗口右边的字符
{
left = max(left , mp[s[right]]); //修改当前left为重复字符上一次出现的位置
}
mp[s[right]] = right + 1; //mp的索引是下标+1
len = max(right-left + 1,len);
right++;
}
return len;
}
};
第11天
双指针,一个指向前一个结点,一个后一个
class Solution {
public:
ListNode* deleteNode(ListNode* head, int val) {
if(head->val == val) return head->next;
ListNode* pre = head , *cur = head->next;
while(cur != NULL && cur->val != val)
{
pre = cur;
cur = cur -> next;
}
if(cur != NULL) pre->next = cur->next;
return head;
}
};
双指针,中间距离为k
class Solution {
public:
ListNode* getKthFromEnd(ListNode* head, int k) {
ListNode* first = head;
ListNode* second = head;
for(int i = 0; i < k;i++)
{
first = first->next;
}
while(first != NULL)
{
second = second->next;
first = first->next;
}
return second;
}
};
第12天
迭代
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* a = new ListNode(); //创建一个新节点
ListNode* p = a; //指向新节点的指针
while(l1 && l2) //只有当两个链表都有结点
{
if(l1->val >= l2->val)
{
p -> next = l2;
l2 = l2 -> next;
}else{
p -> next = l1;
l1 = l1 -> next;
}
p = p -> next;
}
p->next = (l1? l1 :l2);
return a->next;
}
};
递归
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if(!l1)
{
return l2;
}
if(!l2)
{
return l1;
}
if(l1->val >= l2->val)
{
l2->next = mergeTwoLists(l1,l2->next);
return l2;
}
l1->next = mergeTwoLists(l1->next,l2);
return l1;
}
};
共同走过a+b+c
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *l1 = headA , *l2 = headB;
while(l1 != l2)
{
l1 = l1 ? l1 -> next : headB; //如果没有公共结点,循环完a+b后,同时为NULL
l2 = l2 ? l2 -> next : headA;
}
return l1;
}
};
第13天
方法一: 前后指针
前面的指针指向奇数,后面指向偶数
class Solution {
public:
vector<int> exchange(vector<int>& nums) {
int n = nums.size();
int i = 0, j = n-1;
while(i < j)
{
if(nums[i]%2 == 1)
{
i++;
continue;
}
if(nums[j]%2 == 0)
{
j--;
continue;
}
swap(nums[i++],nums[j--]);
}
return nums;
}
};
方法二:快慢指针
快指针指向奇数,满指针指向奇数
class Solution {
public:
vector<int> exchange(vector<int>& nums) {
int low = 0,fast = 0;
while(fast < nums.size())
{
if(nums[fast] & 1) //fast寻找奇数
{
swap(nums[low],nums[fast]);
low++; //low寻找下一个奇数应该存放的位置
}
fast++;
}
return nums;
}
};
双指针
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
int i = 0, j = nums.size() - 1;
while(i < j)
{
if(nums[i] + nums[j] > target) j--;
else if (nums[i] + nums[j] < target) i++;
else return vector<int>{nums[i],nums[j]};
}
return vector<int>{};
}
};
方法一:整段翻转
class Solution {
public:
string reverseWords(string s) {
reverse(s.begin(),s.end()); //全部翻转
int n = s.size();
int idx = 0; //
for(int i = 0;i < n;i++)
{
if(s[i] != ' ') //去除空格
{
if(idx != 0) //在每一个单词后面加空格
{
s[idx++] = ' ';
}
int j = i;
while(j < n && s[j] != ' ') //去掉其他的空格
{
s[idx++] = s[j++];
}
reverse(s.begin()+idx-(j-i) , s.begin()+idx); //翻转当前单词 当前位置 - 单词长度
i = j;
}
}
s.erase(s.begin() + idx ,s.end());
return s;
}
};
方法二:从最后一个字符开始,遇到单词则入栈,遇到空格或第一个字符都要检查一下栈中是否有单词可以弹出,若有则全部弹出并拼接,每弹出一个完整的单词就添加一个空格
class Solution {
public:
string reverseWords(string s) {
stack<char> word; //单词栈
string result = "";
for(int i =s.size()-1;i >= 0; --i)
{
if(s[i] != ' ') //遇到单词入栈
{
word.push(s[i]);
}
if(s[i] == ' '|| i ==0) //当遇到第一个空格或者第一个字符都要检查一下栈中是否有单词可以弹出
{
bool flag = false; //标记是否发生出栈
while(word.empty() == false)
{
result.push_back(word.top()); //因为word栈存储的元素为char型
//而result为string型,故不能相加,只能使用push_back()
word.pop();
flag = true;
}
if(flag) //如果发生出栈,则在单词后面加一个空格。
{
result += " ";
}
}
}
return result.substr(0 , result.size()-1); //最后一个单词后面会多一个空格
}
};