手把手带你刷LeetCode-------爱学习的饲养员[c++版](数据结构篇)


数据结构1.数组 Array

LeetCode485.最大连续1的个数

给定一个二进制数组, 计算其中最大连续 1 的个数。

示例:

输入:[1,1,0,1,1,1]
输出:3
解释:开头的两位和最后的三位都是连续 1 ,所以最大连续 1 的个数是 3.

class Solution {
public:
    int findMaxConsecutiveOnes(vector<int>& nums) {
        if(nums.size() == 0){
            return 0;
        }
        int count = 0,result = INT_MIN;
        for(int i = 0;i < nums.size();i++){
            if(nums[i] == 1){
                count++;
            }else{
                result = max(result,count);
                count = 0;
            }
        }
        return max(result,count);
    }
};

LeetCode283.移动零
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
示例:

输入: [0,1,0,3,12]
输出: [1,3,12,0,0]

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int index = 0;
        for(int i = 0;i < nums.size();i++){
            if(nums[i] != 0){
                nums[index] = nums[i];
                index++;
            }
        }
        for(int i = index;i < nums.size();i++){
            nums[i] = 0;
        }
    }
};

LeetCode27.移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

示例 1:

输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        if(nums.size() == 0)
            return 0;
        int l = 0, r = nums.size() - 1;
        while(l < r){
            while(l < r && nums[l] != val){
                l++;
            }
            while(l < r && nums[r] == val){
                r--;
            }
            swap(nums[l],nums[r]);
        }
        if(nums[l] == val){
            return l;
        }else{
            return l + 1;
        }
    }
};

数据结构2.链表 linked list

LeetCode203.移除链表元素
给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。
示例 1:
输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) 
    {
        ListNode *dummy = new ListNode;
        dummy -> next = head;
        ListNode *prev = dummy;
        while(head != NULL)
        {
            if(head -> val == val)
            {
                prev -> next = head -> next;
                head = head -> next;
            }
            else
            {
                prev = head;
                head = head -> next;
            }
        }
        return dummy -> next;
    }
};

LeetCode206.反转链表
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
示例 1:
在这里插入图片描述
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* dummy = new ListNode;
        dummy -> next = head;
        while(head != nullptr && head -> next != nullptr){
            ListNode* dnext = dummy -> next;
            ListNode* hnext = head -> next;
            dummy -> next = hnext;
            head -> next = hnext -> next;
            hnext -> next = dnext;
        }
        return dummy -> next;
    }
};

数据结构3.队列 Queue

LeetCode933.最近的请求次数
写一个 RecentCounter 类来计算特定时间范围内最近的请求。
请你实现 RecentCounter 类:
RecentCounter() 初始化计数器,请求数为 0 。
int ping(int t) 在时间 t 添加一个新请求,其中 t 表示以毫秒为单位的某个时间,并返回过去 3000 毫秒内发生的所有请求数(包括新请求)。确切地说,返回在 [t-3000, t] 内发生的请求数。
保证 每次对 ping 的调用都使用比之前更大的 t 值。
示例:

输入:
["RecentCounter", "ping", "ping", "ping", "ping"]
[[], [1], [100], [3001], [3002]]
输出:
[null, 1, 2, 3, 3]

解释:
RecentCounter recentCounter = new RecentCounter();
recentCounter.ping(1); // requests = [1],范围是 [-2999,1],返回 1
recentCounter.ping(100); // requests = [1, 100],范围是 [-2900,100],返回 2
recentCounter.ping(3001); // requests = [1, 100, 3001],范围是 [1,3001],返回 3
recentCounter.ping(3002); // requests = [1, 100, 3001, 3002],范围是 [2,3002],返回 3

class RecentCounter {
private:
    queue<int> q;
public:
    RecentCounter() {}
    
    int ping(int t) 
    {
        q.push(t);
        while(q.size() > 0 && t - q.front() > 3000)
        {
            q.pop();
        }
        return q.size();
    }
};

数据结构4.栈 stack

LeetCode20.有效的括号
给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。

示例 1:

输入:s = "()"
输出:true
示例 2:

输入:s = "()[]{}"
输出:true
示例 3:

输入:s = "(]"
输出:false
示例 4:

