刚开始刷力扣,刷了几天发现刷完过两天就忘记了。索性就用写博客的方式记录一下,方便日后复盘回溯。
题目链接: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;
    }
};