數據結構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;
}
};