输入:s = "([)]"
输出:false
示例 5:

输入:s = "{[]}"
输出:true

class Solution {
public:
    bool isValid(string s) 
    {
        if(s.size() == 0)
            return true;
        stack<int> st;
        for(char c:s)
        {
            if(c == '(' || c == '[' || c == '{')
            { 
                st.push(c);
            }
            else
            {
                if(st.size() == 0)
                {
                    return false;
                }
                else
                {
                    int temp = st.top();
                    st.pop();
                    if(c == ')')
                    {
                        if(temp != '(')
                            return false;
                    }
                    else if(c == ']')
                    {
                        if(temp != '[')
                            return false;
                    }
                    else if(c == '}')
                    {
                        if(temp != '{')
                            return false;
                    }
                }
            }
        }
        if(st.size() == 0)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
};

LeetCode496.下一个更大的元素 I
给你两个 没有重复元素 的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。
请你找出 nums1 中每个元素在 nums2 中的下一个比其大的值。
nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出 -1 。

示例 1:
输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: [-1,3,-1]
解释:
对于 num1 中的数字 4 ,你无法在第二个数组中找到下一个更大的数字,因此输出 -1 。
对于 num1 中的数字 1 ,第二个数组中数字1右边的下一个较大数字是 3 。
对于 num1 中的数字 2 ,第二个数组中没有下一个更大的数字,因此输出 -1 。

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) 
    {
        vector<int> res;
        stack<int> st;
        for(int i = 0;i < nums2.size();i++)
        {
            st.push(nums2[i]);
        }
        for(int j = 0;j < nums1.size();j++)
        {
            stack<int> temp;
            bool isFound = false;
            int max = -1;
            while(st.size() != 0 && !isFound)
            {
                int top = st.top();
                st.pop();
                if(top > nums1[j])
                {
                    max = top;
                }
                else if(top == nums1[j])
                {
                    isFound = true;
                }
                temp.push(top);
            }
            res.push_back(max);
            while(temp.size() != 0)
            {
                st.push(temp.top());
                temp.pop();
            }
        }
        return res;
    }
};

数据结构5.哈希表 Hash Table

LeetCode217.存在重复元素
给定一个整数数组,判断是否存在重复元素。
如果存在一值在数组中出现至少两次,函数返回 true 。如果数组中每个元素都不相同,则返回 false 。

示例 1:
输入: [1,2,3,1]
输出: true

示例 2:
输入: [1,2,3,4]
输出: false

示例 3:
输入: [1,1,1,3,3,4,3,2,4,2]
输出: true

第一种利用哈希表:

class Solution {
public:
    bool containsDuplicate(vector<int>& nums) 
    {
        if(nums.size() == 0)
            return false;
        unordered_map<int,int> nhash;   //建立哈希表
        for(int i = 0;i < nums.size();i++)
        {
            if(nhash[nums[i]] == 0)     //如果从未在哈希表中出现则+1
            {
                nhash[nums[i]]++;
            }
            else                        //在哈希表出现过,证明重复直接返回true
            {
                return true;
            }
        }
        return false;
    }
};

第二种利用集合,利用了集合不能存储重复数字的特性

class Solution {
public:
    bool containsDuplicate(vector<int>& nums) 
    {
        if(nums.size() == 0)
            return  false;
        unordered_set<int> nhash;
        for(int i = 0;i < nums.size();i++)
        {
            nhash.insert(nums[i]);      //添加到集合中
        }
        if(nhash.size() == nums.size())
        {
            return false;               //长度相等,证明不存在重复,返回false
        }
        else
        {
            return true;                //长度不等,存在重复,返回true
        }
    }
};

LeetCode389.找不同
给定两个字符串 s 和 t,它们只包含小写字母。

字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母。
请找出在 t 中被添加的字母。

示例 1:
输入:s = "abcd", t = "abcde"
输出:"e"
解释:'e' 是那个被添加的字母。

示例 2:
输入:s = "", t = "y"
输出:"y"

