1、中序遍历前序遍历
2、递归算法的本质:
3、数组删除元素
暴力法:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int size = nums.size();
for (int i = 0; i < size; i++) {
if (nums[i] == val) { // 发现需要移除的元素,就将数组集体向前移动一位
for (int j = i + 1; j < size; j++) {
nums[j - 1] = nums[j];
}
i--; // 因为下标i以后的数值都向前移动了一位,所以i也向前移动一位
size--; // 此时数组的大小-1
}
}
return size;
}
};
双指针法:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slowIndex = 0;
for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {
if (val != nums[fastIndex]) {
nums[slowIndex++] = nums[fastIndex];
}
}
return slowIndex;
}
};
4、俩数之和(使用map表做的映射)
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
std::unordered_map <int,int> map;
for(int i = 0; i < nums.size(); i++) {
// 遍历当前元素,并在map中寻找是否有匹配的key
auto iter = map.find(target - nums[i]);
if(iter != map.end()) {
return {iter->second, i};
}
// 如果没找到匹配对,就把访问过的元素和下标加入到map中
map.insert(pair<int, int>(nums[i], i));
}
return {};
}
};
5、双指针法解决三数之和
什么时候使用哈希表呢。当我们要判断这个元素是否出现过,或者是判断这个元素是否再这个集合里面出现过的时候
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> result;
sort(nums.begin(), nums.end());
// 找出a + b + c = 0
// a = nums[i], b = nums[left], c = nums[right]
for (int i = 0; i < nums.size(); i++) {
// 排序之后如果第一个元素已经大于零,那么无论如何组合都不可能凑成三元组,直接返回结果就可以了
if (nums[i] > 0) {
return result;
}
// 错误去重a方法,将会漏掉-1,-1,2 这种情况
/*
if (nums[i] == nums[i + 1]) {
continue;
}
*/
// 正确去重a方法
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
int left = i + 1;
int right = nums.size() - 1;
while (right > left) {
// 去重复逻辑如果放在这里,0,0,0 的情况,可能直接导致 right<=left 了,从而漏掉了 0,0,0 这种三元组
/*
while (right > left && nums[right] == nums[right - 1]) right--;
while (right > left && nums[left] == nums[left + 1]) left++;
*/
if (nums[i] + nums[left] + nums[right] > 0) right--;
else if (nums[i] + nums[left] + nums[right] < 0) left++;
else {
result.push_back(vector<int>{nums[i], nums[left], nums[right]});
// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重
while (right > left && nums[right] == nums[right - 1]) right--;
while (right > left && nums[left] == nums[left + 1]) left++;
// 找到答案时,双指针同时收缩
right--;
left++;
}
}
}
return result;
}
};
6、合并俩个有序链表
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param pHead1 ListNode类
* @param pHead2 ListNode类
* @return ListNode类
*/
ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
// write code here
if (!pHead1) {
return pHead2;
}
if (!pHead2) {
return pHead1;
}
ListNode* mergedHead;
if (pHead1->val < pHead2->val) {
mergedHead = pHead1;
mergedHead->next = Merge(pHead1->next, pHead2);
} else {
mergedHead = pHead2;
mergedHead->next = Merge(pHead1, pHead2->next);
}
return mergedHead;
}
};
非递归法:
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
ListNode dummy(0); // 创建一个虚拟头节点
ListNode* current = &dummy; // 当前节点指针,初始化为虚拟头节点
while (pHead1 && pHead2) {
if (pHead1->val < pHead2->val) {
current->next = pHead1;
pHead1 = pHead1->next;
} else {
current->next = pHead2;
pHead2 = pHead2->next;
}
current = current->next;
}
// 处理剩余的节点
if (pHead1) {
current->next = pHead1;
} else {
current->next = pHead2;
}
return dummy.next; // 返回合并后的链表的真正头节点
}
};
7、数组右移K位
#include <iostream>
using namespace std;
void reverse(int left, int right, int* x) {
while (left < right) {
int tmp = x[left];
x[left] = x[right];
x[right] = tmp;
left++;
right--;
}
}
int main() {
int n, m, num;
while (cin >> m >> n) {
int* x = new int[m];
for (int i = 0; i < m; i++) {
cin >> num;
x[i] = num;
}
reverse(0, m - 1, x);
reverse(0, n - 1, x);
reverse(n, m - 1, x);
for (int i = 0; i < m; i++) {
cout << x[i] <<" ";
}
delete[] x;
}
return 0;
}
8、回溯算法求子集
思路:使用回溯算法,在合适的地方弹栈,
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
vector<int> nums;
int n;
vector<int> path;
vector<vector<int>> res;
vector<vector<int>> subsets(vector<int>& nums) {
this->nums = nums;
this->n = nums.size();
backtrace(0);
return res;
}
void backtrace(int idx) {
res.push_back(path);
for(int i=idx;i<n;i++){
path.push_back(nums[i]);
backtrace(i+1);
path.pop_back();
}
}
};
int main() {
vector<int> nums = {1,2,3};
Solution solution;
vector<vector<int>> subsets = solution.subsets(nums);
cout << "All subsets:" << endl;
for (const vector<int>& subset : subsets) {
cout << "[";
for (int num : subset) {
cout << num << " ";
}
cout << "]" << endl;
}
return 0;
}
9、全排列
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking (vector<int>& nums, vector<bool>& used) {
// 此时说明找到了一组
if (path.size() == nums.size()) {
result.push_back(path);
return;?
}
for (int i = 0; i < nums.size(); i++) {
if (used[i] == true) continue; // path里已经收录的元素,直接跳过
used[i]= true;
path.push_back(nums[i]);
backtracking(nums, used);
path.pop_back();
used[i] = false;
}
}
vector<vector<int>> permute(vector<int>& nums) {
result.clear();
path.clear();
vector<bool> used(nums.size(), false);
backtracking(nums, used);
return result;
}
};