刚开始刷力扣,刷了几天发现刷完过两天就忘记了。索性就用写博客的方式记录一下,方便日后复盘回溯。
题目链接:https://leetcode.cn/problems/fruit-into-baskets/description/?envType=problem-list-v2&envId=fdmaj8E9
这道题依旧是使用双指针的思路来完成,首先有一个指针必定进行遍历,探索新元素是否符合篮子1和篮子2元素的指针,这里给遍历指针设置为j。
另一个指针也就是左边界,也就是滑动窗口的左界限,同时代表第一个篮子,这里设置为f1。
在遍历过程中我们要思考每个篮子的位置变化,比如说第一个篮子的下一个位置的元素必定等于第二个篮子的元素(注意这里并不是直接等于第二个篮子的位置,而是要判断第二个篮子最后一个元素的位置) 。例如[1,2,1,1,2,3,3,4] 当第二个篮子在3时,第一个篮子应在fruits[5]而非fruits[1].如果单纯的第一个篮子位置等于第二个篮子位置就会出现错误。
这就提示在遍历中我们要把最后一个符合篮子2元素的位置设置成 篮子1下个位置,也就是f1_next。
整体思路就是 :{
遍历整个数组{
if(fruits[f1] != fruits[j])&&(frutis[f2] != fruits[j]){
f1 = f1_next 同时 f2 = j; //这就是篮子更替的过程
}
随时判断第二个篮子最后一个元素的位置,用来作为f1_next,
这里暴力判断,只要符合第二个篮子的元素就等于f1_next,所以第二个篮子的最后
一个元素必定等于f1_next
if(fruits[j] == fruits[f2]) f1_next = j;
最后计算length = j - f1 + 1;
总体代码:
class Solution {
public:
int totalFruit(vector<int>& fruits) {
if(fruits.size() < 3) return fruits.size();
int result = 0;
//f1滑动窗口左(第一种水果起始) j为遍历(右边界)
//f2第二种水果起始 t为未来的两个篮子起始索引
for(int j=0,f1=0,f2=0,t=0;j<fruits.size();j++){
if(fruits[j]!=fruits[f1]&&fruits[j]!=fruits[f2]){
if(f1!=f2) {f1=t;}
f2=j; //第二个篮子
}
if(fruits[t]!=fruits[j]) t = j; //t始终为篮子的位置
result = (result>(j-f1+1))?result:(j-f1+1);
}
return result;
}
};
移除链表元素 题目链接:https://leetcode.cn/problems/remove-linked-list-elements/description/?envType=problem-list-v2&envId=fdmaj8E9
这道题相对来说比上一题好想,但是依旧废了半天劲。
题目中说让我们删除链表元素等于val的值,首先想到的就是遍历整个链表,双指针一个指针p指在被删除的元素上,另一个指针q在被删除元素的前一个位置。
但是我的思路是在设置一个指针,newlocate, 代表p的下一个位置。
同时我们要考虑特殊情况,也就是头结点 和尾结点删除的情况,为了方便头结点删除我们设置一个虚拟头结点dummyhead
struct ListNode* dummyhead = new ListNode(0);
dummyhead->next = head;
然后把newlocate放在head上,在开始遍历的时候直接就可以p = newlocate了,最后返回一个dummyhead->next.注意这里不是head,也不是dummyhead。因为可能出现第一个元素被删除,或者整个链表都被删除的情况。
全部的代码如下:
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
if(head == nullptr){return head;}
struct ListNode* dummyhead = new ListNode(0);
dummyhead->next = head;
struct ListNode* q= dummyhead;
struct ListNode* newlocate = head;
while(newlocate != nullptr){
struct ListNode* p = newlocate;
newlocate = newlocate->next;
if(p->val == val){
q->next = p->next;
}
else{
q = p;
}
}
return dummyhead->next;
}
};
还有一道删除链表的倒数第N个结点,这道题是看了答案后采写出来的,上课时候憋了一个多小时也没写出来。具体链接如下:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/
这道题的主要就是简单快捷的找到被删除的结点,我看的思路是
先设置一个遍历结点front,利用给出的n,走n个结点,然后在设置结点p= dummyhead,p和front同时走,直到front走到最后一个结点的后一个结点时结束。这时候理论上p结点刚好是我们要删除的倒数第n的前一个结点。
数学理论设总长为length,front走n,剩余长度为length-n,所以front走到最后一个结点需要的步数是length - n,所以p结点走了 length - n步,也就是正好在倒数第n个结点
然后就是把要删除的结点 p->next 设置为delete_point,p->next = delete_point->next;然后返回dummyhead->next就可以了。
具体代码如下:
*/class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
if (head == nullptr || head->next == nullptr) {
return nullptr;
}
struct ListNode* dummyhead = new ListNode(0);
dummyhead->next = head;
struct ListNode* front = dummyhead;
struct ListNode* delete_point = dummyhead;
// Move front n steps ahead
for (int i = 0; i <= n; i++) {
front = front->next;
}
// Move both pointers until front reaches the end
while (front != nullptr) {
front = front->next;
delete_point = delete_point->next;
}
// Delete the nth node from the end
struct ListNode* node_to_delete = delete_point->next;
delete_point->next = node_to_delete->next;
delete node_to_delete;
return dummyhead->next;
}
};