文章目錄
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]結尾的子數組最大和
};