速刷算法#Day-02

有序数组的平方

方法一:暴力求解 + 排序

暴力先求平方,然后NT直接用sort这个方法首先对数组中的每个元素求平方,然后进行排序。下面是对应的C++代码:

cpp 复制代码
class Solution {
public:
    vector<int> SortedSquare(vector<int>& nums) {
       for (int i = 0; i < nums.size(); i++)
       {
           nums[i] *= nums[i];
       }
       sort(nums.begin(),nums.end());  
       return nums;

    }
};

方法二:双指针

这个方法使用双指针来对原始数组进行处理。通过双指针的方式,将平方后的数组按从大到小的顺序填充到新的结果数组中

cpp 复制代码
class Solution {
public:
    vector<int> SortedSquare(vector<int>& nums) {

        int k = nums.size() - 1;
        vector<int> result(nums.size(), 0);
        for (int i = 0, j = nums.size() - 1; i <= j;) { // 注意这里要i <= j,因为最后要处理两个元素
            if (nums[i] * nums[i] < nums[j] * nums[j])  {
                result[k--] = nums[j] * nums[j];
                j--;
            }
            else {
                result[k--] = nums[i] * nums[i];
                i++;
            }
        }
        return result;

    }
};

长度最小的子数组

方法一:暴力解法

这个方法通过两遍循环暴力地遍历子数组来寻找满足条件的最小子数组长度:

cpp 复制代码
  int minSubArrayLen(int s, vector<int>& nums) {
        int result = INT32_MAX; // 最终的结果
        int sum = 0; // 子序列的数值之和
        int subLength = 0; // 子序列的长度
        for (int i = 0; i < nums.size(); i++) { // 设置子序列起点为i
            sum = 0;
            for (int j = i; j < nums.size(); j++) { // 设置子序列终止位置为j
                sum += nums[j];
                if (sum >= s) { // 一旦发现子序列和超过了s,更新result
                    subLength = j - i + 1; // 取子序列的长度
                    result = result < subLength ? result : subLength;
                    break; // 因为我们是找符合条件最短的子序列,所以一旦符合条件就break
                }
            }
        }
        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
        return result == INT32_MAX ? 0 : result;
    }

方法二:滑动窗口

这个方法使用滑动窗口来寻找满足条件的最小子数组长度:

cpp 复制代码
class Solution {
public:
 int minSubArrayLen(int s, vector<int>& nums) {
        int result = INT_MAX;
        int sublen = 0;
        int sum = 0;
        int i=0;
         for (int j = 0; j < nums.size(); j++) {
                sum += nums[j];
                if (sum >= s) {
                    sublen = j - i + 1;
                    result = result<sublen?result:sublen;
                    sum -= nums[i++];
                }
            }

        return result == INT_MAX ? 0 : result;
    }
};

移除链表元素

方法一:分情况考虑头节点

这个方法首先考虑了头节点是否需要被移除,然后遍历链表中间和尾部,删除对应的节点:

cs 复制代码
class Solution{
public:
    ListNode* removeElements(ListNode* head, int val) {
        // 删除头部所有值为 val 的节点
        while (head != NULL && head->val == val) {
            ListNode* tmp = head;
            head = head->next;
            delete tmp;
        }
        
        // 遍历链表删除中间和尾部值为 val 的节点
        ListNode* cur = head;
        while (cur != NULL && cur->next != NULL) {
            if (cur->next->val == val) {
                ListNode* p = cur->next;
                cur->next = cur->next->next;
                delete p;
            } else {
                cur = cur->next;
            }
        }
        
        return head; // 返回处理后的链表头节点
    }
};

方法二:设置虚拟头结点

设置虚拟头结点即可将原头结点一视同仁
cpp 复制代码
class Solution{
public:
    ListNode* removeElements(ListNode* head, int val) {
        // 创建一个虚拟节点作为头节点的前驱,简化处理
        ListNode* dummy = new ListNode(0);
        dummy->next = head;

        // 使用 cur 遍历链表
        ListNode* cur = head;
        while (cur != NULL && cur->next != NULL) {
            if (cur->next->val == val) {
                ListNode* p = cur->next;
                cur->next = cur->next->next;
                delete p; // 删除节点
            } else {
                cur = cur->next;
            }
        }

        // 更新头节点并释放虚拟节点
        head = dummy->next;
        delete dummy;
        return head; // 返回处理后的链表头节点
    }
};

设计链表

加入了虚拟头结点,方便一致操作,不用特殊讨论

这个部分是关于设计链表的实现,主要包括初始化、获取节点、在链表头和尾插入节点、在指定位置插入节点、删除节点等操作。

cpp 复制代码
class MyLinkedList {
public:
    // 定义链表节点结构体
    struct LinkedNode {
        int val;
        LinkedNode* next;
        LinkedNode(int val):val(val), next(nullptr){}
    };

    // 初始化链表
    MyLinkedList() {
        _dummyHead = new LinkedNode(0); // 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点
        _size = 0;
    }

    // 获取到第index个节点数值,如果index是非法数值直接返回-1, 注意index是从0开始的,第0个节点就是头结点
    int get(int index) {
        if (index > (_size - 1) || index < 0) {
            return -1;
        }
        LinkedNode* cur = _dummyHead->next;
        while(index--){ // 如果--index 就会陷入死循环
            cur = cur->next;
        }
        return cur->val;
    }

