数据结构与算法

数据结构-算法题(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;
    }
};

第8章-图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alex1_Code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值