数据结构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;
}
};
