LeetCode(仍然是为了跑路做准备的一天哦)

博主分享了近期每日练习算法题目的过程和心得,包括两数之和、链表相加、无重复字符最长子串、二分查找、轮转数组等,涉及链表操作、滑动窗口、二分查找等算法。此外,博主还提到在解决回文数问题时遇到的困扰,并分享了字符串反转和转换成整数的方法。

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

想不到吧,毕业了,我还跑来刷算法题,不过确实忘了很多,所以。。。从头开始吧,日更新好吧,看看能不能坚持,嗯,手残了电脑没了另说。


目录

20220211两数之和

 20220211两数相加

20220213无重复字符的最长子串

todo:20220214寻找两个正序数组的中位数

20220215二分查找

20220216轮转数组

20220220最长回文子串(dp必须会)

20220222 Z字型变换

20220224整数反转

20220226字符串转换成整数(atoi)

20220228回文数


20220211两数之和

这么简单的题,为什么会纠结这么久。。。连代码都懒得贴(vector不像QVector,注意用法,and多上手。。。)

 20220211两数相加

链表的使用还是需要进一步学习,这里一个有next的时候不能L1++,应该l1 =l1->next。还有新建一个结点的时候需要用L1->next=tmp,而不能L1=L1->nextp;L1=tmp;

