leetcode hot 100 刷题记录

题目300:最长递增子序列(NO)

  • 解题思路:动态规划,就是dp[i]的运用,这里dp[i]表示第i个元素为结尾的最长子序列。

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的
子序列。

class Solution 
{
public:
    int lengthOfLIS(vector<int>& nums) 
    {
        int n = nums.size();
        if (n == 0) 
        {
            return 0;
        }
        vector<int> dp(n, 0);
        int max_count=0;
        for (int i = 0; i < n; ++i) 
        {
            dp[i] = 1;//如果前面没有比他小的了,那自己本身就是一个最长子序列
            for (int j = 0; j < i; ++j) 
            {
                if (nums[j] < nums[i]) 
                {
                    //这里是每次扫描前面就记录最大的dp[i]
                    dp[i] = max(dp[i], dp[j] + 1);
                }
            }

            if(dp[i]>max_count)
            {
                max_count=dp[i];
            }        
        }
        return max_count;
    }
};

题目215:数组中的第k个最大元素(NO)

  • 解题思路:使用快速排序算法

给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。

请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。

class Solution {
public:

    void quickSort(std::vector<int>& arr, int left, int right) 
    {
        if (left >= right) 
        {
            return;
        }

        int pivot = arr[(left + right) / 2];
        int i = left, j = right;

        //这次一扫描,就会将整个数组划分为两个区域,以pivot为分界线
        while (i <= j) 
        {
            while (arr[i] < pivot) 
            {
                //找到比中间结点大的
                i++;
            }
            while (arr[j] > pivot) 
            {
                //找到比中间结点小的
                j--;
            }
            if (i <= j) 
            {
                //交换两个元素
                swap(arr[i], arr[j]);
                i++;
                j--;
            }
        }

        //检查左边
        if (left < j) 
        {
            quickSort(arr, left, j);
        }

        //检查右边
        if (i < right) 
        {
            quickSort(arr, i, right);
        }
    }
    int findKthLargest(vector<int>& nums, int k) {
        int len=nums.size();
        quickSort(nums,0,len-1);
        return nums[len-k];
    }
};

题目1:两数之和(YES)

  • 解题思路:使用哈希表

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        //使用哈希表
        unordered_map<int,int>map;

        for(int i=0;i<nums.size();i++)
        {
            if(map.find(target-nums[i])!=map.end())
            {
                return {i,map[target-nums[i]]};
            }
            map[nums[i]]=i;
            
        }
        return {};
    }
};

题目3:无重复字符的最长子串(NO)

  • 解题思路:使用滑动窗口,就是和unordered_set搭配使用,用set来检查是否重复,没有重复在继续添加,如果重复了就删除掉第一个,因为是for一次遍历,所以每个i都可以成为第一个子串。

给定一个字符串 s ,请你找出其中不含有重复字符的 最长
子串的长度。

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        //使用滑动窗口的方法,就是配合unordered_set来实现
        //用set来判断是否出现了重复的字符,如果重复了就删除第一个,否则没重复的话
        //就继续在set中添加字符

        unordered_set<char>set;
        int ans=0;
        int temp=-1;
        int len=s.size();

        for(int i=0;i<s.size();i++)
        {
            //第一个字符是不用删除的
            if(i!=0)
            {
                //删除第一个元素
                set.erase(s[i-1]);
            }

            //以i为起点一直添加元素
            //确保下一个位置合法才能够加入
            while(temp+1<len&&!set.count(s[temp+1]))
            {
                set.insert(s[temp+1]);
                temp++;
            }

            //说明遇到了重复的字符,保存这次的子串长度
            ans=max(ans,temp-i+1);
        }

        return ans;
    }
};

题目11:盛最多水的容器(YES)

  • 解题思路:最刚开始第一想到的是使用双重for遍历一遍,让每个i都作为第一条边,每个的最大的面积,但是显然这样时间复杂度太高了。

  • 错误示例

