Leetcode刷题总结和心得(3)

本文探讨了子序列与连续子序列的区别,介绍了动态规划的原理和滑动窗口的应用实例,以及如何使用哈希集合检测字符重复。内容涵盖了数据结构如set和vector的转换,map的使用,以及常见问题如栈、队列操作和错误修正。此外,还涉及字符串处理、单例模式、工厂模式、搜索算法、错误排查、数据结构与算法的基础概念和常见问题解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

90、概念区别

子序列,中间可以空开
连续子序列、子字符串,中间不能隔开

91、动态规划dp

本质:由前面的已知状态来推理出现在的状态来

92、滑动窗口

leetcode209
leetcode76
leetcode3
主要就是、、、无法言说!!!

93、判断是否有重复的字符

一种数据结构来判断是否有重复的字符,常用的数据结构为哈希集合(即 C++ 中的 std::unordered_set,Java 中的 HashSet,Python 中的 set, JavaScript 中的 Set)。
举例如下;
只需要o(1)的时间复杂度

unordered_set<char> repeat;
repeat.insert(a);

//进行判断有a吗,这种简单一些
if(repeat.count(a))  cout<<"里面有a"//或者,下面这样也行
if(repeat.find(a) != repeat.end())	cout<<"里面有a"

94、单词

英语汉语
dummyNode虚拟节点
pop弹出元素,砰的一声
“BFS(Breadth First Search)广度优先搜索
delimiter分隔符
traversal遍历

95、set到vector的转换

unordered_set<int> ans;
vector<int> ansFinal;
ansFinal.assign(ans.begin(), ans.end());//把ans的数值给ansFinal

注:set有自动去重功能,只有multiset才能有重复元素。

96、map的用法

unordered_map<int,int> hash;
        vector<int>ans;
        for(int i = 0; i < nums.size(); ++i){
            auto iter = hash.find(target - nums[i]);//map查找函数
            if(iter != hash.end())  return  {iter->second, i};//map的数值查询方法
            //hash[nums[i]] = i;//第一种map插入数据方法
            //hash.insert(pair<int, int>(nums[i], i));//第二种map插入数据方法
            hash.insert(make_pair(nums[i], i));//第三种map插入数据方法
        }

97、错误

1、粗心

while(left < right && nums[left] == nums[left + 1]) ++left;
while(left < right && nums[right] == nums[right - 1]) --right;//这里写成了--left

2、数值太大

nums[k] + nums[i] + nums[left] + nums[right] < target

改成下面这样

nums[k] + nums[i] > target - nums[left] - nums[right]

98、swap函数

vector<int> a;
swap(a[0], a[1]);//交换它俩的数值

另外,a的最右边一个元素为a[a.size() - 1]

交换指针也可以

TreeNode * a,b;
swap(a, b);

99、反转函数

reverse函数用于反转在[first,last)范围内的顺序(包括first指向的元素,不包括last指向的元素),reverse函数没有返回值

vector<int> v = {5,4,3,2,1};
reverse(v.begin(),v.begin() + 2);//v的值为4,5,3,2,1

100、push和push_back的区别

vector    	push_back,方向有的选,
list	 	push_back push_front
stack       push没得选
queue       push
set         insert
map         insert

101、栈和队列的基本操作

栈stack

push();从栈顶添加元素
pop();从栈顶移除第一个元素
top();返回栈顶元素
//size();返回栈的大小
empty();空返回true,否则返回false

队列queue

push();往队列中添加元素
pop();从队头移除第一个元素//不返回该数值
front();返回首元素
back();返回队尾元素
size();返回栈的大小
empty();空返回true,否则返回false

102、概念

单调栈:一种解题方法,栈内的元素保持单调
优先队列:一种数据结构,用堆来实现,priority_queue
双端队列(双端数组):一种数据结构,deque

103、stoi

string a = "1";
cout<<stoi(a)<<endl;//将a从字符转变成为数字

注意a不能为空和“bf”之类的字符,不然会报错

104、数据结构

数组、字符串、链表、哈希表、栈、队列、树

105、良好代码的形式

1、变量命名规范
2、耦合度要低,能独立的功能尽量独立函数编写。

106、leetcode94二叉树中序遍历,统一迭代法的执行流程

请添加图片描述

107、错误

vector<int> ans;

//ans.push(st.top() -> val);//这样不行
ans.push_back(st.top() -> val);

108、节点定义

链表节点

struct ListNode {
    int val;
    ListNode* next;
    ListNode(int val) :val(val), next(nullptr) {}
};

二叉树的节点

struct TreeNode {
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int val) :val(val), left(nullptr), right(nullptr) {}
};

109、反转

反转字符串
反转链表
反转二叉树

110、红黑树

红黑树:自平衡二叉查找树
平衡二叉树:左右高度数值小于等于1
二叉查找树:左子树上的所有节点都小于根节点的数值,右子树的所有节点都大于根节点的数值。

111、to_string

数字编程字符串函数

to_string(1);//数字1,变成了字符‘1’

112、构造二叉树

一、普通树
前序和中序
后序和中序
但是前序和后序不可以
二、二叉搜索树
只需要一个递增数组从中间开始分就行了

113、二叉搜索树的特点

用中序遍历的时候,数字是从小到大的

114、红黑树

平衡二叉搜索树(avl)
红黑树(RB-tree)

115、随想

链表的结构要存储结构体对象就会出现麻烦,因此需要用模板,泛型编程的思想。

另外,
数组,查询效率超级高,但是删除和插入很费劲;
链表,查询不行,但是删除和插入很不错;
树,上面俩的综合体,所有现在这个最常用。

116、测试

单元测试: 又称模块测试,是针对软件设计的最小单位——程序模块进行正确性检验的测试工作。其目的在于检查每个程序单元能否正确实现详细设计说明中的模块功能、性能、接口和设计约束等要求,发现各模块内部可能存在的各种错误。单元测试需要从程序的内部结构出发设计测试用例。多个模块可以平行地独立进行单元测试

集成测试: 也叫做组装测试。通常在单元测试的基础上,将所有的程序模块进行有序的、递增的测试。集成测试是检验程序单元或部件的接口关系,逐步集成为符合概要设计要求的程序部件或整个系统

确认测试: 也叫有效性测试。是在模拟的环境下,验证软件的所有功能和性能及其他特性是否与用户的预期要求一致。通过了确认测试之后的软件,才具备了进入系统测试阶段的资质

系统测试: 是在真实的系统运行的环境下,检查完整的程序系统能否和系统(包括硬件、外设、网络和系统软件、支持平台等)正确配置、连接,并最终满足用户的所有需求

验收测试: 是软件产品检验的最后一个环节。按照项目任务书或合同、供需双方约定的验收依据文档进行的对整个系统的测试与评审,决定是否接收或拒收系统。

117、二维数组为空判断

if(matrix.empty() || matrix[0].size() == 0)  return false;
//分别对应{} || {{}}的情况

c++中二维数组是连续存储的

118、错误

改了1个小时、日了,不过学会了用vs进行调试

while (p1 != p2) {
            if (s[p1] != ' ')    s[p2--] = s[p1--];
            else {
                p1--;
                s[p2--] = '0';//日了,写成了这样s[p2--] == '0';
                s[p2--] = '2';
                s[p2--] = '%';
            }
        }

119、单例模式

懒汉式,需要的时候才调用类内部的getInstance()函数来创造实例。并且因为static静态的,所以创建过一次就不会在创建了。

//Singleton.cpp
#include<iostream>
#include<mutex>//锁的头文件
using namespace std;
class Singleton {
public:
    static Singleton* getInstance() {
        static Singleton* singeltonInstance;//函数内的静态变量,声明加定义,已分配空间。
        cout << "getInstance in singleton." << endl;
//线程安全
        //if(singeltonInstance == NULL){
        //  singletonLock.lock();//线程安全
            if (singeltonInstance == NULL)
              singeltonInstance = new Singleton();
       //   singletonLock.unlock();
       //}
        return singeltonInstance;
    };
private:  
    Singleton() {
        cout << "Construct in singleton." << endl;
    }   
};

下面是饿汉子式,直接就预先创建一个实例

class Singleton;
class Singleton {
private:
    Singleton() {};//构造函数私有化
    Singleton(Singleton &s) {}; //拷贝构造私有化
    Singleton& operator=(const Singleton& s) {};
    static Singleton* singletonInstance;
public:
    static Singleton* getInstance() {
        return singletonInstance;
    }
};
//......
Singleton* Singleton::singletonInstance = new Singleton();//全局实例化

120、工厂模式

下午再看
简单工厂模式

121、bug

grid[x][y+1] == '(' ? 1 : -1;
grid[x][y+1] == '(' ? 1-1;//中文的冒号,日了,看了好久才看出来的

122、数字太大取余数的方法

1、ans = (ans * tmp)  % (1000000007);
2、dp[i] = (dp[i - 1] + dp[i - 2]) % 1000000007;
3、dp[i]=((dp[i-1]+dp[i-2])%1000000007+dp[i-3])%1000000007;

123、变量命名

不能和函数重名,可以和类重名;

int min = INT_MAX;
for(auto n : numbers)   min = min(min, n);//这样就不行

124、二分查找

class Solution {
public:

//左闭右闭和左闭右开的写法
    int search(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size() - 1;
        //int right = nums.size();

        while(left <= right){//while(left < right)
            int mid = left + (right - left)/2;
            if(nums[mid] == target) return  mid;
            else if(nums[mid] < target) left = mid + 1;
                else right = mid - 1;//right = mid;
        }

        return -1;
    }
};

125、回溯的细节

bool backTracking(){       
        wordLength += 1;//区别这里
        backTracking( wordLength)//区别这里                        
        --wordLength;//区别这里
    }
bool backTracking(){      
        backTracking(wordLength + 1)//区别这里                        
    }

这两种都可以,但是要注意意义对应啊。

126、数据长度超限制

//下面这个在数据很大的时候肯定报错

int frontSum;
 frontSum = accumulate(nums.begin(), nums.begin() + 1, 0LL);

改成这样就好了

 long long frontSum;//这里也要要再看看
 frontSum = accumulate(nums.begin(), nums.begin() + 1, 0LL);//这里也要改,注意最后的0LL

127、字符串转整数

 string s = to_string(num);
 int x = stoi(s.substr(i, k));

128、整数转字符串

int num;
string s = to_string(num);

129、数字变成字符串的处理

	int number = 12345678;
    string str1;

    //将整数转换成了字符串
    str1 = to_string(number);
    cout << str1[5];//输出结果为6

130、字符变成数字

int main() {  
    char ch = { '9' };
    int sum1 = 0 + ch;
    cout << sum1;//输出结果为57,此时为字符9

    int sum2 = 0 + ch - '0';
    cout << sum2;//输出结果为9,此时为数字9
   
    return 0;
}

131、求三个数的最大值

dp[i] = max({dp[i], j * (i - j), j * dp[i - j]});//c++11中的新特性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值