文章目录
前言
《代码随想录》算法公开课代码合集
数组
二分查找
#include <iostream>
#include <string>
#include<vector>
using namespace std;
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0 ;
int right = nums.size() -1;
while (left<=right){
int mid = (right+left)/2;
if (target == nums[mid]){
return mid;
}
else if (target > nums[mid]){
left = mid +1;
}
else{
right = mid -1;
}
}
return -1;
}
};
int main(void){
Solution s1;
int num[5]={1,3,5,6,10};
int target = 1;
vector<int> a(num,num+5);
int result = s1.search(a,target);
cout<<result<<endl;
}
移除元素
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int count = 0;
int x = 0;
// vector<int> t(nums);
for (int i =0;i<nums.size();i++){
if (val != nums[i]){
nums[x]=nums[i];
count +=1;
x+=1;
}
}
return count;
}
};
有序数组的平方
简单的快排
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
vector<int> ans;
for (int num: nums) {
ans.push_back(num * num);
}
sort(ans.begin(), ans.end());
return ans;
}
};
双指针方法
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int n = nums.size();
vector<int> a(n);
int pos = n -1;
for (int i=0, j = n - 1;i<=j; ){
if (nums[i]*nums[i]<nums[j]*nums[j]){
a[pos]=nums[j]*nums[j];
j--;
}
else{
a[pos]= nums[i]*nums[i];
i++;
}
pos --;
}
return a;
}
};
长度最小的子数组
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int n = nums.size();
int ans = INT_MAX;
int start = 0, end = 0;
int sum = 0;
while(end<n){
sum += nums[end];
while (sum >= target){
ans =min (ans,end-start+1);
sum -=nums[start];
start ++;
}
end ++;
}
return ans == INT_MAX ? 0:ans;
}
};
旋转矩阵
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> mat(n,vector<int>(n,1));
int tar = n*n;
int num=1;
int l = 0,r= n-1,t=0,b=n-1;
while (num<=tar){
for (int i = l;i<=r;i++){
mat[t][i]=num;
num ++;
}
t++;
for (int j = t;j<=b;j++ ){
mat[j][r]=num;
num +=1;
}
r--;
for(int i =r;i>=l;i--){
mat[b][i]=num;
num ++;
}
b-=1;
for(int j = b;j>= t;j--){
mat[j][l]=num;
num +=1;
}
l+=1;
}
return mat;
}
};
链表
移除链表元素
struct ListNode{
int val;
ListNode *next;
ListNode(): val(0),next(nullptr){};
ListNode(int x ): val(x),next(nullptr){};
ListNode(int x , ListNode *next ): val(x),next(next){};
};
ListNode* createList(const std::vector<int>& values){
ListNode* head = new ListNode(0);
ListNode* current = head;
for (int val :values){
current->next = new ListNode(val);
current = current->next;
}
return head->next;
}
void printList(ListNode* head){
while(head != nullptr){
std::cout<< head->val << "->";
head = head -> next;
}
std::cout <<"nullptr\n";
}
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
struct ListNode* dummyHead = new ListNode(0,head);
struct ListNode* temp = dummyHead;
while (temp->next !=nullptr){
if(temp->next->val == val){
temp->next = temp-> next->next;
}
else{
temp = temp ->next;
}
}
return dummyHead->next;
}
};
int main(void){
ListNode* list = createList({1,2,6,3,4,5,6});
Solution solution;
ListNode* newList = solution.removeElements(list,6);
printList(newList);
ListNode* current = list;
while (current != nullptr)
{
ListNode* next = current ->next;
delete current;
current = next;
}
printList(list);
return 0 ;
}
设计链表
class MyLinkedList {
public:
MyLinkedList() {
this -> size = 0;
this -> head = new ListNode(0);
}
int get(int index) {
if (index < 0 || index >= size){
return -1;
}
ListNode* cur = head;
for (int i = 0;i<=index;i++){
cur = cur->next;
}
return cur->val;
}
void addAtHead(int val) {
addAtIndex(0,val);
}
void addAtTail(int val) {
addAtIndex(size,val);
}
void addAtIndex(int index, int val) {
if (index > size ){
return;
}
index =max (0,index);
size++;
ListNode *pred = head;
for (int i = 0;i<index;i++){
pred =pred->next;
}
ListNode* toAdd =new ListNode(val);
toAdd->next = pred->next;
pred->next = toAdd;
}
void deleteAtIndex(int index) {
if (index < 0 || index>= size){
return;
}
size --;
ListNode* pred = head;
for(int i = 0;i<index;i++){
pred = pred->next;
}
ListNode* p = pred ->next;
pred->next = pred->next->next;
delete p;
}
private:
int size;
ListNode* head;
};
/**
* Your MyLinkedList object will be instantiated and called as such:
* MyLinkedList* obj = new MyLinkedList();
* int param_1 = obj->get(index);
* obj->addAtHead(val);
* obj->addAtTail(val);
* obj->addAtIndex(index,val);
* obj->deleteAtIndex(index);
*/
反转链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode *cur = head;
ListNode *pre = nullptr;
while(cur != nullptr) {
ListNode* tmp = cur->next; // 暂存后继节点 cur.next
cur->next = pre; // 修改 next 引用指向
pre = cur; // pre 暂存 cur
cur = tmp; // cur 访问下一节点
}
return pre;
}
};
两两交换链表中的节点
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* dummyHead =new ListNode(0);
dummyHead->next =head;
ListNode* cur = dummyHead;
while (cur->next != nullptr && cur->next->next != nullptr){
ListNode* node1 = cur->next;
ListNode* node2 = cur->next->next->next;
cur->next = cur->next->next;
cur->next->next = node1;
node1->next = node2;
cur= cur->next->next;
}
ListNode* reslut = dummyHead->next;
delete dummyHead;
return reslut;
}
};
删除链表的倒数第N个节点
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyhead = new ListNode(0);
dummyhead->next = head;
ListNode* fast = dummyhead;
ListNode* slow = dummyhead;
// int fast = n;
// int slow = 0;
for (int i = 0;i<n+1;i++){
fast=fast->next;
}
while(fast != nullptr){
fast=fast->next;
slow=slow->next;
}
slow->next = slow->next->next;
return dummyhead->next;
}
};
环形链表II
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *fast = head;
ListNode *slow = head;
while (fast != NULL && fast->next != NULL){
fast = fast->next->next;
slow = slow->next;
if (fast == slow){
ListNode *index1 =fast;
ListNode *index2 = head;
while(index1 != index2){
index1=index1->next;
index2=index2->next;
};
return index1;
}
}
return NULL;
}
};
哈希表
有效的字母异位词
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 i = 0; i < t.size(); i++) {
record[t[i] - 'a']--;
}
for (int i = 0; i < 26; i++) {
if (record[i] != 0) {
return false;
}
}
return true;
}
};
两个数组的交集
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
std::unordered_set<int> result_set;
std::unordered_set<int> nums_set(nums1.begin(), nums1.end());
for (int num : nums2) {
if (nums_set.find(num) != nums_set.end()) {
result_set.insert(num);
}
}
vector<int> a(result_set.begin(), result_set.end());
return a;
}
};
快乐数
class Solution {
public:
int getSum(int n) {
int sum = 0;
while (n) {
sum += (n % 10) * (n % 10);
n = n / 10;
}
return sum;
};
bool isHappy(int n) {
std::unordered_set<int> re_set;
while (1) {
int sum = getSum(n);
if (re_set.find(sum) != re_set.end()) {
return false;
}
re_set.insert(sum);
if (sum == 1) {
return true;
}
n = sum;
}
}
};
两数之和
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++) {
auto iter = map.find(target - nums[i]);
// std::unordered_map<int, int>::iterator iter = map.find(target - nums[i]);
if (iter != map.end()) {
return {iter->second, i};
}
map.insert(std::pair<int, int>(nums[i], i));
}
return {};
}
};
四数相加II
#include <vector>
#include <unordered_map>
#include <iostream>
class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
std::unordered_map<int, int> map1;
std::unordered_map<int, int> map2;
int count = 0;
// 计算 nums1 和 nums2 的和的频率
for (int i = 0; i < nums1.size(); i++) {
for (int j = 0; j < nums2.size(); j++) {
map1[nums1[i] + nums2[j]]++;
}
}
// 计算 nums3 和 nums4 的和的频率
for (int i = 0; i < nums3.size(); i++) {
for (int j = 0; j < nums4.size(); j++) {
map2[nums3[i] + nums4[j]]++;
}
}
// 遍历 map1,查找在 map2 中对应的负数和的频率,并计算总数
for (auto it = map1.begin(); it != map1.end(); ++it) {
int c = it->first;
if (map2.find(0 - c) != map2.end()) {
count += it->second * map2[-c];
}
}
return count;
}
};
// 主函数用于测试
int main() {
Solution sol;
vector<int> nums1 = {1, 2};
vector<int> nums2 = {-2, -1};
vector<int> nums3 = {-1, 2};
vector<int> nums4 = {-2, 2};
int count = sol.fourSumCount(nums1, nums2, nums3, nums4);
std::cout << "Count: " << count << std::endl;
return 0;
}
三数之和
双指针解法
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> result;
sort(nums.begin(), nums.end());
for (int i = 0; i < nums.size(); i++) {
if (nums[0] > 0) {
return result;
}
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
int left = i + 1;
int right = nums.size() - 1;
while (right > 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]});
while (right > left && nums[right] == nums[right - 1])
right--;
while (right > left && nums[left] == nums[left + 1])
left++;
right--;
left++;
}
}
}
return result;
}
};
四数之和
双指针法
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> result;
sort(nums.begin(), nums.end());
for (int k = 0; k < nums.size(); k++) {
if (nums[k] > target && nums[k] >= 0) {
break;
}
if (k > 0 && nums[k] == nums[k - 1]) {
continue;
}
for (int i = k + 1; i < nums.size(); i++) {
if (nums[k] + nums[i] > target && nums[k] + nums[i] >= 0) {
break;
}
if (i > k + 1 && nums[i] == nums[i - 1]) {
continue;
}
int left = i + 1;
int right = nums.size() - 1;
while (right > left) {
if ((long)nums[k] + nums[i] + nums[left] + nums[right] >
target) {
right--;
} else if ((long)nums[k] + nums[i] + nums[left] +
nums[right] <
target) {
left++;
} else {
result.push_back(vector<int>{nums[k], nums[i],
nums[left], nums[right]});
while (right > left && nums[right] == nums[right - 1])
right--;
while (right > left && nums[left] == nums[left + 1])
left++;
right--;
left++;
}
}
}
}
return result;
}
};
字符串
反转字符串
在反转链表中,使用了双指针的方法。那么反转字符串依然是使用双指针
的方法,只不过对于字符串的反转,其实要比链表简单一些。
class Solution {
public:
void reverseString(vector<char>& s) {
for (int i = 0, j = s.size() - 1; i < s.size() / 2; i++, j--) {
swap(s[i], s[j]);
}
}
};
class Solution {
public:
void reverseString(vector<char>& s) {
std::reverse(s.begin(),s.end());
}
};
反转字符串 II
begin()相当于0,end()相当于size,end()返回的自然是最后一个节点的后一个节点,begin() == end()可以直接判空。
class Solution {
public:
string reverseStr(string s, int k) {
for (int i = 0; i < s.size(); i += (2 * k)) {
if (i + k <= s.size()) {
reverse(s.begin() + i, s.begin() + i + k);
} else {
reverse(s.begin() + i, s.end());
}
}
return s;
}
};
替换数字
其实很多数组填充类的问题,其做法都是先预先给数组扩容
待填充后的大小,然后在从后向前
进行操作。
#include <iostream>
using namespace std;
int main(){
string s;
string n = "number";
while (cin >> s){
int sOldIndex = s.size() - 1;
int count = 0;
for (int i =0;i<s.size();i++){
if(s[i]>='0' && s[i] <='9'){
count ++;
}
}
s.resize(s.size() + count*5);
int sNewIndex = s.size() -1;
while (sOldIndex >= 0){
if(s[sOldIndex]>='0'&&s[sOldIndex]<='9'){
for(int j = 5;j>=0;j--){
s[sNewIndex]=n[j];
sNewIndex--;
}
}
else{
s[sNewIndex]=s[sOldIndex];
sNewIndex --;
}
sOldIndex --;
}
cout<<s<<endl;
}
}
测试:echo “a1aaaa” | ./test
翻转字符串里的单词
先全部翻转,然后每个单词再翻转
class Solution {
public:
string reverseWords(string s) {
std::reverse(s.begin(), s.end());
int n = s.size();
int idx = 0;
for (int start = 0; start < n; start++) {
if (s[start] != ' ') {
if (idx != 0)
s[idx++] = ' ';
int end = start;
while (end < n && s[end] != ' ') {
s[idx++] = s[end++];
}
reverse(s.begin() + idx - (end - start), s.begin() + idx);
start = end;
}
}
s.erase(s.begin() + idx, s.end());
return s;
}
};
右旋字符串
#include <iostream>
#include <algorithm>
using namespace std;
int main(){
int n;
std::string s;
cin >> s;
cin >> n;
std::reverse(s.begin(),s.end());
std::reverse(s.begin(),s.begin()+n);
std::reverse(s.begin()+n,s.end());
cout <<s<<endl;
}
实现 strStr()
KMP算法,找匹配项
构建前缀表,即 next表
class Solution {
public:
void getNext(int* next, const string& s) {
int j = 0;
next[0] = 0;
for (int i = 1; i < s.size(); i++) {
while (j > 0 && s[i] != s[j]) {
j = next[j - 1];
}
if (s[i] == s[j]) {
j++;
}
next[i] = j;
}
}
int strStr(string haystack, string needle) {
if (needle.size() == 0) {
return 0;
}
vector<int> next(needle.size());
getNext(&next[0], needle);
int j = 0;
for (int i = 0; i < haystack.size(); i++) {
while (j > 0 && haystack[i] != needle[j]) {
j = next[j - 1];
}
if (haystack[i] == needle[j]) {
j++;
}
if (j == needle.size()) {
return (i - needle.size() + 1);
}
}
return -1;
}
};
重复的子字符串
class Solution {
public:
bool repeatedSubstringPattern(string s) {
int n = s.size();
for (int i = 1; i * 2 <= n; i++) {
if (n % i == 0) {
bool match = true;
for (int j = i; j < n; j++) {
if (s[j] != s[j - i]) {
match = false;
break;
}
}
if (match) {
return true;
}
}
}
return false;
}
};
栈和队列
用栈实现队列
class MyQueue {
public:
stack<int> stIn;
stack<int> stOut;
MyQueue() {}
void push(int x) { stIn.push(x); }
int pop() {
if (stOut.empty()) {
while (!stIn.empty()) {
stOut.push(stIn.top());
stIn.pop();
}
}
int result = stOut.top();
stOut.pop();
return result;
}
int peek() {
int res = this->pop();
stOut.push(res);
return res;
}
bool empty() { return stIn.empty() && stOut.empty(); }
};
用队列实现栈
class MyStack {
public:
queue<int> que;
MyStack() {}
void push(int x) { que.push(x); }
int pop() {
int size = que.size();
size--;
while (size > 0) {
int fronti = que.front();
que.pop();
que.push(fronti);
size--;
}
int result = que.front();
que.pop();
return result;
}
int top() {
int size = que.size();
size--;
while (size--) {
que.push(que.front());
que.pop();
}
int result = que.front();
que.push(que.front());
que.pop();
return result;
}
bool empty() { return que.empty(); }
};
有效的括号
由于栈结构的特殊性,非常适合做对称匹配类的题目。
class Solution {
public:
bool isValid(string s) {
if (s.size() % 2 != 0) {
return false;
}
stack<char> st;
for (int i = 0; i < s.size(); i++) {
if (s[i] == '(')
st.push(')');
else if (s[i] == '{')
st.push('}');
else if (s[i] == '[')
st.push(']');
else if (st.empty() || st.top() != s[i])
return false;
else
st.pop();
}
return st.empty();
}
};
删除字符串中的所有相邻重复项
class Solution {
public:
string removeDuplicates(string s) {
stack<char> st;
for (char cs : s) {
if (st.empty() || st.top() != cs) {
st.push(cs);
} else {
st.pop();
}
}
string result = "";
while (!st.empty()) {
result.push_back(st.top());
st.pop();
}
std::reverse(result.begin(), result.end());
return result;
}
};
逆波兰表达式求值
class Solution {
public:
int evalRPN(vector<string>& tokens) {
stack<long long> st;
for (int i = 0; i < tokens.size(); i++) {
if (tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" ||
tokens[i] == "/") {
long long num1 = st.top();
st.pop();
long long num2 = st.top();
st.pop();
if (tokens[i] == "+")
st.push(num2 + num1);
if (tokens[i] == "-")
st.push(num2 - num1);
if (tokens[i] == "*")
st.push(num2 * num1);
if (tokens[i] == "/")
st.push(num2 / num1);
} else {
st.push(stoll(tokens[i]));
}
}
int result = st.top();
st.pop();
return result;
}
};
滑动窗口最大值
class Solution {
private:
class MyQueue {
public:
deque<int> que;
void pop(int value) {
if (!que.empty() && value == que.front()) {
que.pop_front();
}
}
void push(int value) {
while (!que.empty() && value > que.back()) {
que.pop_back();
}
que.push_back(value);
}
int front() { return que.front(); }
};
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
MyQueue que;
vector<int> result;
for (int i = 0; i < k; i++) {
que.push(nums[i]);
}
result.push_back(que.front());
for (int i = k; i < nums.size(); i++) {
que.pop(nums[i - k]);
que.push(nums[i]);
result.push_back(que.front());
}
return result;
}
};
前 K 个高频元素
总结
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。