class Solution {
public:
    int maxArea(vector<int>& height) {
        //我现在突然想到的是使用双重for遍历,每个i都可以当容器的第一个位置
        //然后找到其中最大的

        int max_ans=0;
        for(int i=0;i<height.size();i++)
        {
            for(int j=i+1;j<height.size();j++)
            {
                int area=(j-i)*min(height[i],height[j]);
                max_ans=max(area,max_ans);
            }
        }

        return max_ans;
    }
};

  • 后面我又想到了一个思路,既然是要计算面积,底乘以高,当然是保证底部越长越好,所以在大的情况从两边开始扫描一定不会漏掉。且在靠齐的时候,当然是向边长高的靠齐最好。

  • 正确写法

class Solution {
public:
    int maxArea(vector<int>& height) {
        //此时我又想到了面积的算法是底乘以高,所以底应该尽可能的长,所以直接从两边开始扫描
        //就行了
        int left=0;
        int right=height.size()-1;
        
        int max_area=0;
        while(left<right)
        {
            //从两边开始记录最大面积
            int temp=(right-left)*min(height[right],height[left]);
            if(temp>max_area)
            {
                max_area=temp;
            }

            if(height[left]<height[right])
            {
                //想要面积最大,应该向高的一边靠齐
                left++;
            }else
            {
                right--;
            }
        }

        return max_area;

    }
};

题目70:爬楼梯(YES)

  • 典型的动态规划问题,考察队dp[i]数组的使用,这里dp[i]表示的是到达第i阶楼梯的方法数。这里需要关注的点是第3阶的方法数是第1阶和第2阶方法数的和。

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

class Solution {
public:
    int climbStairs(int n) {
        //这题使用的是动态规划问题
        //dp[i]的含义是到第i阶有多少不同的方法
        vector<int>dp(n+1);
        dp[0]=1;//单纯为了做题而设置的,没意义
        dp[1]=1;

        if(n<2)
        {
            return dp[n];
        }

        for(int i=2;i<=n;i++)
        {
            dp[i]=dp[i-1]+dp[i-2];
        }

        return dp[n];
    }
};

题目146:LRU缓存(NO)

  • 解题思路:使用了双链表和哈希表的结合,这题值得关注。

请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。
实现 LRUCache 类:
LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存
int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。
函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。

//双向链表
struct DLinkedNode {
    int key, value;
    DLinkedNode* prev;
    DLinkedNode* next;
    DLinkedNode(): key(0), value(0), prev(nullptr), next(nullptr) {}
    DLinkedNode(int _key, int _value): key(_key), value(_value), prev(nullptr), next(nullptr) {}
};

class LRUCache {
private:
    unordered_map<int, DLinkedNode*> cache;
    DLinkedNode* head;
    DLinkedNode* tail;
    int size;
    int capacity;

public:
    LRUCache(int _capacity): capacity(_capacity), size(0) {
        // 使用伪头部和伪尾部节点
        head = new DLinkedNode();
        tail = new DLinkedNode();
        head->next = tail;
        tail->prev = head;
    }
    
    int get(int key) {
        if (!cache.count(key)) {
            return -1;
        }
        // 如果 key 存在,先通过哈希表定位,再移到头部
        DLinkedNode* node = cache[key];
        moveToHead(node);
        return node->value;
    }
    
    void put(int key, int value) {
        if (!cache.count(key)) {
            // 如果 key 不存在,创建一个新的节点
            DLinkedNode* node = new DLinkedNode(key, value);
            // 添加进哈希表
            cache[key] = node;
            // 添加至双向链表的头部
            addToHead(node);
            ++size;
            if (size > capacity) {
                // 如果超出容量,删除双向链表的尾部节点
                DLinkedNode* removed = removeTail();
                // 删除哈希表中对应的项
                cache.erase(removed->key);
                // 防止内存泄漏
                delete removed;
                --size;
            }
        }
        else {
            // 如果 key 存在,先通过哈希表定位,再修改 value,并移到头部
            DLinkedNode* node = cache[key];
            node->value = value;
            moveToHead(node);
        }
    }

    void addToHead(DLinkedNode* node) {
        node->prev = head;
        node->next = head->next;
        head->next->prev = node;
        head->next = node;
    }
    
    void removeNode(DLinkedNode* node) {
        node->prev->next = node->next;
        node->next->prev = node->prev;
    }

    void moveToHead(DLinkedNode* node) {
        removeNode(node);
        addToHead(node);
    }