class Solution {
public:
    char findTheDifference(string s, string t) {
        vector<int> hashtable(26,0);
        for(int i = 0;i < s.size();i++){
            hashtable[s[i] - 97]++;
        }
        for(int j = 0;j < t.size();j++){
            hashtable[t[j] - 97]--;
        }
        for(int k = 0;k < 26;k++){
            if(hashtable[k] != 0){
                return (char)(k + 'a');
            }
        }
        return ' ';
    }
};

数据结构6.集合 Set

LeetCode705.设计哈希表
不使用任何内建的哈希表库设计一个哈希集合(HashSet)。

实现 MyHashSet 类:
void add(key) 向哈希集合中插入值 key 。
bool contains(key) 返回哈希集合中是否存在这个值 key 。
void remove(key) 将给定值 key 从哈希集合中删除。如果哈希集合中没有这个值,什么也不做。

示例:
输入:
["MyHashSet", "add", "add", "contains", "contains", "add", "contains", "remove", "contains"]
[[], [1], [2], [1], [3], [2], [2], [2], [2]]
输出:
[null, null, null, true, false, null, true, null, false]

解释:
MyHashSet myHashSet = new MyHashSet();
myHashSet.add(1); // set = [1]
myHashSet.add(2); // set = [1, 2]
myHashSet.contains(1); // 返回 True
myHashSet.contains(3); // 返回 False ,(未找到)
myHashSet.add(2); // set = [1, 2]
myHashSet.contains(2); // 返回 True
myHashSet.remove(2); // set = [1]
myHashSet.contains(2); // 返回 False ,(已移除)

class MyHashSet {
public:
    vector<bool> nodes;
    /** Initialize your data structure here. */
    MyHashSet() {
        nodes.resize(1000001,false);
    }
    
    void add(int key) {
        nodes[key] = true;
    }
    
    void remove(int key) {
        nodes[key] = false;
    }
    
    /** Returns true if this set contains the specified element */
    bool contains(int key) {
        return nodes[key];
    }
};

数据结构7.树 Tree

LeetCode144.二叉树的前序遍历
给你二叉树的根节点 root ,返回它节点值的 前序 遍历。
示例 1:
在这里插入图片描述
输入:root = [1,null,2,3]
输出:[1,2,3]

class Solution {
public:
    void preorder(TreeNode* root,vector<int> &res)
    {
        if(root == nullptr)
            return;
        res.push_back(root -> val);
        preorder(root -> left,res);
        preorder(root -> right,res);
    }
    vector<int> preorderTraversal(TreeNode* root) 
    {
        vector<int> res;
        preorder(root,res);
        return res;
    }

数据结构8.堆 Heap

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

示例 1:
输入: [3,2,1,5,6,4] 和 k = 2
输出: 5

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        priority_queue<int,vector<int>,less<int>>q;
        for(int num:nums){
            q.push(num);
        }
        while(k > 1){
            q.pop();
            k--;
        }
        return q.top();
    }
};

LeetCode692.前K个高频单词
给一非空的单词列表,返回前 k 个出现次数最多的单词。
返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率,按字母顺序排序。

示例 1:
输入: ["i", "love", "leetcode", "i", "love", "coding"], k = 2
输出: ["i", "love"]
解析: "i" 和 "love" 为出现次数最多的两个单词,均为2次。
注意,按字母顺序 "i" 在 "love" 之前。

class cmp{
    public:
        bool operator()(const pair<string,int> &p1,const pair<string,int> &p2)
        {
            return p1.second == p2.second?(p1.first < p2.first):p1.second > p2.second;
        }
};
class Solution {
public:
    vector<string> topKFrequent(vector<string>& words, int k) {
        unordered_map<string,int> mapping;
        for(string word:words)
        {
            if(mapping.find(word) == mapping.end()){
                mapping.emplace(word,0);
            }
            int temp = mapping[word]++;
            mapping.emplace(word,temp);
        }
        priority_queue<pair<string,int>,vector<pair<string,int>>,cmp>minheap;
        for(auto it = mapping.begin();it != mapping.end();it++)
        {
            minheap.emplace(*it);
            if(minheap.size() > k)
            {
                minheap.pop();
            }
        }
        vector<string> result;
        while(!minheap.empty())
        {
            result.push_back(minheap.top().first);
            minheap.pop();
        }
        reverse(result.begin(),result.end());
        return result;
    }
};


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM