LeetCode刷题记1-10

前言

今年准备考研想固定好每周刷10道算法题以上,特地开这个栏目来记录刷题过程,按序号来刷,每10题一篇文章

LeetCode 1. 两数之和

题目链接

https://leetcode.cn/problems/two-sum/

思路1 暴力枚举

  1. 两重循环枚举下标 i,ji,j,然后判断 nums[i]+nums[j] 是否等于 target。

  2. 复杂度O(n^2)

AC代码1

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) &#123;
        vector<int> res;
        for(int i = 0; i < nums.size(); i ++)
        &#123;
            for(int j = 0; j < i; j ++)
            &#123;
                if(nums[i] + nums[j] == target)
                &#123;
                    res = vector<int> &#123;i, j&#125;;
                &#125;
            &#125;
            if(res.size() > 0) break;
        &#125;
        return res;
    &#125;
&#125;;

思路2 哈希表优化

  1. 使用哈希表边查找边存储

    查找target - num[i]是否在哈希表中 存在则返回
    将num[i]插入

  2. 哈希表的插入和查询操作的复杂度O(1),总复杂度O(n)

AC代码2

class Solution &#123;
public:
    vector<int> twoSum(vector<int>& nums, int target) &#123;
        vector<int> res;
        unordered_map<int, int> hash;
        // 边找边插入
        for(int i = 0; i < nums.size(); i ++)
        &#123;
            int another = target - nums[i];
            if(hash.count(another))
            &#123;
                res = vector<int> &#123;hash[another], i&#125;;
                break;
            &#125;
            hash[nums[i]] = i;
        &#125;
        return res;
    &#125;
&#125;;

LeetCode 2. 两数相加

题目地址

https://leetcode.cn/problems/add-two-numbers/

思路

  1. 从最低位至最高位,逐位相加,如果和大于等于10,则保留个位数字,同时向前一位进1.
  2. 如果最高位有进位,则需在最前面补1.

添加一个虚拟头结点:ListNode *head = new ListNode(-1);

  1. 时间复杂度O(n)

AC代码

class Solution &#123;
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) &#123;
        ListNode *res = new ListNode(-1);
        ListNode *cur = res;
        int carry = 0;
        while(l1 || l2)
        &#123;
            int n1 = l1 ? l1-> val : 0;
            int n2 = l2 ? l2-> val : 0;
            int sum = n1 + n2 + carry;
            carry = sum / 10;
            cur->next = new ListNode(sum % 10);
            cur = cur -> next;
            if(l1) l1 = l1 -> next;
            if(l2) l2 = l2 -> next;
        &#125;
    if(carry) cur->next = new ListNode(carry);
    return res->next;
    &#125;
&#125;;

LeetCode 3. 无重复字符的最长子串

题目地址

https://leetcode.cn/problems/longest-substring-without-repeating-characters/

思路

  1. 双指针写法,看y总思路即可

    https://www.acwing.com/solution/content/49/

  2. 时间复杂度O(n)

AC代码

class Solution &#123;
public:
    int lengthOfLongestSubstring(string s) &#123;
        // 使用双指针
        unordered_map<int, int> hash;
        int res = 0;
        for(int i = 0, j = 0; i < s.size(); i ++)
        &#123;
            hash[s[i]] ++;
            while(hash[s[i]] > 1)
            &#123;
                hash[s[j]]--;
                j ++;
            &#125;
            res = max(res, i - j + 1);
        &#125;
        return res;
    &#125;
&#125;;

LeetCode 4. 寻找两个正序数组的中位数

题目地址

https://leetcode.cn/problems/median-of-two-sorted-arrays/

思路

此题乍一看很简单,实则难度很大,建议看y总的题解
https://www.acwing.com/solution/content/50/

AC代码 递归

class Solution &#123;
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) &#123;
        int total = nums1.size() + nums2.size();
        if(total % 2 == 0)
        &#123;
            int left = findKthNumber(nums1, 0, nums2, 0, total / 2);
            int right = findKthNumber(nums1, 0, nums2, 0, total / 2 + 1);
            return (left + right) / 2.0;
        &#125;
        else 
        &#123;
            return findKthNumber(nums1, 0, nums2, 0, total / 2 + 1);
        &#125;
    &#125;
    // nums1的长度一定比nums2的小 
    int findKthNumber(vector<int>& nums1, int i, vector<int>& nums2, int j, int k)
    &#123;
        // 此处使nums1一定比nums2小
        if(nums1.size() - i > nums2.size() - j) return findKthNumber(nums2, j, nums1, i, k);
        if(nums1.size() == i) return nums2[j + k - 1];
        if(k == 1) return min(nums1[i], nums2[j]);

        int s1 = min(i + k / 2, (int)nums1.size()), s2 = j + k / 2;
        if(nums1[s1 - 1] > nums2[s2 - 1])
        &#123;
            return findKthNumber(nums1, i, nums2, s2, k - (s2 - j));
        &#125;
        else
        &#123;
            return findKthNumber(nums1, s1, nums2, j, k - (s1 - i));
        &#125;
    &#125;
