24 二叉树中和为某一值的路径

题目描述

输入一颗二叉树的根节点和一个整数,按字典序打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。

示例1

输入:

1
{10,5,12,4,7},22

返回值:

1
[[10,5,7],[10,12]]

示例2

输入:

1
{10,5,12,4,7},15

返回值:

1
[]

思路:

本题用到回溯法,先序遍历二叉树,遇到节点后判断是否为一条路径,若是则加入结果集中,不是则回溯到上一步。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public:
vector<vector<int> > FindPath(TreeNode* root,int expectNumber) {
vector<vector<int>> res;
if(root==nullptr)return res;
vector<int> push;
dfs(root,expectNumber,res,push);
return res;
}
void dfs(TreeNode* root,int expectNumber,vector<vector<int>>& res,vector<int> push){
push.push_back(root->val);
if(!root->left&&!root->right&&expectNumber-root->val==0){
res.push_back(push);
}
else{
if(root->left)dfs(root->left,expectNumber-root->val,res,push);
if(root->right)dfs(root->right,expectNumber-root->val,res,push);
}
push.pop_back();
}
};

25 复杂链表的复制

题目描述

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

思路:

  1. 在旧链表中创建新链表,把复制的节点链接到旧链表对应节点的后面

img

  1. 遍历链表,根据旧数组中存在random指针的节点,创建新链表中对应节点的random指针

img

  1. 把旧链表拆分成两个链表,返回新链表的头节点

img

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead) {
if(!pHead)return nullptr;
RandomListNode *head=pHead;
while(head){
RandomListNode *clone=new RandomListNode(head->label);
clone->next=head->next;
head->next=clone;
head=clone->next;
}
head=pHead;
RandomListNode *clone;
while(head){
clone=head->next;
if(head->random)
clone->random=head->random->next;
head=clone->next;
}
RandomListNode *cHead=pHead->next;
head=pHead;
while(head->next){
clone=head->next;
head->next=clone->next;
head=clone;
}
return cHead;
}
};

26 二叉搜索树与双向链表

题目描述

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

思路:

中序遍历二叉树,设置一个pre指针指向前一个节点,当前节点和pre节点互为左右节点,最后找到链表的头节点返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
public:
TreeNode* Convert(TreeNode* pRootOfTree) {
if(pRootOfTree==nullptr)return nullptr;
TreeNode* pre=nullptr;
dfs(pRootOfTree,pre);
TreeNode* node=pRootOfTree;
while(node->left){
node=node->left;
}
return node;
}

void dfs(TreeNode* cur,TreeNode* &pre){
if(cur==nullptr)return;
dfs(cur->left,pre);

cur->left=pre;
if(pre)pre->right=cur;
pre=cur;

dfs(cur->right,pre);

}
};

27 字符串的排列

题目描述

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则按字典序打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

输入描述:

1
输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。

示例1

输入:

1
"ab"

返回值:

1
["ab","ba"]

思路:

此为全排列问题,用回溯法解决,设置一个辅助数组标记当前节点是否使用,因为字符串可能重复,所以当前字符若和前一个字符相同且前一个字符处于可用状态,当前字符不入栈

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Solution {
public:
vector<string> Permutation(string str) {
vector<string> res;
string push;
if(str.size()==0)return res;
vector<bool>b(str.size(),1);
dfs(str,res,push,b);
return res;
}

void dfs(string str,vector<string>& res,string push,vector<bool> b){
if(push.size()==str.size()){
res.push_back(push);
return;
}
for(int i=0;i<str.size();i++){
if(b[i]){
if(str[i]==str[i-1]&&b[i-1])continue;
push+=str[i];
b[i]=false;
dfs(str,res,push,b);
b[i]=true;
push.pop_back();
}
}
}
};

28 数组中出现次数超过一半的数字

题目描述

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

示例1

输入:

1
[1,2,3,2,2,2,5,4,2]

返回值:

1
2

思路:

创建一个map保存数组中出现的数,出现次数作为对应的键值,若超过数组长度一半则返回当前数

1
2
3
4
5
6
7
8
9
10
11
12
13
#include<unordered_map>
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers) {
int targrt=numbers.size()/2+1;
unordered_map<int,int> map;
for(auto n:numbers){
map[n]++;
if(map[n]>=targrt)return n;
}
return 0;
}
};

29 最小的K个数

题目描述

给定一个数组,找出其中最小的K个数。例如数组元素是4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。如果K>数组的长度,那么返回一个空的数组

示例1

输入:

1
[4,5,1,6,2,7,3,8],4

返回值:

1
[1,2,3,4]

思路:

先将数组排序,此处利用stl库中的sort函数进行排序,然后初始化数组长度为k

1
2
3
4
5
6
7
8
9
10
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> res;
if(k>input.size())return res;
sort(input.begin(),input.end());
res = vector<int>(input.begin(),input.begin()+k);
return res;
}
};

30 连续子数组的最大和

题目描述

输入一个整型数组,数组里有正数也有负数。数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为 O(n).

示例1

输入:

1
[1,-2,3,10,-4,7,2,-5]

返回值:

1
18

说明:

1
输入的数组为{1,-2,3,10,—4,7,2,一5},和最大的子数组为{3,10,一4,7,2},因此输出为该子数组的和 18。 

思路:

用动态规划的思想,前n个数的最大值=前n-1个数的和加上当前数与当前数比较取最大值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public:
int FindGreatestSumOfSubArray(vector<int> array) {
if(array.size()==0)return 0;
vector<int> dp(array.size(),0);
dp[0]=array[0];
int m=array[0];
for(int i=1;i<array.size();i++){
dp[i]=max(array[i],dp[i-1]+array[i]);
m=max(m,dp[i]);
}
return m;
}
};