(习题笔记)C++算法竞赛语法基础:结构体,类,指针,引用,链表

前天发了人生第一篇博客,没想到收到了点赞,感觉好开心,能被认可。我算法属实是一个小白,现在入门,意外发现这里很方便记笔记,就将自己的学习笔记放了上来,方便随时随地复习。现在发现还可以督促我学习哈哈哈,希望大家多多指教啦~,有什么好的学习方法大佬们若愿指点一二,hong感激不尽!算法真的感觉难,链表一道题我都要想好久,做不出再看讲解,然后自己再理解,虽道阻且长,但还是勇往直前吧!

注:这里收录的是我做不出、做错之类的我自己需要回顾的题目。

习题一:84. 求1+2+…+n

题解:我做题使用了递归,也是过了的,但是看了讲解后,发现递归的出口也是用到了判断,所以不符合题目要求,这里是正确解法。

class Solution {
public:
    int getSum(int n) {
        int res = n;
        n > 0 && (res+=getSum(n-1));
        return res;
    }
};

其实还是递归,但是写法看起来相差挺大的。主要利用了&&的特性,如果左半边不成立则右半边就不会运行,直接停止了。 

在上面还看到了一个看起来好牛逼的做法,y总都说第一次见!!!代码见下:

class Solution {
public:
    int getSum(int n) {
        char a[n][n+1];
        return sizeof(a)>>1;
    }
};

习题二:28. 在O(1)时间删除链表结点

代码如下:(注:我们只需在void deleteNode(ListNode* node){}的{}里面填写代码即可,其余的都已经给出。)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void deleteNode(ListNode* node) {
        node->val=node->next->val;
        node->next=node->next->next;
    }
};

一开始我以为传入的是整个链表(我的惯性思维吧),所以我一开始的想法是找到该数值的结点的前一个结点,然后它指向需要删除的结点的下一个结点。 其实传入的是要删除的结点的地址,所以正确的做法是可以“耍点小心机”,嘿嘿,将原本要删除的结点node的val值改为它指向的结点的val,再将node的next指向它指向的结点所指向的结点,这样就伪装成功,是不是有点绕?来个图解:

习题三:78. 左旋转字符串

题解:substr()函数的使用

class Solution {
public:
    string leftRotateString(string str, int n) {
        return str.substr(n)+str.substr(0,n);//substr(起始位置,字符总个数)
        //如果从起始位置开始一直到整个字符串结束,则字符总个数可以省略。
    }
};

 习题四:87. 把字符串转换成整数(难,┭┮﹏┭┮)

本题限制了使用函数,但是有两个函数是可以将字符串变成整数的,以字符串str为例:

①atoi(str.c_str())   ②stoi(str)   两个函数的返回值类型都是int

题解:(步骤和解析在代码注释里了)

class Solution {
public:
    int strToInt(string str) {
        int k=0;
        //先过掉空格
        for(char c:str) 
        {
            if(c==' ')
            k++;
        }
     
        //再处理±问题
        int num=1;
        if(str[k]=='-') 
        {
            num=-1;
            k++;
        }
        else if(str[k]=='+') k++;
        //开始处理数字,用每循环*10进行
        long long res=0;//数值会很大,要注意用long long
        while(k<str.size()&&str[k]>='0'&&str[k]<='9')
        {
            res=res*10+str[k]-'0';//str[k]-'0'这里就是将字符串变成0-9的整数
            k++;
            //因为存入的是绝对值。所以就无法直接与 INT_MAX和INT_MIN进行判断
            //所以这里的想法就是,通过计算机得到2的31次方是10位数,所以只要判断res>10的11次方就一定不在范围里
            if(res>1e11) break;
        }
        //这时再加上±,与 INT_MAX和INT_MIN进行判断
        res=res*num;
        if(res>=INT_MAX) res=INT_MAX;
        if(res<=INT_MIN) res=INT_MIN;
        return res;
    }
};

 习题五:35. 反转链表

题解:因为找不到前一个结点,所以设两个新指针p,q,再设指针o保存q的下一个结点,将q的next指向p,然后p=q,q=o。这样进行循环,直到q为空。注意:别忘了将head的next指向空!!!

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(!head||head->next==NULL) return head;
        ListNode *p,*q;
        p=head;
        q=p->next;
        while(q)
        {
            auto o=q->next;
            q->next=p;
            p=q;
            q=o;
        }
        head->next=NULL;
        return p;
    }
};

 习题六:66. 两个链表的第一个公共结点

 我的思路是将两个链表都反过来,然后找到它们最后一个相同的结点,这个结点就是它们原来共同的第一个结点,但是时间超了。。。

题解:(太巧妙了!o(╥﹏╥)o)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *findFirstCommonNode(ListNode *headA, ListNode *headB) {
       ListNode *p = headA, *q = headB;
       while(p!=q)
       {
           if(p) p=p->next;//p不为空,就往下一个结点走
           else p=headB;//为空就到另一条链表
           if(q) q=q->next;//与p类似
           else q=headA;
       }
       return p;
    }
};

习题七:29. 删除链表中重复的节点

 题解:

原理:让q往后找是否有和自己相同的结点,直到下一个结点不一样,这时p->next=q->next.

哨兵指针:当第一个结点可能被删时,要加一个哨兵,到时候传它的下一个结点。例1为例:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* deleteDuplication(ListNode* head) {
       auto dummy=new ListNode(-1);//哨兵
       dummy->next=head;
       auto p=dummy;
       while(p->next)
       {
           auto q=p->next;
           while(q->next)//找q后一个结点与它不相同
           {
               if(q->val==q->next->val) q=q->next;
               else break;
           }
           if(p->next==q) p=q,q=q->next;
           else p->next=q->next;
       }
       return dummy->next;
    }
};

  • 27
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值