从0开始C++

非科班双非硕的C++学习经历,期望大佬给出一点意见和建议,我全盘接收。
日常记录向,与自我监督。
 

12.12记录
 

leetcode:53.最大子数组和(侵删)

题目:

所用语言C++;

方法1:暴力求解

整体思路:1.使用双指针遍历所有子集
                  2.在每次遍历中去确定其是否为最大值

缺点:时间复杂度较高,达到O(n2)

代码:

int sum,maxans;
for (int i=0;i<nums.size();i++){
    int sum = 0;//每次外部循环都需要更新sum,来确保其是连续子集
    for (int j=i;j<nums.size();j++){//注意j要从i处开始
        sum+=nums[i];
        maxans=max(sum,maxans);
    }
}
return maxans;

方法2:动态规划

整体思路:1.遍历一遍,每次判断之前子集pre和与当前值的大小
                  2.每次判断完成后,都将子集pre进行更新
                  3.将pre与max进行对比更新

时间复杂度为o(n)

代码:(写法1)

int pre=nums[0],maxans=nums[0];//确定初始值,不可设为0,因为不确定第一个值是否小于0
for (int i=1;i<nums.size();i++){
    pre=max(pre,pre+nums[i]);//获取当前连续子集中较大的一个
    maxans=max(pre,maxans);//获取连续子集中最大的一个
}
return maxans;

(写法2)(使用双目运算符,判定前一子集pre是否小于0,小于0且与当前元素相加一定使相加子集小于当前元素)

int pre=nums[0],maxans=nums[0];
for (int i=1;i<nums.sizeof();i++){
    (pre<0) ? nums[i]:pre+nums[i];
    maxans=max(pre,maxans);
}
return maxans;

12.13记录

leetcode: 49 字母异位词分组

题目:(侵删)

大意为:将字符数组之内每个元素中含有相同数量,且相同字母的元素置于同一组内,并输出

核心思想:构建哈希表,key为按ascII排列的字母(元素中含有的),value为有且只有这些字母的元素组合的数组。

时间复杂度:O(nk)

代码:

//构建输出
vector<vector<string>> ans;
//构建哈希表
unordered_map <string,vector<string>> occ;
//此处也可以直接使用auto s:strs
for (int i=0;i<strs.sizeof();i++){
    string key = strs[i];
    //sort()内参数只接受范围不能接受变量
    sort(key.begin(),key.end());
    occ[key].emplace_back(strs[i]);
for (auto j:occ){
//此处的j为occ内的键值对
    ans.emplace_back(j.second)
}
//此处遍历还可以使用另一种形式,但含义都相同:
/*
此处的i类似于指针
for (auto i=occ.begin();i<occ.end();i++){
    ans.emplace_back(i->second);
}
*/
return ans;

12.16记录

leetcode:73矩阵置零

方法一:

解题思路:将零投影到边界上,因此存在有两个模块。1.在边界上的零(第一行与第一列) ,2.在内部的零。
先确定边界是否有零,运用bool类型变量,有则标记为true,无则为false
其次将内部的零投影到边界上,将对应边界位置上的值用0替代
在去除边界的内部,将含有零的行列值全部置为零
再将为true的边界全部置为0

缺点:繁琐,时间复杂度较大,但是能通过

代码:

//确定matrix的行数与列数:
int m=matrix.size(), n=matrix[0].size();
//定义bool类型确定初始行列是否有0:
bool row_zero=false, column_zero=false;
//遍历数组寻找0
for (int i=0; i<m; i++){
    for (int j=0; j<n; j++){
        if (matrix[i][j]==0){
            //i等于0,则为第一行存在0
            //j等于0,则为第一列存在0
            if (i==0) row_zero=true;
            if (j==0) column_zero=true;
            matrix[i][0]=matrix[0][j]=0;
        }
    }
}
//将边界存在0的行列识别,并将内部全置为0
for (int i=1; i<m; i++){
    for (int j=1; j<n; j++){
        if (matrix[i][0]==0||matrix[0][j]==0){
            matrix[i][j]=0;
        }
    }
}
//判断边界是否为true,遍历列时则需要明确row是否为0,是则将边界第一行全置为0
for (int i=0; i<m && column_zero; i++) matrix[i][0]=0;
for (int j=0; j<n && row_zero; j++) matrix[0][j]=0;

方法二:

方法类似于方法一,不过省去内外部分类,直接用vector类型替代,关键点用:vector<int> row(m),col(n);

代码:

int m=matrix.size(),n=matrix[0].size();
//用row和col来记录存在0的行列.
//只要行列有一个为true,在后续遍历中,就可以置为0
vector<int> row(m),col(n);
for (int i=0; i<m; i++){
    for (int j=0; j<n; j++){
        if (matrix[i][j]==0){
            row(i)=true;
            col(j)=true;
        }
    }
}
for (int i=0; i<m; i++){
    for (int j=0; j<n; j++){
        if (row(i)||col(j)){
            matrix[i][j]=0;
        }
    }
}

方法三:

解题思路:用两个表分别存储值为0的行列,遍历两个表,将表内存储的行与列内的值全置为0

代码:

int m=matrix.size(),n=matrix.size();
unordered_set<int> row,col;
for (int i=0; i<m; i++){
    for (int j=0; j<n; j++){
        if (matrix[i][j]==0){
            row.insert(i);
            col.insert(j);
        }
    }
}
for (auto i:row){
    for (int j=0; j<n; j++){
        matrix[i][j]=0;
    }
}
for (auto j:col){
    for (int i=0; i<m; i++){
        matrix[i][j]=0;
    }
}

方法三逻辑更加清晰易懂,可读性增加。

12.17记录

leetcode:相交链表

解题思路:用双指针遍历两个链表,遍历是否有相同地址的位置,退出循环,返回相交点。

时间复杂度:O(m * n)

代码:

// 定义双指针
ListNode *p, *q;
//使用三目运算符,遍历整个链表,观察p是否等于q,等于则为相交处,推出循环
while(p!=q){
    p = p ? p->next : headB;
    q = q ? q->next : headA;
}
return p;

12.18记录

leetcode:206反转链表(链表、指针我都不太会啊,感觉需要恶补

解法一(反转链表):

解题思路:创建三个置针,类比于交换数组元素

代码:(该思路较为简单

//先确定该链表是否为空或只有一个元素,则不需要倒置链表
if (!head||!head->next) return head;
//创建两个置针,一个指针用于记录原head,一个指针用于记录反转后的head即nullptr
ListNode* p=head;
ListNode* q=nullptr;
//遍历整个链表
while(!(p==nullptr)){
    List* temp = p->next;//用于存储下一个指针
    p->next = q;//将p所在地址的指针翻转,指为q,q一般为p地址左处的地址
    q = p;
    p = temp;
}
return q;

12.19记录

解体思路:用迭代法,将二叉树中左中右排列,地址取到值则将值放入到栈中,取到空值则让栈内top弹出,弹出的值则放入ans内,最后返回ans。
先将1放入栈中,在观察1的左子数,为null则将1弹出放入ans;
再将2放入栈中,观察2的左子树,为3,放入栈中,则栈内从上到下为:3,2
观察3的左子树,为null,则将3弹出,放入ans;
观察2的右子树,为null,则将2弹出,放入ans;
则ans为[1,3,2]

代码:

//创建ans,存储结果
vector<int> ans;
//创建树的指针,指向root
TreeNode* p=root;
//创建栈
stack<TreeNode> stk;
//先判断该表是否为空,或以stk为空作为循环结束
while(p||!stk.empty()){
    while(p){
        stk.push(p);
        p = p->left;
    }
    p = stk.top(); stk.pop();
    ans.emplace_back(p->value);
    p = p->right;
}
return ans;

12.20记录

leetcode:104二叉树的最大深度

解体思路:(递归思想)

首先要确定什么是递归:引用自己,触底结束,结束后自下而上返回(从最后的值返回)
二叉树原理1,2,2,2……
root向左和右分别移动,非0则加1,判断向左向右谁更max
​​​​​​​递归则是让每一个节点都为root

//确定指针
int maxdepth(TreeNode* root){
    //如果该二叉树值为null则返回0
    if (root == nullptr) return 0;
    //对二叉树进行递归,有值则返回1,null值则返回0,从中选取最大值进行返回
    return max(maxdepth(root->left), maxdepth(root->right))+1 
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值