    // 在链表最前面插入一个节点,插入完成后,新插入的节点为链表的新的头结点
    void addAtHead(int val) {
        LinkedNode* newNode = new LinkedNode(val);
        newNode->next = _dummyHead->next;
        _dummyHead->next = newNode;
        _size++;
    }

    // 在链表最后面添加一个节点
    void addAtTail(int val) {
        LinkedNode* newNode = new LinkedNode(val);
        LinkedNode* cur = _dummyHead;
        while(cur->next != nullptr){
            cur = cur->next;
        }
        cur->next = newNode;
        _size++;
    }

    // 在第index个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。
    // 如果index 等于链表的长度,则说明是新插入的节点为链表的尾结点
    // 如果index大于链表的长度,则返回空
    // 如果index小于0,则在头部插入节点
    void addAtIndex(int index, int val) {

        if(index > _size) return;
        if(index < 0) index = 0;        
        LinkedNode* newNode = new LinkedNode(val);
        LinkedNode* cur = _dummyHead;
        while(index--) {
            cur = cur->next;
        }
        newNode->next = cur->next;
        cur->next = newNode;
        _size++;
    }

    // 删除第index个节点,如果index 大于等于链表的长度,直接return,注意index是从0开始的
    void deleteAtIndex(int index) {
        if (index >= _size || index < 0) {
            return;
        }
        LinkedNode* cur = _dummyHead;
        while(index--) {
            cur = cur ->next;
        }
        LinkedNode* tmp = cur->next;
        cur->next = cur->next->next;
        delete tmp;
        //delete命令指示释放了tmp指针原本所指的那部分内存,
        //被delete后的指针tmp的值(地址)并非就是NULL,而是随机值。也就是被delete后,
        //如果不再加上一句tmp=nullptr,tmp会成为乱指的野指针
        //如果之后的程序不小心使用了tmp,会指向难以预想的内存空间
        tmp=nullptr;
        _size--;
    }

    // 打印链表
    void printLinkedList() {
        LinkedNode* cur = _dummyHead;
        while (cur->next != nullptr) {
            cout << cur->next->val << " ";
            cur = cur->next;
        }
        cout << endl;
    }
private:
    int _size;
    LinkedNode* _dummyHead;

};

整数的各位积和之差

转化为字符串,解决~

cpp 复制代码
class Solution{
    public:
      int Subaddmultiply(int num ){
            string str=to_string(num);
            int multi=1;
            int sum=0;
            for(char c:str){
                int temp=c-'0';
                sum+=temp;
                multi*=temp;
            }

            return multi-sum;
      }
};

class Solution{
    public:
      int Subaddmultiply(int num ){
            int n=num;
            int multi=1;
            int sum=0;
            while(n){
                int x=n%10;
                n/=10;
                sum+=temp;
                multi*=temp;
            }

            return multi-sum;
      }
};//老六就爱简单题

用栈实现队列

输入栈与输出栈一个进栈,一个出栈,将后进先出反向组合,变成了先进先出

cpp 复制代码
class MyQueue {

    Stack<Integer> stackIn;
    Stack<Integer> stackOut;

    /** Initialize your data structure here. */
    public MyQueue() {
        stackIn = new Stack<>(); // 负责进栈
        stackOut = new Stack<>(); // 负责出栈
    }
    
    /** Push element x to the back of queue. */
    public void push(int x) {
        stackIn.push(x);
    }
    
    /** Removes the element from in front of queue and returns that element. */
    public int pop() {    
        dumpstackIn();
        return stackOut.pop();
    }
    
    /** Get the front element. */
    public int peek() {
        dumpstackIn();
        return stackOut.peek();
    }
    
    /** Returns whether the queue is empty. */
    public boolean empty() {
        return stackIn.isEmpty() && stackOut.isEmpty();
    }

    // 如果stackOut为空,那么将stackIn中的元素全部放到stackOut中
    private void dumpstackIn(){
        if (!stackOut.isEmpty()) return; 
        while (!stackIn.isEmpty()){
                stackOut.push(stackIn.pop());
        }
    }
}
相关推荐
Dontla27 分钟前
Rust泛型系统类型推导原理(Rust类型推导、泛型类型推导、泛型推导)为什么在某些情况必须手动添加泛型特征约束?(泛型trait约束)
开发语言·算法·rust
Ttang2333 分钟前
Leetcode:118. 杨辉三角——Java数学法求解
算法·leetcode
喜欢打篮球的普通人34 分钟前
rust模式和匹配
java·算法·rust
java小吕布1 小时前
Java中的排序算法:探索与比较
java·后端·算法·排序算法
win x1 小时前
链表(Linkedlist)
数据结构·链表
杜若南星1 小时前
保研考研机试攻略(满分篇):第二章——满分之路上(1)
数据结构·c++·经验分享·笔记·考研·算法·贪心算法
路遇晚风1 小时前
力扣=Mysql-3322- 英超积分榜排名 III(中等)
mysql·算法·leetcode·职场和发展
Neophyte06081 小时前
C++算法练习-day40——617.合并二叉树
开发语言·c++·算法
木向1 小时前
leetcode104:二叉树的最大深度
算法·leetcode