文章目录
21. 栈的压入、弹出序列
class Solution {
public:
bool IsPopOrder(vector<int> pushV,vector<int> popV) {
int i = 0;
int j = 0;
for(; i<pushV.size(); i++)
{
s.push(pushV[i]);
while(j < popV.size() && s.top() == popV[j])
{
s.pop();
j++;
}
}
return s.empty();
}
private:
stack<int> s;
};
22. 从上往下打印二叉树
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
vector<int> PrintFromTopToBottom(TreeNode* root) {
vector<int> ret;
if(!root)
return ret;
queue<TreeNode*> q;
q.push(root);
while(!q.empty())
{
TreeNode *node = q.front();
q.pop();
ret.push_back(node->val);
if(node->left)
q.push(node->left);
if(node->right)
q.push(node->right);
}
return ret;
}
};
23. 二叉搜索树的后序遍历序列
二叉搜索树(二叉排序树):
- 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值
class Solution {
public:
bool VerifySquenceOfBST(vector<int> sequence) {
if(sequence.size() == 0)
return false;
return help(sequence, 0, sequence.size()-1);
}
private:
bool help(const vector<int>& sequence, int l, int r)
{
if(l >= r)
return true;
int target = sequence[r]; //根节点值
int i = l;
while(sequence[i] < target && i < r) //左子树 < 根节点值
i++;
int mid = i-1;
for(; i< r; i++)
{
if(sequence[i] <= target)
return false;
}
return help(sequence, l, mid) && help(sequence, mid+1, r-1);
}
};
24.二叉树中和为某一值的路径
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
vector<vector<int> > FindPath(TreeNode* root,int expectNumber) {
vector<vector<int>> ret;
if(!root)
return ret;
vector<int> v;
help(root, expectNumber, ret, v);
return ret;
}
private:
void help(TreeNode *node, int expectNumber, vector<vector<int>> &ret, vector<int> &v)
{
v.push_back(node->val);
if(!node->left && !node->right && node->val == expectNumber)
{
ret.push_back(v);
}
if(node->left)
{
help(node->left, expectNumber-node->val, ret, v);
}
if(node->right)
{
help(node->right, expectNumber-node->val, ret, v);
}
v.pop_back();
}
};
25. 复杂链表的复制
方法一:
- 第一遍构建next指针,同时保存random信息到 map<RandomListNode , RandomListNode >
- 第二遍根据 map 信息构建random
/*
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
*/
class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead)
{
if(!pHead)
return pHead;
RandomListNode *newHead = new RandomListNode(pHead->label);
m[pHead] = newHead;
RandomListNode *curP = pHead->next;
RandomListNode *curN = newHead;
while(curP)
{
RandomListNode *node = new RandomListNode(curP->label);
curN->next = node;
m[curP] = node;
curP = curP->next;
curN = curN->next;
}
curP = pHead;
curN = newHead;
while(curP)
{
if(curP->random)
{
RandomListNode *tmp = curP->random;
curN->random = m[tmp];
}
curP = curP->next;
curN = curN->next;
}
return newHead;
}
private:
map<RandomListNode*, RandomListNode*> m; //first:保存原始链表节点 second:保存对应的新链表节点
};
方法二:
- 将每个新建的节点放在对应原节点之后
- 原节点的random的next为新节点的random
- 分离两个链表
/*
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
*/
class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead)
{
if(!pHead)
return pHead;
RandomListNode *cur = pHead;
while(cur) //构建 next
{
RandomListNode *node = new RandomListNode(cur->label);
node->next = cur->next;
cur->next = node;
cur = node->next;
}
cur = pHead;
while(cur) //构建 random
{
RandomListNode *node = cur->next;
if(cur->random)
{
node->random = cur->random->next;
}
cur = node->next;
}
cur = pHead;
RandomListNode *ret = cur->next;
while(cur->next) //分离链表 务必画图
{
RandomListNode *newN = cur->next;
cur->next = cur->next->next;
cur = newN;
}
return ret;
}
};
26. 二叉搜索树与双向链表
方法一:
- 中序遍历,将节点保存在 vector 中
- 遍历vector,将节点的 left 指向前一个节点,right 指向后一个节点
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution
{
public:
TreeNode* Convert(TreeNode* pRootOfTree)
{
if((pRootOfTree == NULL) || (!pRootOfTree->left) && (!pRootOfTree->right))
return pRootOfTree;
inOrder(pRootOfTree);
nodeVector[0]->left = NULL;
nodeVector[0]->right = nodeVector[1];
int i = 1;
for( ; i < nodeVector.size() - 1; i ++)
{
nodeVector[i]->left = nodeVector[i - 1];
nodeVector[i]->right = nodeVector[i + 1];
}
nodeVector[i]->left = nodeVector[i - 1];
nodeVector[i]->right = NULL;
return nodeVector[0];
}
private:
vector<TreeNode *> nodeVector;
void inOrder(TreeNode* root)
{
if(root->left)
inOrder(root->left);
nodeVector.push_back(root);
if(root->right)
inOrder(root->right);
}
};
方法二:
- 将左子树变为有序的排序链表,
- 再将右子树变为有序的链表,
- 然后将当前结点插入到两个链表中间
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution
{
public:
TreeNode* Convert(TreeNode* pRootOfTree)
{
if(!pRootOfTree)
return pRootOfTree;
TreeNode *lNode = Convert(pRootOfTree->left);
TreeNode *rNode = Convert(pRootOfTree->right);
TreeNode *node = lNode;
if(node)
{
while(node->right) //找到左链表的最后一个节点
node = node->right;
node->right = pRootOfTree;
}
pRootOfTree->left = node;
if(rNode)
rNode->left = pRootOfTree;
pRootOfTree->right = rNode;
return (lNode)?lNode:pRootOfTree;
}
};
27. 字符串的排列
class Solution {
public:
vector<string> Permutation(string str) {
if(str.length() == 0)
return vector<string>();
visited = vector<bool>(str.length(), false);
string s;
help(str, 0, s);
vector<string> v(s_.begin(), s_.end());
return v;
}
private:
set<string> s_; //去重
vector<bool> visited;
void help(const string &str, int index, string s)
{
if(index == str.length())
{
s_.insert(s);
return ;
}
for(int i=0; i<str.length(); i++)
{
if(!visited[i])
{
visited[i] = true;
help(str, index+1, s+str[i]);
visited[i] = false;
}
}
}
};
28. 数组中出现次数超过一半的数字
方法一:
- 用map统计数字出现的次数
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers) {
for(int i=0; i<numbers.size(); i++)
{
int num = ++m[numbers[i]];
if(num > numbers.size()/2)
return numbers[i];
}
return 0;
}
private:
map<int, int> m;
};
方法二:
- 数组排序后,如果符合条件的数存在,则一定是数组中间那个数
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers) {
sort(numbers.begin(), numbers.end());
int n = numbers.size();
int mid = numbers[n/2];
int ret = 0;
for(int i=0; i<n; i++)
{
if(numbers[i] == mid)
ret++;
}
return (ret>n/2)?mid:0;
}
};
方法三:
- 如果符合条件的数存在,则其他数字出现的次数和要小于这个数
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers) {
int num = numbers[0];
int index = 1;
for(int i=1; i<numbers.size(); i++)
{
if(index == 0)
{
num = numbers[i];
index = 1;
continue;
}
if(num == numbers[i])
index++;
else
index--;
}
//判断是否符合条件
int count = 0;
for(int i=0; i<numbers.size(); i++)
{
if(numbers[i] == num)
count++;
}
return (count>numbers.size()/2)?num:0;
}
};
29. 最小的K个数
方法一:
- 大根堆
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> ret;
if(input.size() < k)
return ret;
for(int i=0; i<input.size(); i++)
{
if(pq.size()<=k || pq.top() > input[i])
pq.push(input[i]);
if(pq.size() > k)
pq.pop();
}
while(pq.size() > 0)
{
ret.push_back(pq.top());
pq.pop();
}
return ret;
}
private:
priority_queue<int> pq;
};
方法二:
- 排序
30. 连续子数组的最大和
class Solution {
public:
int FindGreatestSumOfSubArray(vector<int> array) {
int maxSum = INT_MIN;
int sum = 0;
for(int i=0; i<array.size(); i++)
{
sum += array[i];
if(sum > maxSum)
maxSum = sum;
if(sum < 0) //在每次元素累加和小于0时,从下一个元素重新开始累加
sum = 0;
}
return maxSum;
}
};
动态规划
class Solution {
public:
int FindGreatestSumOfSubArray(vector<int> array) {
memo = vector<int>(array.size(), -1);
memo[0] = array[0];
for(int i=1; i<array.size(); i++)
{
memo[i] = max(memo[i-1]+array[i], array[i]);
}
sort(memo.begin(), memo.end());
return memo[array.size()-1];
}
private:
vector<int> memo; //memo[i]:以array[i]结尾的子数组最大和
};