    DLinkedNode* removeTail() {
        DLinkedNode* node = tail->prev;
        removeNode(node);
        return node;
    }
};

题目200:岛屿数量(YES)

  • 解题思路:用双重for遍历所有的元素,第一个进来的1就是一个岛屿,然后用广度优先遍历遍历这个岛屿的1,并使用check数组设置标记为访问过了。这里可以优化的地方就是使用dx[ ]和dy[ ]来控制方向

给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。

class Solution {
public:
    int numIslands(vector<vector<char>>& grid) {
    if(grid.empty()) {
        return 0;
    }

    int row = grid.size();
    int col = grid[0].size();

    //用来标记是否访问过
    vector<vector<bool>> check(row, vector<bool>(col, false));
    int ans = 0;//记录岛屿的数量

    //用来控制方向的   上  下  右 左
    vector<int> dx = {1, -1, 0, 0};
    vector<int> dy = {0, 0, 1, -1};

    //将所有的元素都检查一遍
    for(int i = 0; i < row; i++) 
    {
        for(int j = 0; j < col; j++) 
        {
            if(grid[i][j] == '1' && check[i][j] == false) 
            {
                ans++;//能进来的就是一个岛屿
                queue<pair<int, int>> que;
                que.push({i, j});
                check[i][j] = true;

                while(!que.empty()) 
                {
                    pair<int,int> temp = que.front();
                    que.pop();

                    for(int k = 0; k < 4; k++) 
                    {
                        int x = temp.first + dx[k];
                        int y = temp.second + dy[k];
                        if(x >= 0 && x < row && y >= 0 && y < col && grid[x][y] == '1' && check[x][y] == false) 
                        {
                            que.push({x, y});
                            check[x][y] = true;
                        }
                    }
                }
            }
        }
    }
    return ans;
}
};

相关推荐

  1. 一个月速leetcodeHOT100 day08 两道DP 一道子串

    2024-07-10 13:32:04       15 阅读
  2. LeetCodehot100

    2024-07-10 13:32:04       42 阅读
  3. 一个月速leetcodeHOT100 day02

    2024-07-10 13:32:04       20 阅读
  4. 一个月速leetcodeHOT100 day 01

    2024-07-10 13:32:04       64 阅读
  5. 一个月速leetcodeHOT100 day03

    2024-07-10 13:32:04       16 阅读
  6. leetcode hot 100 记录

    2024-07-10 13:32:04       11 阅读
  7. leetcode hot 100 记录(medium)

    2024-07-10 13:32:04       6 阅读
  8. 2024.3.25力扣(1200-1400记录

    2024-07-10 13:32:04       20 阅读
  9. 2024.3.27力扣(1200-1400记录

    2024-07-10 13:32:04       26 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-10 13:32:04       4 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-10 13:32:04       5 阅读
  3. 在Django里面运行非项目文件

    2024-07-10 13:32:04       4 阅读
  4. Python语言-面向对象

    2024-07-10 13:32:04       5 阅读

热门阅读

  1. 全面解析C#:现代编程语言

    2024-07-10 13:32:04       9 阅读
  2. 【深入探索】揭秘SQL Server的多重身份验证模式

    2024-07-10 13:32:04       7 阅读
  3. 短链接day3

    2024-07-10 13:32:04       10 阅读
  4. [C++基础]C++ 10个常用案例

    2024-07-10 13:32:04       12 阅读
  5. android paddingStart paddingLeft 使用区别

    2024-07-10 13:32:04       12 阅读
  6. 【ARMv8/v9 GIC 系列 5.7 -- 中断路由与系统寄存器】

    2024-07-10 13:32:04       10 阅读
  7. python在人工智能领域中的应用

    2024-07-10 13:32:04       9 阅读
  8. 互联汽车的RF挑战和解决方案

    2024-07-10 13:32:04       9 阅读
  9. 如何在vue3中实现动态路由

    2024-07-10 13:32:04       7 阅读
  10. 使用RAGAs评估基于Milvus Cloud的RAG应用

    2024-07-10 13:32:04       11 阅读
  11. electron通信与持久化存储

    2024-07-10 13:32:04       10 阅读
  12. Electron Forge 打包更改打包后图片

    2024-07-10 13:32:04       11 阅读