&#125;;

LeetCode 5. 最长回文子串

题目地址

https://leetcode.cn/problems/median-of-two-sorted-arrays/

思路

使用双指针 比较简单的了,注意处理好字符串长度奇数和偶数的情况

  1. 奇数:l = i, r = i;
  2. 偶数:l = i, r = i + 1;

AC代码 递归

class Solution &#123;
public:
    string longestPalindrome(string s) &#123;
        string res;
        for(int i = 0; i < s.size(); i ++)s
        &#123;
            // s长度为奇数 
            int l = i, r = i;
            while (l >= 0 && r < s.size()  && s[l] == s[r]) l --, r ++;
            if(res.size() < r - l - 1) res = s.substr(l + 1, r - l - 1);
            // s长度为偶数
            l = i, r = i + 1;
            while(l >= 0 && r < s.size() && s[l] == s[r]) l --, r ++;
            if(res.size() < r - l - 1) res = s.substr(l + 1, r - l - 1);
        &#125;
        return res;
    &#125;
&#125;;

LeetCode 6. Z 字形变换

题目地址

https://leetcode.cn/problems/zigzag-conversion/submissions/

思路

找规律问题 可以看y总的解释
https://www.acwing.com/solution/content/75/

下面ac代码也有超级详细注释

AC代码

class Solution &#123;
public:
    string convert(string s, int n) &#123;
        string res;
        // 如果只有一个字符 则为原字符串
        if (n == 1) return s;
        for (int i = 0; i < n; i ++)
        &#123;
            // 第一行和最后一行 是首项为i 公差为2n-2的等差数列
            if (i == 0 || i == n - 1)
            &#123;
                for (int j = i; j < s.size(); j += 2 * n - 2)
                    res += s[j];
            &#125;
            else // 其他每一行都是由两个等差数列交叉 一个是首项为i公差为2n-2-i 一个是首项为2n-2-i公差为
            &#123;
                for (int j = i, k = 2 * n - 2 - i; j < s.size() || k < s.size(); j += 2 * n - 2 , k += 2 * n - 2)
                &#123;
                    if (j < s.size()) res += s[j];
                    if (k < s.size()) res += s[k];
                &#125;
            &#125;
        &#125;
        return res;
    &#125;
&#125;;

LeetCode 7. 整数反转

题目地址

https://leetcode.cn/problems/reverse-integer/

思路

比较简单看代码即可

注意:有两种方法一种用long long res不会溢出,题目说明好像有规定不让long long,使用int的时候注意判断溢出情况

AC代码

// 使用long long
class Solution &#123;
public:
    int reverse(int x) &#123;
        long long res = 0;
        while (x)
        &#123;
            res = res * 10 + x % 10;
            x /= 10;
        &#125;

        if (res > INT_MAX) return 0;
        if (res < INT_MIN) return 0;
        return res;
    &#125;
&#125;;
// 使用int
class Solution &#123;
public:
    int reverse(int x) &#123;
        int res = 0;
        while (x)
        &#123;
            // 检测res会不会溢出
            if (res > 0 && res > (INT_MAX - x % 10) / 10) return 0;
            if (res < 0 && res < (INT_MIN - x % 10) / 10) return 0;
            res = res * 10 + x % 10;
            x /= 10;
        &#125;
        return res;
    &#125;
&#125;;

LeetCode 8. 字符串转换整数 (atoi)

题目地址

https://leetcode.cn/problems/string-to-integer-atoi/

思路

跟上一题一样 使用long long 和 int存储

AC代码

