数据结构-算法题(c++完整代码实现)
第1章-线性表
1.1 单链表的函数接口
#include<iostream>
using namespace std;
class MylinkList {
public:
struct LinkNode {
int val;
LinkNode* next;
LinkNode(int x):val(x),next(NULL){}
};
MylinkList() {
//虚拟头结点,而不是真正的链表头结点
_dummyHead = new LinkNode(0);
size = 0;
}
~MylinkList() {
LinkNode* cur = _dummyHead;
LinkNode* temp = NULL;
while (cur!= NULL) {
temp = cur;
cur = cur->next;
delete temp;
temp = NULL;
}
if (temp != NULL) {
temp = NULL;
cout << "成功释放内存" << endl;
}
}
//获得第index个节点的值,若index非法,则返回-1,第0个节点是头结点
int get(int index) {
if (index < 0 || index >size-1) {
return -1;
}
LinkNode* cur = _dummyHead->next;
while (index--) {
cur = cur->next;
}
return cur->val;
}
// 在链表最前面插入一个节点,插入完成后,新插入的节点为链表的新的头结点
void addAtHead(int val) {
LinkNode* L = new LinkNode(val);
L->next = _dummyHead->next;
_dummyHead->next = L;
size++;
}
// 在链表最后面添加一个节点
void addAtTail(int val) {
LinkNode* L = new LinkNode(val);
LinkNode* cur = _dummyHead;
while (cur->next!=NULL) {
cur = cur->next;
}
//L->next = NULL;
cur->next = L;
size++;
}
// 在第index个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。
// 如果index 等于链表的长度,则说明是新插入的节点为链表的尾结点
// 如果index大于链表的长度,则返回空
void addAtIndex(int index, int val) {
if (index > size || index<0) {
return;
}
LinkNode* L = new LinkNode(val);
LinkNode* cur = _dummyHead;
while (index--) {
cur = cur->next;
}
L->next = cur->next;
cur->next = L;
size++;
}
//删除第index个节点,如果index大于链表长度,直接return
void deleteAtIndex(int index) {
if (index<0 || index>size - 1) {
return;
}
LinkNode* cur = _dummyHead;
while (index--) {
cur = cur->next;
}
LinkNode* temp = cur->next;
cur->next = cur->next->next;
delete temp;
}
//打印指针
void printLinkList() {
LinkNode* cur = _dummyHead;
while (cur->next!=NULL) {
cur = cur->next;
cout << cur->val << " ";
}
cout << endl;
}
//反转链表
void reversLinkList() {
LinkNode* Pre = NULL;
//删除虚拟头结点
/*LinkNode* temp1 = _dummyHead;
_dummyHead = _dummyHead->next;
delete temp1;*/
LinkNode* cur = _dummyHead->next;
LinkNode* temp;
while (cur != NULL) {
temp = cur->next;
cur->next = Pre;
Pre = cur;
cur = temp;
}
_dummyHead->next = Pre;
}
LinkNode* get() {
return this->_dummyHead;
}
private:
int size;
LinkNode* _dummyHead;
};
void test1() {
MylinkList m1;
m1.addAtTail(10);
m1.addAtTail(20);
m1.printLinkList();
m1.reversLinkList();
m1.printLinkList();
}
int main() {
test1();
}
反转链表运行窗口:
第2章-栈和队列
题目2.1-用栈实现队列
使用栈实现队列的下列操作:
push(x) – 将一个元素放入队列的尾部。
pop() – 从队列首部移除元素。
peek() – 返回队列首部的元素。
empty() – 返回队列是否为空。
#include <stack>
#include<iostream>
using namespace std;
//两个栈相当于一个队列
class MyQueue {
public:
stack<int>stdIn;
stack<int>stdOut;
MyQueue() {
}
void push(int x) {
stdIn.push(x);
}
int pop() {
if (stdOut.empty()) {
while (!stdIn.empty()) {
stdOut.push(stdIn.top());
stdIn.pop();
}
}
int result = stdOut.top();
stdOut.pop();
return result;
}
int peek() {
int res = this->pop();
stdOut.push(res);
return res;
}
bool empty() {
return stdIn.empty() && stdOut.empty();
}
};
void test1() {
MyQueue queue1;
queue1.push(10);
queue1.push(20);
cout << "队首元素:"<<queue1.peek() << endl;
cout << "移除队列第一个元素:" << queue1.pop() << endl;
cout << "移除队列第二个元素:" << queue1.pop() << endl;
cout << "队列是否为空:1 为空,2 不为空" << queue1.empty() << endl;
}
int main() {
test1();
return 0;
}
运行窗口:
题目2.2-用队列实现栈
使用队列实现栈的下列操作:
push(x) --元素 x 入栈
pop() --移除栈顶元素
top() --获取栈顶元素
empty() --返回栈是否为空
#include<queue>
#include<iostream>
using namespace std;
class MyStack {
public:
queue<int>q1;
queue<int>q2;
MyStack() {
}
void push(int x) {
q1.push(x);
}
int pop() {
if (q1.empty()) {
cout << "栈已经为空" << endl;
return 0;
}
int size = q1.size() - 1;
while (size--) {
q2.push(q1.front());
q1.pop();
}
int result = q1.front();
q1.pop();
q1 = q2;
while (!q2.empty()) {
q2.pop();
}
return result;
}
int top() {
return q1.back();
}
bool empty() {
return q1.empty();
}
};
void test1() {
MyStack st;
st.push(10);
st.push(20);
st.push(30);
cout << "栈是否为空 0:不为空 1:为空 " << st.empty() << endl;
cout << "栈的顶部元素:" << st.top() << endl;
cout << "栈顶第一个元素:" << st.pop() << endl;
cout << "栈顶第二个元素:" << st.pop() << endl;
cout << "栈顶第三个元素:" << st.pop() << endl;
st.pop();
}
int main() {
test1();
}
运行窗口:
题目2.3-有效的括号
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
示例 1:
输入: “()[]{}”
输出: true
#include<string>
#include<iostream>
using namespace std;
#include<stack>
class solution {
public:
bool validString(string str1) {
stack<int>st1;
for (int i = 0; i < str1.size(); i++) {
if (str1[i] == '[') {
st1.push(']');
}
else if (str1[i] == '(') {
st1.push(')');
}
else if (str1[i] == '{') {
st1.push('}');
}
else {
if (!st1.empty() && st1.top()==str1[i]) {
st1.pop();
continue;
}
return false;
}
}
return st1.empty();
}
};
void test1() {
solution s1;
string str{ "()[]{}" };
string str1{ "(]" };
string str2{ "([)]" };
string str3{ "()" };
cout << s1.validString(str) << endl;
cout << s1.validString(str1) << endl;
cout << s1.validString(str2) << endl;
cout << s1.validString(str3) << endl;
}
int main() {
test1();
return 0;
}
运行窗口:
题目2.4-删除字符串中的所有相邻重复项
给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
示例:
输入:“abbaca”
输出:“ca”
#include<string>
#include<iostream>
using namespace std;
#include<stack>
#include<algorithm>
//输入:"abbaca"
//输出:"ca"
class solution {
public:
string deleSameChar(string& str) {
stack<char>st;
for (int i = 0; i < str.size(); i++) {
if (!st.empty()&&str[i]==st.top()) {
st.pop();
continue;
}
st.push(str[i]);
}
string result = "";
while (!st.empty()) {
result += st.top();
st.pop();
}
reverse(result.begin(), result.end());
return result;
}
};
void fun(char s1) {
cout << s1 ;
}
void test1() {
solution s1;
string str1{ "abbaca" };
string str2{ "abbaccd" };
string str3 = s1.deleSameChar(str1);
string str4 = s1.deleSameChar(str2);
//利用for_each进行输出字符串
for_each(str3.begin(), str3.end(), fun);
cout << endl;
for_each(str4.begin(), str4.end(), fun);
}
int main() {
test1();
}
运行窗口:
题目2.5-删除字符串中的所有相邻重复项
示例 1:
输入: [“2”, “1”, “+”, “3”, " * "]
输出: 9
解释: 该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
#include<string>
#include<iostream>
using namespace std;
#include<stack>
#include<vector>
class solution {
public:
int evalRPN(vector<string>& tokens) {
stack<int>st;
for (int i = 0; i < tokens.size(); i++) {
if (tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/") {
int num1;
num1 = st.top();
st.pop();
int num2;
num2 = st.top();
st.pop();
int result;
if (tokens[i] == "+") {
st.push(num2+num1);
}
else if (tokens[i] == "-") {
st.push(num2 - num1);
}
else if (tokens[i] == "*") {
st.push(num2*num1);
}
else {
st.push(num2 / num1);
}
}
else {
st.push(atoi(tokens[i].c_str()));
//另外一种将字符串转化为数字的方法,二选一即可
//st.push(stoi(tokens[i]));
}
}
int result = st.top();
return result;
}
};
void test1(){
vector <string> v1{"2","1","+","3","*"};
solution s1;
cout << "result=" << s1.evalRPN(v1);
}
int main() {
test1();
}
运行窗口:
第3章-串
题目3.1-反转字符串
给定一个字符串 s 和一个整数 k,你需要对从字符串开头算起的每隔 2k 个字符的前 k 个字符进行反转。
如果剩余字符少于 k 个,则将剩余字符全部反转。
如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
示例:
输入: s = “abcdefg”, k = 2
输出: “bacdfeg”
#include<iostream>
using namespace std;
#include<vector>
class solution {
public:
solution() {};
//反转字符串函数
void reverse1(vector<char>&v1, int start, int end) {
int middle = (end - start + 1) / 2;
for (int i = start, j = end; i < start + middle; i++, j--) {
swap(v1[i], v1[j]);
}
}
vector<char> reverseString(vector<char>&v1, int k) {
for (int i = 0; i < v1.size(); i += (2 * k)) {
//小于 2k 但大于或等于 k 个,则反转前 k 个字符
if (i + k <= v1.size()) {
reverse1(v1, i, i + k-1);
continue;
}
//少于 k 个,将剩余字符全部反转
reverse1(v1, i, v1.size() - 1);
}
return v1;
}
//交换字符swap函数
void swap(char& s1, char& s2) {
char temp;
temp = s1;
s1 = s2;
s2 = temp;
}
void printVector(vector<char>s1) {
for (int i = 0; i < s1.size(); i++) {
cout << s1[i] << " ";
}
cout << endl;
}
};
void test1() {
//创建字符容器并初始化
vector<char>v1{ 'b','a','c','d','f' };
solution s1;
s1.printVector(v1);
s1.reverseString(v1, 2);
s1.printVector(v1);
}
int main(){
test1();
return 0;
}
运行结果:
题目3.2-替换空格
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
示例 1:
输入:s = “We are happy.”
输出:“We%20are%20happy.”
class solution {
public:
string replaceString(string& s1) {
int count = 0;
//记录初始字符串容器的大小
int m_size = s1.size();
//找出字符串的空格数
for (int i = 0; i < s1.size(); i++) {
if (s1[i] == ' ') {
count++;
}
}
//重置数组大小,扩容
s1.resize(s1.size() + count * 2);
//利用双指针,进行循环
for (int i = s1.size() - 1,j = m_size - 1; j < i; j--, i--) {
if (s1[j] != ' ') {
s1[i] = s1[j];
}
else {
s1[i] = '0';
s1[i - 1] = '2';
s1[i - 2] = '%';
i -= 2;
}
}
return s1;
}
//打印输出字符串
void display(string s) {
for (int i = 0; i < s.size(); i++) {
cout << s[i] << " ";
}
cout << endl;
}
};
void test1() {
solution m1;
string s1{ "We are happy." };
m1.display(s1);
m1.replaceString(s1);
m1.display(s1);
}
int main() {
test1();
return 0;
}
运行结果:
题目3.3-翻转字符串里的单词
给定一个字符串,逐个翻转字符串中的每个单词。
示例 1:
输入: “the sky is blue”
输出: “blue is sky the”
#include<iostream>
using namespace std;
#include<string>
class solution {
public:
void removeExtraSpace(string& s1) {
int slowIndex = 0;
int fastIndex = 0;
//检查字符串首尾是否有空格,并且去除
while ( fastIndex < s1.size() && s1[fastIndex]==' ') {
fastIndex++;
}
for (; fastIndex < s1.size(); fastIndex++) {
//删除字符串中间多余的空字符
if (s1[fastIndex] == ' '&& fastIndex-1>0 && s1[fastIndex-1]==s1[fastIndex]) {
continue;
}
else {
s1[slowIndex++] = s1[fastIndex];
}
}
//删除字符串尾部的字符
if (s1[slowIndex - 1] ==' ') {
s1.resize(slowIndex - 1);
}
else {
s1.resize(slowIndex);
}
}
string reverseWord(string& s1) {
removeExtraSpace(s1);
reverse1(s1, 0, s1.size() - 1);
int start = 0;
int end = 0;
//标记是否进入字符串
bool entry = false;
for (int i = 0; i < s1.size(); i++) {
//第一个字符直接标记开始,进入下一个字符
if (i==0) {
start = i;
entry = true;
continue;
}
if ((!entry) || (s1[i] != ' ' && s1[i - 1] == ' ')) {
start = i; // 确定单词起始位置
entry = true; // 进入单词区间
}
if (s1[i] == ' '&& s1[i - 1] != ' ' && entry) {
end = i - 1;
entry = false;
reverse1(s1, start, end);
}
if (entry && i == (s1.size() - 1) && s1[i] != ' ') {
end = i;
entry = false;
reverse1(s1, start, end);
}
}
return s1;
}
//双指针反转字符
void reverse1(string& v1, int start, int end) {
for (int i = start, j = end; i < j; i++, j--) {
swap(v1[i], v1[j]);
}
}
void swap(char& s1, char& s2) {
char temp;
temp = s1;
s1 = s2;
s2 = temp;
}
void display(string s) {
for (int i = 0; i < s.size(); i++) {
cout << s[i] << " ";
}
cout << endl;
}
};
void test1() {
solution s;
string str1;
string str{ " the sky is blue " };
s.display(str);
str1=s.reverseWord(str);
s.display(str1);
}
int main() {
test1();
return 0;
}
运行结果:
第4章-哈希表
题目4.1-两个数组的交集
示例 1:
输入: a1[6]={1,2,2,3,5,1}
a2[4]={2,2,5,1}
输出: 2,5,1
#include<iostream>
using namespace std;
#include<vector>
#include<unordered_set>
void printSet(unordered_set<int>s1) {
for (unordered_set<int>::iterator it = s1.begin(); it != s1.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
void printSet1(vector<int>s1) {
for (vector<int>::iterator it = s1.begin(); it != s1.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
class solution {
public:
vector<int>intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int>result_set;
unordered_set<int>num_set(nums1.begin(), nums1.end());
for (vector<int>::iterator it = nums2.begin(); it != nums2.end(); it++) {
if (num_set.find(*it) != num_set.end()) {
result_set.insert(*it);
}
}
return vector<int>(result_set.begin(), result_set.end());
}
};
void test1() {
solution s;
vector<int>v1{ 1,2,2,3,5,1 };
vector<int>v2{ 2,2,5,1 };
vector<int>result;
result=s.intersection(v1, v2);
printSet1(result);
}
int main() {
test1();
return 0;
}
运行窗口:
题目4.2-有效的字母异位词
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
输入: str1{ “anagram” };
string str2{ “nagaram” };
输出: 1
#include<iostream>
using namespace std;
#include<string>
class solution {
public:
bool isAnagram(string s, string t) {
int record[26] = { 0 };
for (int i = 0; i < s.size(); i++) {
record[s[i] - 'a']++;
}
for (int j = 0; j < t.size(); j++) {
record[s[j] - 'a']--;
}
for (int i = 0; i < 26; i++) {
if (record[i] != 0) {
return false;
}
}
return true;
}
};
void test1() {
solution s;
string str1{ "anagram" };
string str2{ "nagaram" };
bool result;
result=s.isAnagram(str1, str2);
cout << result << endl;
}
int main() {
test1();
return 0;
}
运行窗口:
题目4.3-快乐数
编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。如果 可以变为 1,那么这个数就是快乐数。
如果 n 是快乐数就返回 True ;不是,则返回 False 。
「示例:」
输入:19
输出:true
#include<iostream>
using namespace std;
#include<vector>
#include<unordered_set>
void printSet(unordered_set<int>s1) {
for (unordered_set<int>::iterator it = s1.begin(); it != s1.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
class solution {
public:
//获得各个位的和
int getSum(int num) {
int sum=0;
while (num) {
int i = num % 10;
sum += i * i;
num = num / 10;
}
return sum;
}
bool isHappu(int num) {
unordered_set<int>under_set;
while (1) {
int sum= getSum(num);
if (sum != 1){
if (under_set.find(sum) != under_set.end()) {
return false;
}
under_set.insert(sum);
num = sum;
continue;
}
return true;
}
}
};
void test1() {
solution s1;
int num1 = 19;
cout << s1.isHappu(num1) << endl;
}
int main() {
test1();
return 0;
}
运行窗口:
题目4.4-两数之和
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
「示例:」
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
#include<iostream>
using namespace std;
#include<vector>
#include<unordered_map>
void printVector(vector<int>s1) {
for (vector<int>::iterator it = s1.begin(); it != s1.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
class solution {
public:
//给定 nums = [2, 7, 11, 15], target = 9
//因为 nums[0] + nums[1] = 2 + 7 = 9
//所以返回[0, 1]
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int,int>map;
vector<int>a(2, 0);
for (int i = 0; i < nums.size(); i++) {
auto iter = map.find(target - nums[i]);
if (iter != map.end()) {
a[0] = i;
a[1] = iter->second;
return a;
}
map.insert(make_pair(nums[i], i));
}
return a;
}
};
void test1() {
solution s1;
vector<int>num{ 2,7,11,15 };
int target = 9;
vector<int>result;
result = s1.twoSum(num, target);
printVector(result);
}
int main() {
test1();
return 0;
}
运行窗口:
题目4.5-四数相加
[例如:]
输入: A = [ 1, 2] B = [-2,-1] C = [-1, 2] D = [ 0, 2]
输出: 2
[解释:]
两个元组如下:
(0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0
(1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0
#include<iostream>
using namespace std;
#include<vector>
#include<unordered_map>
class solution {
public:
int fourSumCount(vector<int>v1, vector<int>v2, vector<int>v3, vector<int>v4) {
unordered_map<int, int>unmap;
for (int a : v1) {
for (int b : v2) {
unmap[a + b]++;
}
}
int count = 0;
for (int c : v3) {
for (int d : v4) {
if (unmap.find(0 - (c + d)) != unmap.end()) {
count += unmap[0 - (c + d)];
}
}
}
return count;
}
};
void test1() {
solution s1;
vector<int>num{ 2,7,11,15 };
int target = 9;
vector<int>v1{1,2};
vector<int>v2{ -2,-1 };
vector<int>v3{ -1,2 };
vector<int>v4{ 0,2 };
cout <<"count="<< s1.fourSumCount(v1, v2, v3, v4) << endl;
}
int main() {
test1();
return 0;
}
题目4.6-赎金信
给定一个赎金信 (ransom) 字符串和一个杂志(magazine)字符串,判断第一个字符串 ransom 能不能由第二个字符串 magazines 里面的字符构成。如果可以构成,返回 true ;否则返回 false。
//给定一个赎金信(ransom) 字符串和一个杂志(magazine)字符串,
//判断第一个字符串 ransom 能不能由第二个字符串 magazines 里面的字符构成
//如果可以构成,返回 true ;否则返回 false。
#include<iostream>
using namespace std;
#include<string>
class solution {
public:
//method 1----暴力解
bool canConstruct1(string ransomNote, string magazine) {
for (int i = 0; i < magazine.size(); i++) {
for (int j = 0; j < ransomNote.size(); j++) {
if (magazine[i] == ransomNote[j]) {
//删除第j个元素
ransomNote.erase(ransomNote.begin()+j);
break;
}
}
}
if (ransomNote.size() == 0) {
return true;
}
return false;
}
//method 2-哈希解
bool canConstruct2(string ransomNote, string magazine) {
int record[26]{ 0 };
//记录magazine中各个字符出现的个数
for (int i = 0; i < magazine.size(); i++) {
record[magazine[i] - 'a']++;
}
for (int j = 0; j < ransomNote.size(); j++) {
record[ransomNote[j] - 'a']--;
if (record[ransomNote[j] - 'a'] < 0) {
return false;
}
}
return true;
}
};
void test1() {
solution s1;
string a1{ "fa" };
string a2{"aabd" };
cout << s1.canConstruct2(a1, a2);
}
int main() {
test1();
return 0;
}
第5章-双指针
题目5.1-四数之和
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:[ [-1, 0, 1], [-1, -1, 2] ]
#include<iostream>
using namespace std;
#include<vector>
#include<set>
#include<algorithm>
void printVector(vector<vector<int>>v1) {
for (auto iter = v1.begin(); iter != v1.end(); iter++) {
vector<int>tem_it = *iter;
for (auto it = tem_it.begin(); it != tem_it.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
}
class solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
sort(nums.begin(), nums.end());
//创建set容器防止组合重复
set<vector<int>>set1;
for (int i = 0; i < nums.size(); i++) {
int l = i + 1;
int r = nums.size() - 1;
while (l < r) {
if (nums[i] + nums[l] + nums[r] == 0) {
set1.insert({ nums[i], nums[l], nums[r] });
l++;
r--;
}
else if (nums[i] + nums[l] + nums[r] < 0) {
l++;
}
else {
r--;
}
}
}
vector<vector<int>>result(set1.begin(), set1.end());
return result;
}
};
void test1() {
solution s1;
vector<int>v1{ -1,0,1,2,-1,-1,-4 };
vector<vector<int>>result;
result = s1.threeSum(v1);
printVector(result);
}
int main() {
test1();
}
运行窗口:
题目5.2-移除元素
示例 1:
给定 nums = [3, 2, 2, 3], val = 3,
函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。
#include<vector>
#include<iostream>
using namespace std;
class solution {
public:
int removeElement(vector<int>&v1, int val) {
int slow = 0;
int fast ;
for (fast = 0; fast < v1.size(); fast++) {
if (v1[fast] == val) {
continue;
}
v1[slow++] = v1[fast];
}
return slow ;
}
};
void test1() {
vector<int>v1{ 0,1,2,2,3,0,4,2 };
solution s1;
cout <<"移除元素后的容器长度:"<< s1.removeElement(v1, 2) << endl;
}
int main() {
test1();
return 0;
}
运行窗口:
第6章-树与二叉树
题目6.1-深度优先遍历
题目6.1.1-中序遍历
中序遍历为:左中右
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
stack<TreeNode*>st;
vector<int>result;
TreeNode* cur=root;
while(cur!=NULL || !st.empty()){
if(cur!=NULL){
st.push(cur);
cur=cur->left;
}else{
cur=st.top();
result.push_back(cur->val);
st.pop();
cur=cur->right;
}
}
return result;
}
};
题目6.1.2-前序遍历
前序遍历为:中左右
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*>st;
vector<int>result;
st.push(root);
while(!st.empty()){
TreeNode* node=st.top();
st.pop();
if(node!=nullptr){
result.push_back(node->val);
}
else{
continue;
}
st.push(node->right);
st.push(node->left);
}
return result;
}
};
题目6.1.3-后序遍历
前序遍历为:左右中
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int>result;
stack<TreeNode*>st;
st.push(root);
while(!st.empty()){
TreeNode* cur=st.top();
st.pop();
if(cur!=nullptr){
result.push_back(cur->val);
}else{
continue;
}
st.push(cur->left);
st.push(cur->right);
}
reverse(result.begin(),result.end());
return result;
}
};
题目6.2-广度优先遍历
题目6.2.1-二叉树层的平均值
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<double> averageOfLevels(TreeNode* root) {
vector<double>result;
queue<TreeNode*>que;
if(root!=nullptr){que.push(root);}
while(!que.empty()){
int size=que.size();
double sum=0.0;
for(int i=0;i<size;i++){
TreeNode* node=que.front();
sum+=que.front()->val;
que.pop();
if(node->left){que.push(node->left);}
if(node->right){que.push(node->right);}
}
double aver=sum/size;
result.push_back(aver);
}
return result;
}
};
题目6.2.2-二叉树的层序遍历
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>>result;
queue<TreeNode*>que;
if(root!=NULL){
que.push(root);
}
while(!que.empty()){
int size=que.size();
vector<int>v1;
for(int i=0;i<size;i++){
TreeNode* node=que.front();
que.pop();
v1.push_back(node->val);
if(node->left){
que.push(node->left);
}
if(node->right){
que.push(node->right);
}
}
result.push_back(v1);
}
return result;
}
};
题目6.2.3-二叉树的层序遍历(2)
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<vector<int>> levelOrderBottom(TreeNode* root) {
queue<TreeNode*> que;
if (root != NULL) que.push(root);
vector<vector<int>> result;
while (!que.empty()) {
int size = que.size();
vector<int> vec;
// 这里一定要使用固定大小size,不要使用que.size(),因为que.size是不断变化的
for (int i = 0; i < size; i++) {
TreeNode* node = que.front();
que.pop();
vec.push_back(node->val);
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
result.push_back(vec);
}
reverse(result.begin(),result.end());
return result;
}
};
第7章-数组
题目7.1-在排序数组中查找元素的第一个和最后一个位置
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
示例 1:
输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]
#include<iostream>
using namespace std;
#include<vector>
class Solution {
public:
int firstLoaction(vector<int>&nums, int target) {
int left = 0;
int right = nums.size();
while (left < right) {
int middle = (left + right) / 2;
if (target < nums[middle]) {
right = middle;
}
else if (target > nums[middle]) {
left = middle + 1;
}
else {
right = middle;
}
}
//注意边界条件
if (left<nums.size() && target == nums[left]) { return left; }
else { return -1; }
}
int lastLocation(vector<int>&nums, int target) {
int left = 0;
int right = nums.size();
while (left < right) {
int middle = (left + right) / 2;
if (target < nums[middle]) {
right = middle;
}
else if (target > nums[middle]) {
left = middle + 1;
}
else {
left = middle + 1;
}
}
//
if (left-1>=0 && target == nums[left - 1]) { return left - 1; }
else { return -1; }
}
vector<int> searchRange(vector<int>& nums, int target) {
if (nums.size() == 0) { return vector<int>{-1, -1}; }
int first, last;
//查找开始位置
first = firstLoaction(nums, target);
//查找最后一个位置
last = lastLocation(nums, target);
if (first == -1 || last == -1) {
return vector<int>{-1, -1};
}
return vector<int>{first, last};
}
};
void test1() {
vector<int>num{2,2};
vector<int>result;
int target = 3;
Solution s1;
result=s1.searchRange(num, target);
}
int main() {
test1();
return 0;
}
题目7.2-长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
方法一:暴力解
#include<stdio.h>
#include<vector>
#include<iostream>
using namespace std;
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int length = INT_MAX;
int result;
for (int i = 0; i < nums.size(); i++) {
int sum =0;
int j;
result = 0;
if (sum >= target) { return 1; }
for (j = i ; j < nums.size(); j++) {
sum += nums[j];
result++;
if (sum >= target) {
length = (length > result ? result : length);
break;
}
else {
continue;
}
}
//if (j == nums.size()) { return 0; }
}
return length == INT_MAX ? 0 : length;
}
};
void test1() {
Solution s1;
vector<int>v1{ 1,1,1,1,7};
int length = s1.minSubArrayLen(7, v1);
cout << "length="<<length << endl;
}
int main() {
test1();
return 0;
}
方法二:滑动窗口
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int length = INT_MAX;
int left=0,right=0;
int sum=0;
int result;
for(;right<nums.size();right++){
sum+=nums[right];
while(sum>=target){
result=right-left+1;
length = (length > result ? result : length);
sum-=nums[left++];
}
}
return length == INT_MAX ? 0 : length;
}
};