class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
// 获取二维数组的行列
int rows = array.size();
int cols = array[0].size();
// if(rows > 0 && cols > 0){
int i = 0;
int j = cols - 1;
while(i < rows && j>=0){
if(array[i][j] == target) return true;
else if(array[i][j] > target) --j;
else ++i;
}
// }
return false;
}
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
// 二分法
for(int n=0; n<array.size(); n++){
int i = 0;
int j = array[n].size() - 1;
while( i<= j){
int mid = (i+j)/2;
if(array[n][mid] == target) return true;
else if(array[n][mid] > target) j = mid - 1;
else i = mid + 1;
}
}
return false;
}
};
class Solution {
public:
void replaceSpace(char *str,int length) {
// 1、统计字符长度L1和空格数S
// 2、建立数组新的长度,为 L1+2S
// 3、从末尾开始寻找空格,如过遇到空格,就替换为%20;否则将字符后移
if(str == NULL) return;
int lengthOri = 0;
int numberSpace = 0;
for(int i=0; str[i] != '\0'; i++){
lengthOri++;
if(str[i] == ' ')
++numberSpace;
}
int lengthNew = lengthOri + 2 * numberSpace;
if(lengthNew > length) return;
char* pStr1 = str + lengthOri;
char* pStr2 = str + lengthNew;
while(pStr1 < pStr2){
if(*pStr1 == ' '){ // 带* 是指向此地址的内容,不带* 是指针地址
*pStr2 --= '0';
*pStr2 --= '2';
*pStr2 --= '%';
}
else
*pStr2 --= *pStr1;
--pStr1;
}
}
};
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
std::stack<ListNode*> node;
ListNode* pNode = head;
vector<int> result;
while(pNode != NULL){
node.push(pNode);
pNode = pNode->next;
}
while(!node.empty()){
result.push_back(node.top()->val);
node.pop();
}
return result;
}
};
class Solution {
vector<int> result;
public:
vector<int> printListFromTailToHead(ListNode* head) {
if(head != NULL){
if(head->next != NULL){
printListFromTailToHead(head->next);
}
result.push_back(head->val);
}
return result;
}
};
class Solution {
public:
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
// 1、先利用前序pre[0]找到根节点root,并得到vin的长度len
// 2、然后在中序vin中找到root的位置记录为root_vin
// 0 ~ root_vin-1 是中序左子树 ——> 放到 vin_left
// 1 ~ root_vin 是前序左子树 ——> 放到 pre_left
// root_vin+1 ~ len-1 为中序右子树 ——> 放到vin_right
// root_vin+1 ~ len-1 为前序右子树 ——> 放到pre_right
// 3、分别对左右子树递归,返回根节点、
int len = vin.size();
if(len == 0) return NULL;
// 1、建立根节点
TreeNode* head = new TreeNode(pre[0]);
// 找到root_vin
int root_vin = 0;
for(int i=0; i<len; i++){
if(vin[i] == pre[0]){
root_vin = i;
break;
}
}
// 2、
vector<int> pre_left, pre_right, vin_left, vin_right;
for(int i=0; i<root_vin; i++){
vin_left.push_back(vin[i]);
pre_left.push_back(pre[i+1]);
}
for(int i=root_vin+1; i<len; i++){
vin_right.push_back(vin[i]);
pre_right.push_back(pre[i]);
}
// 3、
head->left = reConstructBinaryTree(pre_left, vin_left);
head->right = reConstructBinaryTree(pre_right, vin_right);
return head;
}
};
class Solution {
public:
TreeLinkNode* GetNext(TreeLinkNode* pNode)
{
// 1、有右子树:其下一节点就是右节点中的最左子树
// 2、没有右子树:其下一个节点一定是父节点路径上第一个右父节点
if(pNode == NULL) return NULL;
// 1
if(pNode->right != NULL){
pNode = pNode->right; // 右节点
while(pNode->left != NULL){ // 右节点中的最左子树
pNode = pNode->left;
}
return pNode;
}
// 2
while(pNode->next != NULL){
if(pNode->next->left == pNode) // 第一个右父节点
return pNode->next;
pNode = pNode->next;
}
return NULL;
}
};
栈:先进后出
队列:先进先出
class Solution
{
public:
// 队列:先进先出
// 栈:先进后出
void push(int node) {
stack1.push(node);
}
int pop() {
// 先将栈1压入栈2
if(stack2.empty()){
while(!stack1.empty()){
int tmp;
tmp = stack1.top();
stack2.push(tmp);
stack1.pop();
}
}
if(stack2.empty())
printf("queue is empty");
// 出栈
int result;
result = stack2.top();
stack2.pop();
return result;
}
private:
stack<int> stack1;
stack<int> stack2;
};
class Solution {
public:
int Fibonacci(int n) {
// 递归容易出现内存溢出,且时间复杂度高,故使用循环
// 先计算0,1
int result[2] = {0,1};
if(n<2) return result[n];
// 再计算2及以上
int F_one = 1; // f(n-1)
int F_two = 0; // f(n-2)
int F_n = 0;
for(unsigned int i=2; i<=n; i++){
F_n = F_one + F_two;
F_two = F_one;
F_one = F_n;
}
return F_n;
}
};
1、青蛙跳台阶:一只青蛙一次可以跳1级台阶,也可以跳2级台阶。求该青蛙跳上一个n级台阶总共有多少种跳法。
2、变态青蛙跳:一只青蛙一次可以跳1级台阶,也可以跳2级台阶…, 它也可以跳上n级。求该青蛙跳上一个n级台阶总共有多少种跳法。
3、矩形覆盖:同样是斐波那契数列的变形
查找:
排序:
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
// 1、边界条件
// 2、双指针法(二分查找),P1 P2分别指向前后两个顺序序列
// 3、主循环:
// 二分查找 P_mid = (P1 + P2) / 2 进行范围缩小
// 要判断当有P1==P2 && P2==P_mid情况采用直接顺序查找
// 1
if(rotateArray.size() == 0) cout << "rotateArray is empty" << endl;
// 2
int len = rotateArray.size();
int P1 = 0;
int P2 = len - 1;
int P_mid = P1; // 返回P_mid处的值
// 3 注意此处是 P1>= P2,即前面序列大于后面序列时一直循环
while(rotateArray[P1] >= rotateArray[P2]){
if(P2 - P1 == 1){
P_mid = P2;
break;
}
P_mid = (P1 + P2) / 2;
if(rotateArray[P1] == rotateArray[P2] && rotateArray[P2] == rotateArray[P_mid])
InOrder(rotateArray, P1, P2);
if(rotateArray[P1] <= rotateArray[P_mid])
P1 = P_mid;
else if(rotateArray[P2] >= rotateArray[P_mid])
P2 = P_mid;
}
return rotateArray[P_mid];
}
int InOrder(vector<int> rotateArray, int P1, int P2){
int result;
for(int i = P1; i < P2-1; i++){
if(rotateArray[i] > rotateArray[i+1]){
result = rotateArray[i+1];
break;
}
}
return result;
}
};
class Solution {
public:
bool hasPath(char* matrix, int rows, int cols, char* str)
{
// 回溯法:
// 1、循环遍历每个格子作为起点
// 2、递归直到路径上的所有字符都在矩阵中找到想应的位置,并且使用布尔值矩阵标识路径是否已经进入格子
// 3、所有字符都在矩阵中找到合适的位置(此时str[pathLength] == '\0')
// 边界条件
if(matrix == NULL || rows <= 0 || cols <= 0; str == NULL)
return false;
// 布尔矩阵
bool *visit = new bool[rows * cols];
memset(visit, 0, rows * cols); // 被填充的矩阵,填充数字,填充长度
int pathLength = 0;
for(int row = 0; row < rows; row++){
for(int col = 0; col < cols; col++){
if(hasPathCore(matrix, rows, cols, row, col, str, visit, pathLength))
return true;
}
}
// delete: 释放new分配的【单个对象】指针指向的内存
// delete[]: 释放new分配的【对象数组】指针指向的内存
delete[] visit;
return false;
}
bool hasPathCore(const char* matrix, int rows, int cols, int row, int col,
const char* str, bool* visit, int pathLength){
if(str[pathLength] == '\0') // 最后一个是’\0’则完成
return true;
bool haspath = false;
if(rows>=0 && row<rows
&& cols>=0 && col < cols
&& matrix[row*cols + col] == str[pathLength]
&& !visit[row*cols + col])
{
++pathLength;
visit[row*cols + col] = true;
haspath = hasPathCore(matrix, rows, cols, row - 1, col, str, visit, pathLength)
|| hasPathCore(matrix, rows, cols, row + 1, col, str, visit, pathLength)
|| hasPathCore(matrix, rows, cols, row, col - 1, str, visit, pathLength)
|| hasPathCore(matrix, rows, cols, row, col + 1, str, visit, pathLength);
if(!haspath){
--pathLength;
visit[row * cols + col] = false;
}
}
return haspath;
}
};
class Solution {
public:
int movingCount(int threshold, int rows, int cols)
{
// 和矩阵中的路径类似
if(threshold < 0 || rows <=0 || cols <= 0)
return 0;
// 布尔值标识矩阵
bool *visited = new bool[rows * cols];
for(int i=0; i<rows*cols; i++)
visited[i] = false;
int count = movingCountCore(threshold, rows, cols, 0, 0, visited);
delete[] visited;
return count;
}
// 核心算法,递归得到count
int movingCountCore(int threshold, int rows, int cols,
int row, int col, bool* visited){
int count = 0;
if( check(threshold, rows, cols, row, col, visited) )
{
visited[row * cols + col] = true;
// 累加, 其实如果在(0,0) 周围都不满足阈值,也可以得到count
count = 1 + movingCountCore(threshold, rows, cols, row + 1, col, visited)
+ movingCountCore(threshold, rows, cols, row - 1, col, visited)
+ movingCountCore(threshold, rows, cols, row, col + 1, visited)
+ movingCountCore(threshold, rows, cols, row, col - 1, visited);
}
return count;
}
// 检测是否满足阈值条件,数位之和 <= 阈值
bool check(int threshold, int rows, int cols, int row, int col, bool* visited)
{
if( row >= 0 && row < rows && col >= 0 && col < cols // 注意row 和 col 的范围
&& getDigitSum(row) + getDigitSum(col) <= threshold
&& !visited[row * cols + col] )
return true;
return false;
}
// 计算得到数位之和(就是每一位数之和,例如35为 3+5 = 8)
int getDigitSum(int number)
{
int sum = 0;
// 循环得到每个位数
while(number > 0){
sum += number % 10;
number /= 10;
}
return sum;
}
};
class Solution {
public:
int cutRope(int number) {
// 动态规划:自下往上累加
// 先确定固定的number小的结果
// 两个for循环来确定最大值,分解成小问题的最优解
// 1
if(number<2) return 0; // 1*0
if(number == 2) return 1; // 1*1
if(number == 3) return 2; // 1*2
// 2
int *products = new int[number+1];
products[0] = 0;
products[1] = 1;
products[2] = 2;
products[3] = 3;
int max = 0;
for(int i=4; i<=number; i++){
max = 0;
for(int j=1; j<=i/2; j++){
int product = products[j] * products[i-j]; // j + i - j = i
if(max < product)
max = product;
products[i] = max;
}
}
max = products[number];
delete[] products;
return max;
}
};
class Solution {
public:
int cutRope(int number) {
// 贪婪算法:固定策略
// n>=5 尽可能多剪3,n=4,剪2
// 1
if(number<2) return 0; // 1*0
if(number == 2) return 1; // 1*1
if(number == 3) return 2; // 1*2
// 2 尽可能多的剪3
int timeOf3 = number/3;
// 此时更好的方法是剪成长度为2的两
if(number - timeOf3*3 == 1)
timeOf3 -= 1;
int timeOf2 = (number - timeOf3 * 3) / 2;
return int(pow(3, timeOf3) * pow(2, timeOf2));
}
};
class Solution {
public:
int NumberOf1(int n) {
int count = 0;
while(n)
{
++count;
n = (n-1) & n;
}
return count;
}
};
删除一个链表的两种方法:
要全面考虑重复节点所处的位置,以及删除重复节点之后的后果
class Solution {
public:
ListNode* deleteDuplication(ListNode* pHead)
{
if(pHead==NULL || pHead->next==NULL)
return pHead;
ListNode* Head = new ListNode(0); // 新建头节点
Head->next = pHead;
ListNode* pre = Head; // 辅助节点
ListNode* cur = Head->next; //当前节点
while(cur != NULL){
if(cur->next != NULL && cur->val == cur->next->val){
// 找到最后一个相同的节点
while(cur->next != NULL && cur->val == cur->next->val){
cur = cur->next;
}
pre->next = cur->next; // 直接接入当前节点的下一节点
cur = cur->next;
}
else{
pre = pre->next; // 继续往前走
cur = cur->next;
}
}
return Head->next;
}
};
一、首先,考虑特殊情况:
1>两个字符串都为空,返回true
2>当第一个字符串不空,而第二个字符串空了,返回false(因为这样,就无法
匹配成功了,而如果第一个字符串空了,第二个字符串非空,还是可能匹配成
功的,比如第二个字符串是“a*a*a*a*”,由于‘*’之前的元素可以出现0次,
所以有可能匹配成功)
二、之后就开始匹配第一个字符,这里有两种可能:匹配成功或匹配失败。但考虑到pattern
下一个字符可能是‘*’, 这里我们分两种情况讨论:pattern下一个字符为‘*’或
不为‘*’:
1>pattern下一个字符不为‘*’:这种情况比较简单,直接匹配当前字符。如果
匹配成功,继续匹配下一个;如果匹配失败,直接返回false。注意这里的
“匹配成功”,除了两个字符相同的情况外,还有一种情况,就是pattern的
当前字符为‘.’,同时str的当前字符不为‘\0’。
2>pattern下一个字符为‘*’时,稍微复杂一些,因为‘*’可以代表0个或多个。
这里把这些情况都考虑到:
a>当‘*’匹配0个字符时,str当前字符不变,pattern当前字符后移两位,
跳过这个‘*’符号;
b>当‘*’匹配1个或多个时,str当前字符移向下一个,pattern当前字符
不变。(这里匹配1个或多个可以看成一种情况,因为:当匹配一个时,
由于str移到了下一个字符,而pattern字符不变,就回到了上边的情况a;
当匹配多于一个字符时,相当于从str的下一个字符继续开始匹配)
class Solution {
public:
bool match(char* str, char* pattern)
{
if(str == NULL && pattern==NULL)
return false;
return matchCore(str, pattern);
}
bool matchCore(char* str, char* pattern)
{
// 1、字符和模式都为空'\0', 返回true
if(*str == '\0' && *pattern == '\0')
return true;
// 2、字符不为空,模式为空,肯定匹配不上,返回false
if(*str != '\0' && *pattern == '\0')
return false;
// 3、如果模式的下一个(第二个)字符位'*'
if(*(pattern+1) == '*')
{
// 如果字符串和模式第一个字符相匹配
if(*str == *pattern || (*pattern == '.' && *str != '\0')){
return matchCore(str+1, pattern) // 字符串后移一个字符,模式不变
|| matchCore(str+1, pattern+2) // 字符串后移一个字符,模式后移两个,'*'和其前面的字符可以算空
|| matchCore(str, pattern+2); // 字符串不动,模式后移两个,'*'和其前面的字符可以算空
}
else
return matchCore(str, pattern+2);
}
// 4、pattern下一个不为'*',直接匹配,如果匹配成功,返回字符,否则返回false。
if(*str == *pattern || (*pattern == '.' && *str != '\0'))
{
return matchCore(str+1, pattern+1);
}
return false;
}
};
class Solution {
public:
bool isNumeric(char* string)
{
// A[.[B]][e|EC]
if(string == NULL)
return false;
bool numeric = scanInteger(&string);
// '.'后面可以是数字的小数部分,点前面可以没有整数;点后面可以没有数字;点前后都可以有数字
if(*string == '.')
{
++string;
numeric = scanUnsignedInteger(&string) || numeric;
}
// 'e|E' 后面是指数部分,前面必须有数字,可以是小数;后面必须有整数
if(*string == 'e' || *string == 'E')
{
++string;
numeric = scanInteger(&string) && numeric;
}
return numeric && *string == '\0';
}
// 匹配B
bool scanUnsignedInteger(char** string)
{
char* before = *string;
while(**string != '\0' && **string >= '0' && **string <= '9')
++(*string);
return *string > before;
}
// 匹配AC
bool scanInteger(char** string)
{
if(**string == '+' || **string == '-')
++(*string);
return scanUnsignedInteger(string);
}
};
class Solution {
public:
void reOrderArray(vector<int> &array) {
int len = array.size();
if(len == 0 )
return;
// 冒泡排序
while(len--){
bool change = false;
for(int i=0; i<len; i++)
{
// 判断前后两个数据奇偶并交换
if(array[i] % 2 == 0 && array[i+1] % 2 == 1){
Swap(array, i, i+1);
change = true;
}
}
if(!change)
return;
}
}
void Swap(vector<int> &array, int i, int j){
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
};
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
// 边界条件
if(pListHead == NULL || k == 0)
return NULL;
ListNode* pAhead = pListHead;
ListNode* pBehid = NULL;
for(unsigned int i=0; i<k-1; i++){
if(pAhead->next != NULL)
pAhead = pAhead->next;
else
return NULL;
}
pBehid = pListHead;
while(pAhead->next != NULL){
pAhead = pAhead->next;
pBehid = pBehid->next;
}
return pBehid;
}
};
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
if(pHead == NULL)
return NULL;
ListNode* fast = pHead;
ListNode* slow = pHead;
while(fast != NULL && fast->next != NULL){
fast = fast->next->next;
slow = slow->next;
if(fast == slow){
ListNode* slow2 = pHead;
// 让slow2去和slow相遇,相遇的节点即为入口
while(slow2 != slow){
slow = slow->next;
slow2 = slow2->next;
}
return slow2;
}
}
return NULL;
}
};
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
if(pHead == NULL || pHead->next == NULL)
return pHead;
ListNode *ret = ReverseList(pHead->next); // 递归
pHead->next->next = pHead;
pHead->next = NULL;
return ret;
}
};
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
if(pHead == NULL && pHead->next == NULL)
return pHead;
ListNode *cur = pHead; // cur在前
ListNode *last = NULL;
while(cur != NULL){
ListNode *temp = cur->next;
cur->next = last; // 局部翻转
last = cur; // 同时前移
cur = temp;
}
return last;
}
};
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if(pHead1 == NULL)
return pHead2;
if(pHead2 == NULL)
return pHead1;
ListNode *pMergeNode = NULL;
// 链表1的值小于链表2的值
if(pHead1->val < pHead2->val){
pMergeNode = pHead1;
pMergeNode->next = Merge(pHead1->next, pHead2); // 将2放在1后
}
else{
pMergeNode = pHead2;
pMergeNode->next = Merge(pHead1, pHead2->next); // 否则1放在2后
}
return pMergeNode;
}
};
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
ListNode *vHead = new ListNode(-1); // 哨兵节点
ListNode *cur = vHead;
while(pHead1 && pHead2){
if(pHead1->val <= pHead2->val)
{
cur->next = pHead1;
pHead1 = pHead1->next;
}
else
{
cur->next = pHead2;
pHead2 = pHead2->next;
}
cur = cur->next;
}
cur->next = pHead1 ? pHead1:pHead2;
return vHead->next;
}
};
class Solution {
public:
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
{
bool result = false;
// 递归
if(pRoot1 != NULL && pRoot2 != NULL)
{
if(Equal(pRoot1->val, pRoot2->val)) // 注意此处判断是double 相等, 不能直接用等号来判断
result = DoesTreeHaveTree2(pRoot1, pRoot2);// 进行第二步判断
if(!result)
result = HasSubtree(pRoot1->left, pRoot2);
if(!result)
result = HasSubtree(pRoot1->right, pRoot2);
}
return result;
}
// 判断第二步:如果根节点相同之后,就判断左右节点是否相同
bool DoesTreeHaveTree2(TreeNode* pRoot1, TreeNode* pRoot2)
{
if(pRoot2 == NULL)
return true;
if(pRoot1 == NULL)
return false;
if(!Equal(pRoot1->val, pRoot2->val))
return false;
return DoesTreeHaveTree2(pRoot1->left, pRoot2->left)
&& DoesTreeHaveTree2(pRoot1->right, pRoot2->right);
}
bool Equal(double num1, double num2)
{
if((num1 - num2 > -0.0000001) && (num1 - num2 < 0.0000001))
return true;
else
return false;
}
};
【精简版的代码】
class Solution {
public:
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
{
return (pRoot1 != NULL && pRoot2 != NULL)
&& (recur(pRoot1, pRoot2)
|| HasSubtree(pRoot1->left, pRoot2)
|| HasSubtree(pRoot1->right, pRoot2));
}
bool recur(TreeNode* A, TreeNode* B){
if(B == NULL) return true;
if(A == NULL || A->val != B->val) return false;
return recur(A->left, B->left) && recur(A->right, B->right);
}
};
class Solution {
public:
void Mirror(TreeNode *pRoot) {
if(pRoot == NULL) // 注意边界条件
return;
// 非递归
queue<TreeNode*> pq;
pq.push(pRoot);
while(!pq.empty()){
int pq_size = pq.size();
while(pq_size--){
TreeNode* node = pq.front();
pq.pop();
// 层序遍历,将左右节点依次压入栈,供下次读取
if(node->left) pq.push(node->left);
if(node->right) pq.push(node->right);
// 交换节点
TreeNode* temp = node->left;
node->left = node->right;
node->right = temp;
}
}
}
};
class Solution {
public:
bool isSymmetrical(TreeNode* pRoot)
{
return isSymetricalCore(pRoot, pRoot);
}
bool isSymetricalCore(TreeNode* pRoot1, TreeNode* pRoot2){
if(pRoot1 == NULL && pRoot2 == NULL)
return true;
if(pRoot1 == NULL || pRoot2 == NULL)
return false;
if(pRoot1->val != pRoot2->val)
return false;
return isSymetricalCore(pRoot1->left, pRoot2->right) // 前序遍历
&& isSymetricalCore(pRoot1->right, pRoot2->left); // 对称前序遍历
}
};
class Solution {
public:
vector<int> printMatrix(vector<vector<int> > matrix) {
int rows = matrix.size();
int cols = matrix[0].size();
vector<int> result;
int start = 0;
if(cols <= 0 && rows <= 0)
return result;
while(rows > start*2 && cols > start*2){
int endX = cols - 1 - start; // 终止列
int endY = rows - 1 - start; // 终止行
for(int i=start; i<=endX; ++i){
result.push_back(matrix[start][i]);
}
if(start < endY){
for(int i=start+1; i<=endY; ++i){
result.push_back(matrix[i][endX]);
}
}
if(start<endX && start<endY){
for(int i=endX-1; i>=start; --i){
result.push_back(matrix[endY][i]);
}
}
if(start<endX && start<endY-1){
for(int i=endY-1; i>=start+1; --i){
result.push_back(matrix[i][start]);
}
}
++start;
}
return result;
}
};
class Solution {
public:
stack<int> Src;
stack<int> Min;
void push(int value) {
Src.push(value);
if(Min.empty() || value<=Min.top()){
Min.push(value);
}
}
void pop() {
if(Src.top() == Min.top())
Min.pop();
Src.pop();
}
int top() {
return Src.top();
}
int min() {
return Min.top();
}
};
class Solution {
public:
bool IsPopOrder(vector<int> pushV,vector<int> popV) {
// 新建一个栈,将数组A压入栈中,当栈顶元素等于数组B时,该元素出栈,当循环结束时判断,该栈是否为空,空则返回true
if(pushV.size() == 0 || popV.size() == 0 || pushV.size() != popV.size())
return false;
stack<int> stack;
int j = 0;
for(int i=0; i<pushV.size(); i++){
stack.push(pushV[i]);
while(!stack.empty() && stack.top() == popV[j]){
stack.pop();
j++;
}
}
return stack.empty(); // 为空则返回true,否则位false
}
};
class Solution {
public:
vector<int> PrintFromTopToBottom(TreeNode* root) {
vector<int> result;
if(!root)
return result;
std::deque<TreeNode*> dequeRoot; // 使用标准库的 deque 队列,两端都可以进出
dequeRoot.push_back(root);
while(dequeRoot.size())
{
TreeNode *pNode = dequeRoot.front();
dequeRoot.pop_front();
result.push_back(pNode->val);
if(pNode->left)
dequeRoot.push_back(pNode->left);
if(pNode->right)
dequeRoot.push_back(pNode->right);
}
return result;
}
};
二叉搜索树:又称二叉排序树,二叉查找树,
后续遍历:
本题:
class Solution {
public:
bool VerifySquenceOfBST(vector<int> sequence) {
// 先判断根节点左子树是否有大于根节点的值,再判断右子树
// 最后再递归判断左右子树是否符合
int length = sequence.size();
if(length <= 0)
return false;
int root = sequence[length - 1];
// 判断左子树
int i = 0;
vector<int> sequence_left;
for(; i<length-1; i++){
if(sequence[i] > root)
break;
sequence_left.push_back(sequence[i]);
}
// 判断右子树
int j = i;
vector<int> sequence_right;
for(; j<length-1; j++){
if(sequence[j] < root)
return false;
sequence_right.push_back(sequence[j]);
}
// 递归判断左右子树
bool left = true;
if(i > 0)
left = VerifySquenceOfBST(sequence_left);
bool right = true;
if(j < length-1)
right = VerifySquenceOfBST(sequence_right);
return(left && right);
}
};
class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead)
{
// 分解问题:1、根据原始链表的每个节点N创建对应N';2、设置复制出来的节点random;3、把长链表拆成复制链表
if(pHead == NULL) return NULL;
CloneNode(pHead);
ConnectRandomNode(pHead);
return ReconnectNode(pHead);
}
void CloneNode(RandomListNode* pHead)
{
RandomListNode* pNode = pHead;
while(pNode != NULL){
RandomListNode* pCloned = new RandomListNode(pNode->label); // 注意此处的new
pCloned->next = pNode->next;
pCloned->label = pNode->label;
pCloned->random = NULL;
pNode->next = pCloned;
pNode = pCloned->next;
}
}
void ConnectRandomNode(RandomListNode* pHead)
{
RandomListNode* pNode = pHead;
while(pNode != NULL){
RandomListNode* pCloneNode = pNode->next;
if(pNode->random != NULL){
pCloneNode->random = pNode->random->next;
}
pNode = pCloneNode->next;
}
}
RandomListNode* ReconnectNode(RandomListNode* pHead){
RandomListNode* pNode = pHead;
RandomListNode* pCloneHead = NULL;
RandomListNode* pClodeNode = NULL;
if(pNode != NULL){
pCloneHead = pClodeNode = pNode->next;
pNode->next = pClodeNode->next;
pNode = pNode->next;
}
while(pNode != NULL){
pClodeNode->next = pNode->next;
pClodeNode = pClodeNode->next;
pNode->next = pClodeNode->next;
pNode = pNode->next;
}
return pCloneHead;
}
};
class Solution {
public:
TreeNode* Convert(TreeNode* pRootOfTree)
{
// 1、由于二叉搜索树中序遍历是按照顺序排好的,当遍历到根节点的时候,把树分成三部分,根节点左子树,根节点,根节点右子树
// 2、先把根节点与左右子树双向链表链接,再递归左右子树
TreeNode* pLastNodeList = NULL;
ConvertNode(pRootOfTree, &pLastNodeList);
TreeNode *pHeadOfList = pLastNodeList;
while(pHeadOfList != NULL && pHeadOfList->left != NULL)
pHeadOfList = pHeadOfList->left;
return pHeadOfList;
}
void ConvertNode(TreeNode* pNode, TreeNode** pLastNodeList){
if(pNode == NULL) return;
TreeNode* pCurrent = pNode;
if(pCurrent->left != NULL)
ConvertNode(pCurrent->left, pLastNodeList);
pCurrent->left = *pLastNodeList;
if(*pLastNodeList != NULL)
(*pLastNodeList)->right = pCurrent;
*pLastNodeList = pCurrent;
if(pCurrent->right != NULL)
ConvertNode(pCurrent->right, pLastNodeList);
}
};
class Solution {
private:
TreeNode* Decode(char *&str){ // &str是内存地址,*&str表示&str指向地址内存空间的值
if(*str == '$'){
str++;
return NULL;
}
int num = 0;
while(*str != ',')
num = num*10 + (*(str++) - '0'); //
str++;
TreeNode *root = new TreeNode(num);
root->left = Decode(str);
root->right = Decode(str);
return root;
}
public:
char* Serialize(TreeNode *root) {
//
if(!root) return "$";
string s = to_string(root->val);
s.push_back(',');
char* left = Serialize(root->left);
char* right = Serialize(root->right);
char* result = new char[strlen(left) + strlen(right) + s.size()];// 新建字符串保存序列
strcpy(result, s.c_str()); // 复制
strcat(result, left); // 合并
strcat(result, right);
return result;
}
TreeNode* Deserialize(char *str) {
return Decode(str);
}
};
class Solution {
public:
vector<string> Permutation(string str) {
// 递归法,先固定第一个字符,求剩余字符的排列
// 1、遍历出所有可能出现第一个位置的字符
// 2、固定第一个字符,求后面字符的排列
vector<string> result;
if(str.empty()) return result;
PermutationCore(str, result, 0);
sort(result.begin(), result.end());
return result;
}
void PermutationCore(string str, vector<string> &result, int begin){ // 传入result地址
if(begin == str.size() - 1){// 递归结束条件,索引已近指向str最后一个元素时
if(find(result.begin(), result.end(), str) == result.end())
result.push_back(str); // 如果result中不存在str,才添加。避免重复添加的情况
}
else{
// 第一次循环i与begin相等,相当于第一个位置自身交换,关键在于之后的循环
// 之后i != begin,则会交换两个不同位置上的字符,直到begin==str.size() - 1,进行输出
for(int i=begin; i<str.size(); i++){
swap(str[i], str[begin]);
PermutationCore(str, result, begin+1);
swap(str[i], str[begin]); // 复位,用以恢复之前字符串顺序,达到第一位依次跟其他位交换的目的
}
}
}
void swap(char &first, char &second){
char temp = first;
first = second;
second = temp;
}
};
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers) {
if(numbers.empty()) return 0;
// 遍历每个元素,并记录次数,若与前一个元素相同,则次数加1,否则次数减1
int result = numbers[0];
int cnt = 1; // 次数
for(int i=0; i<numbers.size(); ++i){
if(cnt == 0){
result = numbers[i];
cnt = 1;
}
else if(numbers[i] == result)
++cnt; // 相同则加1
else
--cnt; // 不同则减1
}
// 判断result是否符合条件,即出现次数大于数组长度的一半
cnt = 0;
for(int i=0; i<numbers.size(); ++i){
if(numbers[i] == result) ++cnt;
}
return (cnt > numbers.size()/2) ? result : 0;
}
};
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers) {
if(numbers.empty()) return 0;
sort(numbers.begin(), numbers.end());
int middle = numbers[numbers.size() / 2];
int count = 0;
for(int i=0; i<numbers.size(); ++i){
if(numbers[i] == middle) ++count;
}
return (count > (numbers.size()/2)) ? middle : 0;
}
};