// 使用long long
class Solution &#123;
public:
    int myAtoi(string s) &#123;
        int k = 0; // 移动指针
        // 先去除空格
        while (k < s.size() && s[k] == ' ') k ++;
        if (k == s.size()) return 0;

        // 判断数字前面的正负
        int minus = 1;
        if (s[k] == '+') k ++;
        else if (s[k] == '-') minus = -1, k++; 

        // 数字部分
        long long res = 0;
        while (k < s.size() && s[k] >= '0' && s[k] <= '9')
        &#123;
            res = res * 10 + s[k] - '0';
            k ++;
            if (res > INT_MAX) break;
        &#125;
        res *= minus;
        // 判断溢出
        if (res > INT_MAX) res = INT_MAX;
        if (res < INT_MIN) res = INT_MIN;
        return res; 
    &#125;
&#125;;
// 使用int
class Solution &#123;
public:
    int myAtoi(string s) &#123;
        int k = 0; // 移动指针
        // 先去除空格
        while (k < s.size() && s[k] == ' ') k ++;
        if (k == s.size()) return 0;

        // 判断数字前面的正负
        int minus = 1;
        if (s[k] == '+') k ++;
        else if (s[k] == '-') minus = -1, k++; 

        // 数字部分 使用int处理好溢出
        int res = 0;
        while (k < s.size() && s[k] >= '0' && s[k] <= '9')
        &#123;
            int x = s[k] - '0';
            // 正数和负数溢出情况
            if (minus > 0 &&  res > (INT_MAX - x) / 10) return INT_MAX;
            if (minus < 0 && -res < (INT_MIN + x) / 10) return INT_MIN;

            // 注意int正数的最大值是2^31-1 int负数的最小值是-2^31 比正数多译
            // 这里得判断 如果刚好等于负数最小值的情况
            if (- res * 10 - x == INT_MIN) return INT_MIN;

            res = res * 10 + x;
            k ++;
            if (res > INT_MAX) break;
        &#125;
        res *= minus;
        // 判断溢出
        if (res > INT_MAX) res = INT_MAX;
        if (res < INT_MIN) res = INT_MIN;
        return res; 
    &#125;
&#125;;

LeetCode 9. 回文数

题目地址

https://leetcode.cn/problems/palindrome-number/

思路

两种做法 一种需要额外开辟tmp存储x 另一种不用

AC代码

// 需要存储x 这种好像快一点
class Solution &#123;
public:
    bool isPalindrome(int x) &#123;
        int tmp = x;
        // 负数直接返回
        if ( x < 0 ) return false;
        long long y = 0;
        while (x)
        &#123;
            y = y * 10 + x % 10;
            x /= 10;
        &#125;
        return tmp == y;
    &#125;
&#125;;
// 不需要存储x
class Solution &#123;
public:
    bool isPalindrome(int x) &#123;
        // 负数直接返回
        if ( x < 0 ) return false;
        long long y = 0;
        for (int i = x; i; i /= 10)
        &#123;
            y = y * 10 + i% 10;
        &#125;
        return x == y;
    &#125;
&#125;;

LeetCode 10. 正则表达式匹配

题目地址

https://leetcode.cn/problems/regular-expression-matching/

思路

本题难度有点大 建议看y总讲解

https://www.acwing.com/solution/content/102/

AC代码

class Solution &#123;
public:
    bool isMatch(string s, string p) &#123;
        int n = s.size(), m = p.size();
        s = ' ' + s, p = ' ' + p;
        vector<vector<bool>> f(n + 1, vector<bool> (m + 1));
        f[0][0] = true;

        for (int i = 0; i <= n; i ++)
            for (int j = 1; j <= m; j ++)
            &#123;
                if (j + 1 < m && p[j + 1] == '*') continue;
                if (i && p[j] != '*')
                &#123;
                    f[i][j] = f[i - 1][j - 1] && (s[i] == p[j] || p[j] == '.');
                &#125;
                else if (p[j] == '*')
                &#123;
                    f[i][j] = f[i][j - 2] || i && f[i - 1][j] && (s[i] == p[j - 1] || p[j - 1] == '.');
                &#125;
            &#125;
        return f[n][m];
    &#125;
&#125;;

  转载请注明: Justin博客 LeetCode刷题记1-10

 上一篇
LeetCode刷题记11-20 LeetCode刷题记11-20
LeetCode 11. 盛最多水的容器题目链接 https://www.acwing.com/solution/content/100/ 思路双指针问题 比较简单 AC代码1class Solution &#123; publi
下一篇 
【算法基础篇】数组模拟队列、滑动窗口问题 【算法基础篇】数组模拟队列、滑动窗口问题
两种写法数组模拟栈: tt=-1, q[++tt]=x, hh<=tt 表示队列非空 tt=0, q[tt++]=x, hh<tt 表示队列非空 AC代码#include <iostream> using names
  目录