【力扣打卡--day1】

1.链表

在这里插入图片描述
在这里插入图片描述

/**
 * 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* addTwoNumbers(ListNode* l1, ListNode* l2) {
        int t=0;
        ListNode* l,* r;//l是结果链表的头,r是尾
        l=r=new ListNode(-1);//虚拟头节点
        while(l1||l2||t){//位上有数字或者进位都得加进结果中
            if(l1){//第一个数字还有数字
                t+=l1->val;
                l1=l1->next;
            }
            if(l2){//第二个数字还有数字
                t+=l2->val;
                l2=l2->next;
            }
            r=r->next=new ListNode(t%10);//只取个位出来进结果链表
            t=t/10;//十位进位掉
        }
        return l->next;
    }
};

2.双指针

在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int N=s.size();
        unordered_map<char,int> hash;//记录i-j之间字母出现次数
        int res=0;
        for(int i=0,j=0;i<N;i++){//i在后,j在前
            while(hash[s[i]]) hash[s[j++]]--;
            //只要发现新增的字母在原区间已存在
            //就用j来找之前和现在加进来的i重的,边找边吐
            //反证法知道j只可能往后走
            hash[s[i]]++;//铲出原来重复的字母后自己进去
            res=max(res,i-j+1);//更新结果
        }
        return res;
    }
};

3.贪心

在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    string longestPalindrome(string s) {
        int N=s.size();
        string res;//可用dp,但是dp得多开数组空间大,有点难
        for(int i=0;i<N;i++){//遍历对称中心
            int l=i-1,r=i+1;//奇数长度的遍历
            while(l>=0&&r<N&&s[l]==s[r]) l--,r++;
            if(r-l-1>res.size()) res=s.substr(l+1,r-l-1);
            //l+1,r-1里的才是要的部分,
            //因为上面是不相等时退出来的

            l=i,r=i+1;//偶数长度的遍历
            while(l>=0&&r<N&&s[l]==s[r]) l--,r++;
            if(r-l-1>res.size()) res=s.substr(l+1,r-l-1);
        }
        return res;
    }
};

4.找规律

在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    string convert(string s, int numRows) {
        string res;
        int N=s.size();
        if(numRows==1) return s;//特殊情况,间隔变成0了,下面会死循环
        for(int i=0;i<numRows;i++){
            if(i==0||i==numRows-1){//第一行和最后一行
                for(int j=i;j<N;j+=2*numRows-2){
                //这个2*x-2得画图标下标看才能找这个规律出来
                    res+=s[j];
                }
            }else{//2*numRows-2-i这个也是规律出来的,画图就知道
                for(int j=i,k=2*numRows-2-i;
                j<N||k<N;j+=2*numRows-2,k+=2*numRows-2){
                //画图标下标看规律
                    if(j<N) res+=s[j];//要加判断,不然可能下标越界
                    if(k<N) res+=s[k];
                }
            }
        }
        return res;
    }
};

5.位运算

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

// class Solution {
// public:
//     int reverse(int x) {
//         long n=0;//long是钻空子,64位不能用
//         while(x!=0){
//             n=n*10+x%10;
//             x/=10;
//         }
//         return (int)n==n?n:0;
//     }
// };
class Solution {
public:
    int reverse(int x) {
        int n=0;//long是钻空子,64位不能用
        while(x){
            if(n>0&&n>(INT_MAX-x%10)/10) return 0;
            //加上后会溢出,
            //移到等式另一边缩小溢出值来判断就可以了
            if(n<0&&n<(INT_MIN-x%10)/10) return 0;
            n=n*10+x%10;
            //数学%的结果永远是正数,计算机是正负都行,歪打正着这题
            //所以不用判断符号
            x/=10;
        }
        return n;
    }
};

6.位运算

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    int myAtoi(string s) {
        int N=s.size();
        int k=0;
        while(s[k]==' ') k++;//前导空格

        int st=1;
        if(s[k]=='-') st=-1,k++;
        else if(s[k]=='+') k++;//符号判断
        // long long res=0;
        int res=0;
        while(k<N&&s[k]>='0'&&s[k]<='9'){
            int x=s[k]-'0';
            if(st>0&&res>(INT_MAX-x)/10) return INT_MAX;
            //超过最大值,和上一题一样判断溢出
            //不用try-catch了
            if(st<0&&-res<(INT_MIN+x)/10) return INT_MIN;
            //小于最小值
            if(-res*10-x==INT_MIN) return INT_MIN;
            //因为最小值的绝对值比最大值大1,
            //正数最大值装不下负数最大值绝对值,所以遇到就不装返回
            res=res*10+x;
            k++;
            // if(res>INT_MAX) break;
        }

        res*=st;
        // if(res>INT_MAX) return INT_MAX;
        // if(res<INT_MIN) return INT_MIN;
        return res;
    }
};

7.贪心

在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    int maxArea(vector<int>& height) {
        int res=0;
        for(int l=0,r=height.size()-1;l<r;){
            int h=min(height[l],height[r]);
            res=max(res,(r-l)*h);
            if(height[l]<height[r]){
            //值小的指针向内移动,这样就减小了搜索空间 
            //因为面积取决于指针的距离与值小的值乘积,
            //如果值大的值向内移动,距离一定减小,
            //而求面积的另外一个乘数一定小于等于值小的值,
            //因此面积一定减小,
            //而我们要求最大的面积,因此值大的指针不动,
            //而值小的指针向内移动遍历
                l++;
            }else{
                r--;
            }
        }
        return res;
    }
};

8.找规律

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    string intToRoman(int num) {
        string a[]={"I","IV","V","IX","X","XL","L","XC","C","CD","D","CM","M"};
        int b[]={
            1,4,5,9,
            10,40,50,90,
            100,400,500,900,
            1000
        };//模拟题找规律
        string res;
        for(int i=12;i>=0;i--){
        //查表,够就减数字加字符
            while(num>=b[i]){
                num-=b[i];
                res+=a[i];
            }
        }
        return res;
    }
};

9.双指针

  • 在这里插入图片描述
    在这里插入图片描述
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        //双指针必须先排序
        vector<vector<int>> res;
        int N=nums.size();
        for(int i=0;i<N;i++){//i指的为固定值
            if(i&&nums[i]==nums[i-1]) continue;
            //相同跳过,枚举过了
            for(int j=i+1,k=N-1;j<k;j++){//双指针
                if(j>i+1&&nums[j]==nums[j-1]) continue;
                //相同跳过,枚举过了
                while(j<k-1&&nums[j]+nums[i]+nums[k]>0) k--;
                //看要不要走下一步,直到走不了
                if(nums[i]+nums[j]+nums[k]==0){
                    res.push_back({nums[i],nums[j],nums[k]});
                }
            }
        }
        return res;
    }
};

10.双指针

  • 在这里插入图片描述
class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        sort(nums.begin(),nums.end());
        pair<int,int> res(INT_MAX,INT_MAX);
        //first是差值,second是总和
        int N=nums.size();
        for(int i=0;i<N;i++){
            for(int j=i+1,k=N-1;j<k;j++){
                while(j<k-1&&nums[i]+nums[j]+nums[k-1]>=target) k--;
                //第一种情况大于目标值:
                //缩小距离,一直走到不能走为止
                int sum=nums[i]+nums[j]+nums[k];
                res=min(res,make_pair(abs(sum-target),sum));
                //有可能走完了都没找到大的情况
                //那就是负数了,所以要绝对值
                if(k-1>j){
                //第二种情况小于目标值:看看下一步还有得走吗
                //,有就拿来判断第二种情况
                    sum=nums[i]+nums[j]+nums[k-1];
                    res=min(res,make_pair(target-sum,sum));
                    //必定小于目标值,所以不用绝对值
                }
            }
        }
        return res.second;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值