leetcode:https://leetcode-cn.com/problemset/algorithms/
类别:热题HOT100 easy篇 共26道
No.1
标签:栈 设计
155. Min Stack
class MinStack {
public:
/** initialize your data structure here. */
stack stackData;
stack stackMin;
MinStack() {
}
void push(int x) {
if(stackMin.empty() || x<=stackMin.top())
stackMin.push(x);
stackData.push(x);
}
void pop() {
if(stackData.empty())
throw new exception();
if(stackMin.top() == stackData.top())
stackMin.pop();
stackData.pop();
}
int top() {
if(stackData.empty())
throw new exception();
return stackData.top();
}
int getMin() {
return stackMin.top();
}
};
No.2
标签:栈
20. Valid Parentheses
有效的括号 – 其实就是让括号配成对儿啦
class Solution {
public:
bool isValid(string s) {
if(s=="") return true;
if(s.length()%2!=0) return false;
stack ss;
for(auto i:s){
if(i=='{' || i=='(' || i=='[')
ss.push(i);
else {
if(ss.size()==0 && (i==']' || i=='}' || i==')'))
return false;
else if((i=='}' && ss.top()!='{') || (i==']' && ss.top()!='[') ||(i==')' && ss.top()!='('))
return false;
else
ss.pop();
}
}
if(ss.size()!=0)
return false;
return true;
}
};
No.3
标签:位运算
461. Hamming Distance
思路:两个数字之间的Hamming距离是两个数字二进制表示中,数位上数字不同的个数。那么可以通过异或获取不同的位置,然后再统计二进制中1的个数。
n&(n-1)可以把该整数n最右边的1变成0。一个整数的二进制表示中有多少个这样的1,就可以进行多少次这样的操作。
class Solution {
public:
int hammingDistance(int x, int y) {
int n = x^y;
int count =0;
while(n){
count++;
n = n&(n-1);
}
return count;
}
};
No.4
标签:位运算 数组
169. Majority Element 求众数
主要元素:出现次数严格大于⌊ n/2 ⌋,即数组中出现次数超过一半
思路:摩尔投票法
从第一个数开始count=1,遇到相同的就加1,遇到不同的就减1,减到0就重新换个数开始计数,总能找到最多的那个。只需遍历一遍即可。
class Solution {
public:
int majorityElement(vector& nums) {
int candidate = nums[0], count = 1;
for (int i = 1; i < nums.size(); ++i) {
if (count == 0) {
candidate = nums[i];
count = 1;
} else if (nums[i] == candidate) {
count++;
} else{
count--;
}
}
return candidate;
}
};
No.5
标签:位运算,哈希
136. Single Number 只出现一次的数字
除了出现一词,就是出现两次。
思路:异或
class Solution {
public:
int singleNumber(vector& nums) {
int res = nums[0];
for(int i = 1; i < nums.size(); i++){
res = res ^ nums[i];
}
return res;
}
};
No.6
标签:树
538. Convert BST to Greater Tree
把二叉搜索树转换为累加树
Given a Binary Search Tree (BST), convert it to a Greater Tree such that every key of the original BST is changed to the original key plus sum of all keys greater than the original key in BST.
Input: The root of a Binary Search Tree like this:
5
/ \
2 13Output: The root of a Greater Tree like this:
18
/ \
20 13
思路:BST的中序遍历就是从小到大,那么反过来就是从大到小,然后累加就好了.
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int sum=0;
TreeNode* convertBST(TreeNode* root) {
if(root){
convertBST(root->right);
root->val = root->val + sum;
sum = root->val;
convertBST(root->left);
return root;
}
return NULL;
}
};
No.7
标签:树
543. Diameter of Binary Tree
思路:一个树中两个节点间的最长路径。主要要会求树的高度。
时间复杂度为 O(n):每个结点最多仅被遍历一次
这实际上是一种深度遍历,所以treedepth–> dfs
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int treedepth(TreeNode *r, int &ans) {
if (r == NULL)
return -1;
int d1 = treedepth(r -> left, ans);
int d2 = treedepth(r -> right, ans);
ans = max(ans, d1 + d2 + 2);
return max(d1, d2) + 1;
}
int diameterOfBinaryTree(TreeNode* root) {
int ans = 0;
treedepth(root, ans);
return ans;
}
};
No.8
标签:树
226. Invert Binary Tree
思路:递归遍历整棵二叉树,遍历到每个节点时交换左右孩子。
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if (!root) return nullptr;
swap(root->left, root->right);
invertTree(root->left);
invertTree(root->right);
return root;
}
};
No.9
标签:树 深度优先搜索
104. Maximum Depth of Binary Tree
二叉树的最大深度-- (我理解的就是看有多少层啦)
class Solution {
public:
int maxDepth(TreeNode* root) {
if (root == NULL)
return 0;
int d1 = maxDepth(root -> left);
int d2 = maxDepth(root -> right);
return max(d1, d2) + 1;
}
};
No.10
标签:树
617.Merge Two Binary Trees
class Solution {
public:
TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
if (!t1 && !t2)
return NULL;
if (!t1 && t2)
return t2;
if (t1 && !t2)
return t1;
t1 -> val += t2 -> val;
t1 -> left = mergeTrees(t1 -> left, t2 -> left);
t1 -> right = mergeTrees(t1 -> right, t2 -> right);
return t1;
}
};
/**
不修改原来的结构
*/
class Solution {
public:
TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
if (!t1 && !t2)
return NULL;
if (!t1 && t2)
return t2;
if (t1 && !t2)
return t1;
TreeNode* root = new TreeNode((t1==NULL?0:t1->val)+(t2==NULL?0:t2->val));
root -> left = mergeTrees(t1 -> left, t2 -> left);
root -> right = mergeTrees(t1 -> right, t2 -> right);
return root;
}
};
No.11
标签:树
437. Path Sum III
Find the number of paths that sum to a given value.
二叉树中和为某一值的路径的 个数
/**
双递归法,缺点是存在很多路径的重复计算
*/
class Solution {
public:
int pathSum(TreeNode* root, int sum) {
if (root==nullptr)
return 0;
return pathSum(root->left, sum) + pathSum(root->right, sum) + dfs(root, sum);
}
int dfs(TreeNode* node, int sum) { // 将当前节点考虑在内
if (node==nullptr)
return 0;
int count = 0;
if (node->val == sum)
count = 1;
return count + dfs(node->left, sum - node->val) + dfs(node->right, sum - node->val);
}
};
#仅仅需要一层递归即可~没有重复检查
检查方式也是极其简单,使用vector保存遍历过程中的值,然后反向for循环这个vector求和即可。沿着数组向前看。
class Solution {
public:
int pathSum(TreeNode* root, int sum) {
vectordata;
int r=0;
recursive(root,sum,data,r);
return r;
}
void recursive(TreeNode* root, int sum,vector& data,int &r){
if(!root) return;
data.push_back(root->val);
int curr=0;
for(int i=data.size()-1;i>=0;i--){//检查包含root->val的解的个数
curr+=data[i];
if(curr==sum)
r++;
}
recursive(root->left,sum,data,r);
recursive(root->right,sum,data,r);
data.pop_back();
}
};
No.12
标签:树 深度优先搜索 广度优先搜索
101. Symmetric Tree
class Solution {
public:
bool isSymmetric(TreeNode* root) {
return isMirror(root, root);
}
bool isMirror(TreeNode* t1, TreeNode* t2) {
if (t1 == nullptr && t2 == nullptr) return true;
if (t1 == nullptr || t2 == nullptr) return false;
return (t1->val == t2->val)
&& isMirror(t1->right, t2->left)
&& isMirror(t1->left, t2->right);
}
};
No.13
标签:数组
121. Best Time to Buy and Sell Stock
思路:找最大利润
class Solution {
public:
int maxProfit(vector& prices) {
if(prices.size()<2) return 0;
int profit = 0, low = prices[0];
for(int i = 1; i < prices.size(); ++i){
profit = max(profit, prices[i]-low);
low = min(low, prices[i]);
}
return profit;
}
};
No.14
标签:数组
448. Find All Numbers Disappeared in an Array
Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.Find all the elements of [1, n] inclusive that do not appear in this array.
思路:假设数组序号0~n-1 应该放的是数字1~n,则遍历数组,将当前元素与其应该放的位置处的元素交换,直到该位置处放的是应该放的元素或者与交换处元素相等。
class Solution {
public:
vector findDisappearedNumbers(vector& nums) {
vectorlist;
for(int i=0;i
No.15
标签:数组 动态规划
53. Maximum Subarray
最大子序和
Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.
class Solution {
public:
int maxSubArray(vector& nums) {
int n = nums.size(), ans;
vector f(n);
f[0] = nums[0];
ans = f[0];
for (int i = 1; i < n; i++) {
f[i] = max(f[i - 1] + nums[i], nums[i]);
ans = max(ans, f[i]);
}
return ans;
}
};
No.16
标签:数组
283. Move Zeroes
Given an array nums, write a function to move all 0’s to the end of it while maintaining the relative order of the non-zero elements.
class Solution {
public:
void moveZeroes(vector& nums) {
int i = 0;
for (int j = 0; j < nums.size(); j++)
if (nums[j] != 0)
nums[i++] = nums[j];
for (; i < nums.size(); i++)
nums[i] = 0;
}
};
No.17
标签:数组
581. Shortest Unsorted Continuous Subarray
最短无序连续子数组
Given an integer array, you need to find one continuous subarray that if you only sort this subarray in ascending order, then the whole array will be sorted in ascending order, too.You need to find the shortest such subarray and output its length.
思路:排序后前后夹击扫描 O(nlogn)
class Solution {
public:
int findUnsortedSubarray(vector& nums) {
int n = nums.size();
vector sorted_nums(nums);
sort(sorted_nums.begin(), sorted_nums.end());
int i = 0;
while (i < n && nums[i] == sorted_nums[i])
i++;
int j = n - 1;
while (j >= 0 && nums[j] == sorted_nums[j])
j--;
return max(0, j - i + 1);
}
};
方法2
思路:时间复杂度O(n),按照规则数组从小到大排序,那么:
使用max记录局部极大值,使用end标记这个局部最大值应该出现的位置,比如数组内部出现了一个比较大的数,怎么办呢?
只要后面的数比它小,那么end就记录下来当前位置,直到出现比他大的数字,max值被替换,说明我们已经找到,这个局部
极大值应该存放的位置,就这样持续遍历到尾,期间可能出现好几个局部极大值,那么end一定会越来越靠后,即它表示局部最大值
组成的集合中最大的那个值应该存放的位置。
同理,从后往前查找,用min表示局部极小值,star标记局部极小值应该存放的正确位置,持续遍历整个数组,若期间出现
好几个局部极小,star一定越来越靠前,即它表示局部极小值组成的集合中最小的那个值应该存放的位置。
end-star+1;
class Solution {
public:
int findUnsortedSubarray(vector& nums) {
int n = nums.size();
int start = -1;
int end = -2;
int minnumber = nums[n - 1];
int maxnumber = nums[0];
for(int i = 0, pos = 0; i < n; i++) {
pos = n - 1 - i;
maxnumber = max(maxnumber, nums[i]);
minnumber = min(minnumber, nums[pos]);
if(nums[i] < maxnumber)
end = i;
if(nums[pos] > minnumber)
start = pos;
}
return end - start + 1;
}
};
No.18
标签:数组,哈希
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
key 2 11 7 15
value 0 1 2 3…
unordered_maphash
class Solution {
public:
vector twoSum(vector& nums, int target) {
vector res;
unordered_maphash;
for(int i=0;i({hash[another],i});
break;
}
hash[nums[i]]=i;
}
return res;
}
};
No.19
标签:动态规划
70. Climbing Stairs
Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?
class Solution {
public:
int climbStairs(int n) {
if (n <= 0) {
return 0;
}
if (n == 1) {
return 1;
}
if (n == 2) {
return 2;
}
int first = 1, second = 2, third = 0;
for (int i = 3; i <= n; i++) {
third = first + second;
first = second;
second = third;
}
return third;
}
};
No.20
标签:动态规划
198. House Robber
这是一场有预谋的盗窃活动。现在一条路上有一排房间,每个房间都有一些钱。盗窃不能同时出现在两个相邻的房间,否则会触发警报。
现在给定这些房间的钱的数量,问在不触动警报的情况下最多能拿到多少钱。
class Solution {
public:
int rob(vector& nums) {
int n = nums.size();
if (n == 0)
return 0;
int f = nums[0], g = 0;
for (int i = 1; i < n; i++) {
int last_f = f, last_g = g;
f = last_g + nums[i];
g = max(last_f, last_g);
}
return max(f, g);
}
};
剑指offer:https://www.nowcoder.com/ta/coding-interviews?page=1
No.1
知识点:查找,数组
二维数组中的查找
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
class Solution {
public:
bool Find(int target, vector > array) {
if(array.size()!=0)
{
int row = 0;
int col = array[0].size()-1;
while(row < array.size() && col >= 0)
{
if(array[row][col] == target)
return true;
else if(array[row][col] > target)
--col;
else
++row;
}
}
return false;
}
};
No.2
知识点:字符串
替换空格
请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
class Solution {
public:
void replaceSpace(char *str,int length) {
if(str == nullptr||length <= 0)
return;
int originalLength = 0;
int numberOfBlank = 0;
int i = 0;
while(*(str+i) != '\0')
{
++originalLength;
if(*(str+i)==' ')
++numberOfBlank;
++i;
}
int newLength = originalLength + numberOfBlank*2;
if(newLength>length)
return;
int indexOfOriginal = originalLength;
int indexOfNew = newLength;
while(indexOfOriginal >= 0 && indexOfNew > indexOfOriginal)
{
if(*(str+indexOfOriginal) == ' ')
{
*(str+indexOfNew)='0';
indexOfNew--;
*(str+indexOfNew)='2';
indexOfNew--;
*(str+indexOfNew)='%';
indexOfNew--;
}
else{
*(str+indexOfNew)=*(str+indexOfOriginal);
indexOfNew--;
}
--indexOfOriginal;
}
}
};
No.3
知识点:链表
从尾到头打印链表
输入一个链表,按链表从尾到头的顺序返回一个ArrayList。
class Solution {
public:
vector printListFromTailToHead(ListNode* head) {
stack nodes;
ListNode* pNode = head;
vector outnodes;
while(pNode != nullptr)
{
nodes.push(pNode);
pNode = pNode->next;
}
while(!nodes.empty())
{
pNode = nodes.top();
outnodes.push_back(pNode->val);
nodes.pop();
}
return outnodes;
}
};
No.4
知识点:树
重建二叉树
/**
* Definition for binary tree
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* reConstructBinaryTree(vector pre,vector in) {
int in_size = in.size();
if(in_size == 0)
return NULL;
vector pre_left, pre_right, in_left, in_right;
int val = pre[0];
TreeNode* node = new TreeNode(val);//root node is the first element in pre
int p = 0;
for(;p < in_size; ++p){
if(in[p] == val) //Find the root position in in
break;
}
for(int i = 0; i < in_size; ++i){
if(i < p){
in_left.push_back(in[i]); //Construct the left pre and in
pre_left.push_back(pre[i+1]);
}
else if(i > p){
in_right.push_back(in[i]); //Construct the right pre and in
pre_right.push_back(pre[i]);
}
}
node->left = reConstructBinaryTree(pre_left, in_left);
node->right = reConstructBinaryTree(pre_right, in_right);
return node;
}
};
No.5
知识点:栈,队列
用两个栈实现一个队列
class Solution
{
public:
void push(int node) {
stack1.push(node);
}
int pop() {
if(stack2.empty()) {
while(!stack1.empty()) {
stack2.push(stack1.top());
stack1.pop();
}
}
int t=stack2.top();
stack2.pop();
return t;
}
private:
stack stack1;
stack stack2;
};
No.6
知识点:查找
旋转数组的最小数
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
class Solution {
public:
int minNumberInRotateArray(vector rotateArray) {
if(rotateArray.size() <= 0)
throw new std::exception();
int index1 = 0;
int index2 = rotateArray.size()-1;
int indexMid = index1;
while(rotateArray[index1] >= rotateArray[index2])
{
if(index2 - index1 == 1)
{
indexMid = index2;
break;
}
indexMid = (index1 + index2)/2;
// 如果下标为 index1, index2, indexMid 指向的三个数字相等,则只能顺序查找
if(rotateArray[index1]==rotateArray[index2] && rotateArray[indexMid] == rotateArray[index1])
return MinInOrder(rotateArray,index1,index2);
if(rotateArray[indexMid]>=rotateArray[index1])
index1 = indexMid;
else if(rotateArray[indexMid]<= rotateArray[index2])
index2 = indexMid;
}
return rotateArray[indexMid];
}
// 顺序查找
int MinInOrder(vector rotateArray, int index1, int index2)
{
int result = rotateArray[index1];
for(int i = index1 + 1;i<=index2; ++i)
{
if(result>rotateArray[i])
result = rotateArray[i];
}
return result;
}
};
No.7
知识点:动态规划
斐波那契数列
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。
class Solution {
public:
int Fibonacci(int n) {
int result[2]={0,1};
if(n<2)
return result[n];
int first = 0;
int second = 1;
int third = 0;
for(int i = 2;i<=n;i++){
third = first + second;
first = second;
second = third;
}
return third;
}
};