/**
 * 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) {
        ListNode * res = new ListNode(l1->val+l2->val);
        ListNode * res_head = res;

        l1 = l1->next;
        l2 = l2->next;
        while(l1 && l2)
        {
            //两数相加,先不考虑进位
            int sum = l1->val + l2->val;

            ListNode *tmp = new ListNode(sum);
            res->next = tmp;
            res = res->next;

            l1 = l1->next;
            l2 = l2->next;
        }

        //这个数字结束,就把另一个数字的剩余部分直接给res
        if(l1 == NULL)
        {
            res->next = l2;
        }
        else if(l2 == NULL)
        {
            res->next = l1;
        }
        else
        {
            //sure ?
        }

        //对res进行进位操作
        ListNode *res2 = res_head;
        int carry = 0;
        while(res_head->next != NULL)
        {
            res_head->val += carry;
            if(res_head->val >= 10)
            {
                res_head->val -= 10;
                carry = 1;
            }
            else
            {
                carry = 0;
            }
            res_head = res_head->next;
        }

        //考虑一下,最后一位的进位
        res_head->val += carry;
        if(res_head->val >= 10)
        {
            res_head->val -= 10;
            ListNode *tmp = new ListNode(1);
            res_head->next = tmp;
        }

        return res2;
    }
};

20220213无重复字符的最长子串

首先昨天咕了,因为周六放假,一玩就没刹住车,嗯,因为学习算法看到人没了。

然后这道题,一开始是以为是KMP,还跑去复习半天,看懂以后发现不是一个题目(一个是最长子串,一个是无重复子串,我为什么会觉得是同一个?)。然后去看一眼题解(leetcode有题解,真的就舒服好多啊~),用滑动窗口(为什么我以前重来没听过。。。还是太逊了我)

  1. start不动,end向后移动
  2. 当end遇到重复字符,start应该放在上一个重复字符的位置的后一位,同时记录最长的长度(如果上一个重复字符的位置后一位在原start前面,则不调回start)
  3. 用map的key来判断是否重复,用value来记录该字符的下一个不重复的位置。
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        map<char, int> hash;
        int start = 0;
        int res   = 0;
        for(int end = 0; end < s.length(); end++)
        {
            char ch = s.at(end);
            if(hash.find(ch) != hash.end())
            {
                start = max(start, hash[ch]+1);//从上一个这个字符,的后一位,继续匹配
                hash[ch] = end;//更新这个字符的位置
            }
            else
            {
                hash.insert(pair<char, int>(ch, end));//插入新的字符
            }

            res = max(res, end-start+1);//记录最长字长
        }

        return res;
    }
};

todo:20220214寻找两个正序数组的中位数

 是的,todo,昨晚一小时+今晚一小时,我决定,先拖回。。。

情人节一个人过就罢了,还要受这人间疾苦,下次再议

20220215二分查找

是的,因为被中等、困难打击到了,所以找了简单的题目做一下(才不是不想做题,所以找个简单应付一下)

这是个简单的二分查找,但是一开始因为我的start=mid-1,没有-1,导致超出时间了。。。

(ps:大家没事的时候练练爱好,例如口琴,那就要先找准口,发对音,慢慢练)

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int start = 0;
        int end   = nums.size()-1;
        int res   = -1;

        while(start <= end)
        {
            int mid = (start+end)/2;
            if(target == nums[mid])
            {
                res = mid;
                break;
            }
            else if(target < nums[mid])
            {
                end = mid - 1;
            }
            else //target > nums[mid]
            {
                start = mid + 1;
            }
        }

        return res;
    }
};

20220216轮转数组

 这就好简单唉,虽然是简单题,但热热手还是不错的。(我就纳闷,项目里写注释,不是常识嘛,为什么要丢给我一份没注释的代码,难受一天了)。

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        int len = nums.size();
        int rel_k = k % len;
        vector<int> res(len);
        for(int i = 0, j = len-rel_k; i < rel_k; i++, j++)
        {
            res[i] = nums[j];
        }
        for(int i = rel_k, j = 0; i < len; i++, j++)
        {
            res[i] = nums[j];
        }
        nums = res;
    }
};

20220220最长回文子串(dp必须会)

这个题目一上来,就想到dp了,然后!dp忘了。。。所以中间去学dp啦。然后这不出差了嘛,所以拖了几天。(第一天坏了空调被冻在被窝不想出来,第二天收拾行李处理一些事,第三天刚到西安,咕咕咕)todo:这道题的题解有建议用马拉车算法,还说不会也背一下,嗯,下次一定

ps:个人愚见,做算法题,先学习嘛,所以一开始如果遇到不会的,不要丧气,看看人家怎么做的,集大成了,再去对自己做要求

class Solution {
public:
    string longestPalindrome(string s) {
        int n = s.size();
        if(n == 1)
        {
            return s;//就一个字符,直接返回(题目设定n>=1)
        }

        vector<vector<int> > dp(n, vector<int>(n, 0));
        for(int i = 0; i < n; i++)
        {
            dp[i][i] = 1;
        }

        int len    = 1;
        string res = s.substr(0, len);

        for(int j = 1; j < n; j++)
        {
            for(int i = 0; i < j; i++)
            {
                if(s[i] != s[j])
                {
                    dp[i][j] = 0;
                }
                else
                {
                    if(j-i <= 2)
                    {
                        dp[i][j] = 1;//边界值
                    }
                    else
                    {
                        dp[i][j] = dp[i+1][j-1];//dp的精髓啊
                    }
                }

                if(dp[i][j] == 1 && j-i+1 > len)//更新长度
                {
                    len = j-i+1;
                    res = s.substr(i, len);
                }
            }
        }
        return res;
    }
};

20220222 Z字型变换

好吧,昨天晚上自己想了半天,然后就无了啊。中午参考了一下别人的题解,补一下

思路差不多,但是根据flag和row,管理好了下一个字符的位置


class Solution {
public:
    string convert(string s, int numRows) {
        if(numRows == 1)
        {
            return s;
        }

        int n = s.size();
        
        //这是我一开始的想法,填表来着,没想好怎么安排x和y,所以无了
        //int t = numRows * 1.5;
        //int col = (n/t) * (1+numRows/2) + (n/t*t == n ? 0 : 1);
        //vector<vector<char> > rec(numRows, vector<char>(col, ' '));

        vector<string> process(numRows, "");//将z字变换的过程模拟出来
        int flag   = 0;//0:向左,1:向下
        int row    = 0;//下一个s字符所处的行数
        for(int i = 0; i < n; i ++)
        {
            process[row] += s[i];

            //然后要判断,下一个字符的走向
            if(flag)
            {
                row++;//向下走
            }
            else
            {
                row--;//向左走,也就是向上走
            }

            if(row == -1) // 0--=-1,上一个字符行数为0,不能再向上了
            {
                flag = 1;//所以下一个字符,应该是向下
                row  = 1;//向下的话,下一个字符的行数应该为1
            }
            else if(row == numRows)//numrows-1 ++ = numrows。到底了,应该向上走了
            {
                flag = 0;
                row  = numRows-2;
            }
        }
        string res = "";
        for(string tmp : process)
        {
            res += tmp;
        }
        return res;
    }
};

20220224整数反转

这个题,没用什么算法,嗯。大体思路就是int转string,string转换(string好像可以直接颠倒),然后再转成int输出。然后我就写的这么烂了。。。

昨晚写的,但是因为没考虑到超出限制,然后以为有问题了,就重写了。。。(记得审题)

提醒:环境只能存储得下 32 位的有符号整数,意味着其数值范围为 [−2^31,  2^31 − 1]

class Solution {
public:
    int reverse(int x) {
        string strx = to_string(x);
        int n       = strx.size();

        if(x < 0)
        {
            for(int i = 1; i <= n/2; i++)//考虑到去一位符号位
            {
                char tmp  = strx[i];
                strx[i]   = strx[n-i];
                strx[n-i] = tmp;
            }

            int pos  = 1;
            char tmp = strx[pos];
            while(tmp == '0')
            {
                tmp = strx[++pos];
            }
            strx = "-"+strx.substr(pos, n-pos+1);
        }
        else if(x > 0)
        {
            for(int i = 0; i < n/2; i++)
            {
                char tmp    = strx[i];
                strx[i]     = strx[n-i-1];//注意好下标
                strx[n-i-1] = tmp;
            }

            int pos = 0;
            char tmp = strx[pos];
            while(tmp == '0')//不会一直等于0的,所以不设限制
            {
                tmp = strx[++pos];
            }
            strx = strx.substr(pos, n-pos);//注意好长度
        }
        else//x == 0
        {
            return 0;
        }

        try
        {
            return stoi(strx);//超出限制了,要返回0。无语了我都
        }
        catch(...)
        {
            return 0;
        }
    }
};

然后这是人家好一点的代码(对啊,直接%不就行了嘛,还是对数据不够敏感)

int reverse(int x) {
    int ans = 0;
    while (x) {
        if (ans > INT_MAX / 10 || ans < INT_MIN / 10)
            return 0;
        ans = ans * 10 + x % 10;
        x /= 10;
    }
    return ans;
}

作者:tab-liu
链接:https://leetcode-cn.com/problems/reverse-integer/solution/7-zheng-shu-fan-zhuan-rust-c-python3-by-bhlin/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

20220226字符串转换成整数(atoi)

首先,强调读题。。。不知道为什么自己前面那么大意,题都没读好,就开干了 

这道题,一开始什么都没想,正则匹配一下,然后就花了三天时间(当然也有因为最近10.下班的原因,想不到吧。领导说9.开个例会就下班,然后她9.40过来,讲讲到10.,她再整理一下我们上交的文档,就回去啦

因为自己慢慢折腾嘛,就是先复习一下正则,然后提交,看哪里有问题,针对着改。。。

class Solution {
public:
    int myAtoi(string s) {
        // regex reg("[-]?[\\d]*[.]?[\\d]*");     //一开始以为要匹配浮点数
        s = regex_replace(s, regex("^\\s*"), ""); //去除空格,而且是前置空格,中间的空格不消除
                                                  //regex_replace(s, regex(" "), "");则是去除所有空格
        if(!isdigit(s[0]) && (s[0]!='-'&& s[0]!='+') || (s.size()>2 && !isdigit(s[1])))
        //首字母不是数字,并且不是正负号的,直接return 0(貌似数据集不存在这个情况)
        //+-,连续两个字符的情况。。。
        {
            return 0;
        }

        regex reg("[-+]?[\\d]*"); //匹配有符号整型
        cmatch m;
        auto flag = regex_search(s.c_str(), m, reg);
        string res = m[0].str();  //结果放在这个m[0]里了

        try
        {
            return stoi(res);//超出限制了,要返回0
        }
        catch(out_of_range&)
        {
            if (res[0] == '-')
            {
                return  INT_MIN; //超出界限的情况,直接返回最值
            }
            else
            {
                return  INT_MAX;
            }
        }
        catch(...)
        {
            return 0;           //else 也可以加个std::invalid_argument&
        }
    }
};
//遇到的稀奇古怪的情况。。。
// 24
//-24
//+-24
//-91283472332
//3.1415926
//   +0 123

20220228回文数

emmm,一个很简单的题目,嗯,然后被我弄复杂了,就很难受。想到了从数字入手,然后节省一半时间,弄个prefix和suffix,结果最后纠结在prefix+suffix==x。难道直接prefix==suffix不行嘛。折腾两天了,嗯,昨天周日没躺平而是在改错

(不过,要准备考研的话,可能没时间再做题了,也许辞职以后专心考研,可能还能抽个一小时做会。也是在担心,中间没管住自己,该怎么办)

class Solution {
public:
    bool isPalindrome(int x) {
        if(x < 0 || (x>0&&x%10==0))//有个负号,或者个位是0,不可能回文
        {
            return false;
        }

        int suffix = 0;
        while(x > suffix)
        {
            suffix = suffix*10 + x%10;
            x /= 10;
        }

        return suffix==x || suffix/10==x;
        // int prefix = 0;
        // int suffix = x;
        // int digit  = 0;
        // while(suffix >= prefix)
        // //suffix的位数比prefix多,相等的时候,就是 x.size()/2 了
        // {
        //     prefix = prefix*10 + suffix%10;
        //     suffix /= 10;
        //     digit++;
        // }
        // for(int i = 0; i < digit-1; i++)
        // {
        //     prefix *= 10;
        // }
        //error了,不用看
        // if(suffix)
        // {
        //     return prefix+suffix == x;
        // }
        // else
        // {
        //     return prefix == x;
        // }
    }
};

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值