LeetCode刷题总结 && 每五题汇总(一)

  • 一些算法题的总结,部分是自己所写,部分是官网所提供的答案;
  • 关于刷题,虽然数量很重要,但是重点在于刷题质量和解题方法的总结;
  • 撰写笔记于此,每一题都有思路总结和注释引导,希望对你有所帮助。

目录

一、两数之和

二、回文数

三、罗马数字转整数

四、最长公共前缀

五、有效的括号


一、两数之和

思路总结:

  1. 分析题干:
    从数组中找到两个元素A和B,A+B = target;
  2. 返回值:
    两个元素A和B的下标;
  3. 解题:
    有元素有下标,考虑map哈希表,根据 target-A 来寻找B,最终返回A和B的下标。具体步骤见代码中的注释。

注意事项:

  1. 每一次循环都往哈希表中添加键值对,以保证不让A或者B和自己匹配。
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) 
    {
        // 定义无序映射的哈希表
        unordered_map<int, int> hashtable;
        for (int i = 0; i < nums.size(); ++i) {
            // 根据两数之差,找到并返回对应的哈希表的迭代(键值对)
            auto iter = hashtable.find(target - nums[i]);
            // 如果找不到满足 target-nums[i] 的值,返回哈希表的end
            if (iter != hashtable.end()) {  // 找到了
                return {it->second, i};
            }
            // 往哈希表中添加键值对,以保证不让nums[i]不和自己匹配!
            hashtable[nums[i]] = i;
        }
        return {};  // 返回结果
    }
};

二、回文数

扫描二维码关注公众号,回复: 14779396 查看本文章

思路总结:

  1. 分析题干:
    回文数,即两端对称的整数;
  2. 返回值:
    bool类型,ture或者false;
  3. 解题:
    首先分析整数的范围,负数全部返回false,末尾为零的整数(非0)也返回false。然后分析奇数和偶数,对于奇数,省略中间数的影响后,判别步骤同偶数。具体步骤见注释。

注意事项:

  1. 反转整数的方法:取整运算( / )和取余运算( % )相互结合使用;
  2. while循环中的判断条件,刚好限制住 revertedNumber 取到 x 的半边。即x=112233时,循环过后,x=112,revertedNumber=332,非常巧妙。
class Solution {
public:
    bool isPalindrome(int x) {
        // 特殊情况:
        // 1、当 x < 0 时,x 不是回文数。
        // 2、非零整数,末尾为0时,不是回文数
        if (x < 0 || (x % 10 == 0 && x != 0)) {
            return false;
        }

        // 1、偶数:把x从中间分开,根据取余和取整运算,判断左侧的正序和右侧的逆序是否相等
        // 2、奇数:可以省略中间数的影响,判别步骤同偶数
        int revertedNumber = 0;
        while (x > revertedNumber) {  // 注意while的判断条件,巧妙
            revertedNumber = revertedNumber * 10 + x % 10;
            x /= 10;
        }

        // x == revertedNumber:当x为偶数时,直接判断即可
        // x == revertedNumber/10:当x为奇数时,去除中间数后,进行判断即可
        return x == revertedNumber || x == revertedNumber / 10;
    }
};

三、罗马数字转整数

 思路总结:

  1. 分析题干:
    罗马数字转整数,有条件的整数加减运算罢了;
  2. 返回值:
    返回最终的整数;
  3. 解题:
    每一个罗马文字都对应一个数字,需要创建一个映射来存储键值对。不要被特殊条件所迷惑,判断相邻的罗马数字大小,前者小,相减;反之相加即可。具体步骤见注释。

注意事项:

  1. 判断条件很重要。
class Solution {
private:
    // 根据题干条件创建映射
    unordered_map<char, int> symbolValues = {
        {'I', 1},
        {'V', 5},
        {'X', 10},
        {'L', 50},
        {'C', 100},
        {'D', 500},
        {'M', 1000},
    };

public:
    int romanToInt(string s) {
        int ans = 0;
        int n = s.length();
        for (int i = 0; i < n; ++i) {
            // 利用无序映射,返回数值
            int value = symbolValues[s[i]];
            // 判断前后位的数值大小:若前者小,相减;反之相加
            if (i < n - 1 && value < symbolValues[s[i + 1]]) {  // 此处的判断条件是精华
                ans -= value;
            } else {
                ans += value;
            }
        }
        return ans;
    }
};

四、最长公共前缀

 思路总结:

  1. 分析题干:
    找到数组中所有元素的最长公共前缀;
  2. 返回值:
    返回string(最长公共前缀);
  3. 解题:
    首先需要判断数组中的最短字符串,以最短字符串的长度min_len作为限制条件,去遍历所有元素的前min_len个字符是否相等。部分情况需要直接返回,具体见注释。

注意事项:

  1. C++中添加元素到字符串中的方法:string res; res += 'c';
  2. 定义方式:字符串 "Faying Bulldo",字符 'g'。
class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        int n_strs = strs.size();  // 字符串数组的长度
        int min_len = 0;  // 字符串最小长度
        for (int i = 0; i < n_strs - 1; i++) {
            int len_str = strs[i].length();
            int len_str_latter = strs[i + 1].length();
            // 冒泡比较得出最小的字符串长度
            if (len_str_latter > len_str) {
                min_len = len_str;
            }
            else {
                min_len = len_str_latter;
            }
        }

        // 两种情况:
        // 1、字符串数组中只有一个元素
        // 2、字符串数组中有多个元素,并且其中有一个位空字符
        if (min_len == 0 && n_strs == 1) {
            return strs[0];
        }
        else if (min_len == 0 && n_strs > 1) {
            return "";
        }

        // 最多的一种情况:字符串中有多个数组,并且没有空字符
        string temp1; 
        string temp2;
        bool flag = true;  // 存储正确结果的标志
        string res;  // 存储每一轮判断的正确结果
        for (int j = 0; j < min_len; j++) {
            // 更快一些:把temp1从内循环中拿出,每一次循环只需要把第一个字符串的一个字符作为标准即可
            temp1 = strs[0][j];
            for (int i = 0; i < n_strs - 1; i++) {
                temp2 = strs[i + 1][j];
                // 比较每相邻两个元素的相同位置的字符是否相等
                if (temp1 != temp2) {
                    flag = false;
                    break;
                }
            }
            if (flag == true) {
                res += temp1;  // 如果相等,融合字符
            }
        }
        // 根据结果字符串的长度来return
        if (res.length() <= 0) {
            return "";
        }
        else {
            return res;
        }
    }
};

五、有效的括号

 思路总结:

  1. 分析题干:
    左括号和右括号的匹配问题,特殊例子:( [ ] ) { }、{ [ ( ) ] } 正确,( [ ) ] ( ) 错误;
  2. 返回值:
    返回bool值,全部匹配成功,返回ture,反之返回false;
  3. 解题:
    利用 "栈" 的特点匹配括号,遍历字符串,只把左括号压入栈中,然后判断是否有右括号和栈顶的左括号匹配,匹配成功后,不要忘记把左括号从栈中抛出。具体步骤键注释。

注意事项:

  1. 栈的特点:先进后出,即最后压入栈中的元素在栈顶,从栈顶开始抛出元素;
  2. 关于栈的基本语句需要牢记:
                                 empty()   堆栈为空则返回真
                                 pop()       移除栈顶元素
                                 push()     增加元素到栈顶
                                 size()       返回栈中元素数目
                                 top()        返回栈顶元素
class Solution {
public:
    bool isValid(string s) {
        int n = s.size();
        // 如果字符串长度为奇数,直接返回false
        if (n % 2 == 1) {
            return false;
        }
        // 根据题干条件创建映射
        unordered_map<char, char> pairs = {
            {')', '('},  // 注意:键为右括号,值为左括号
            {']', '['},
            {'}', '{'}
        };
        stack<char> stk;  // 栈特点:先进后出
        for (char ch: s) {  // 遍历字符串s
            // 限制条件:遍历所有右括号
            if (pairs.count(ch)) {  // 查找键ch,若存在,则返回1,反之返回0
                // 栈为空 或者 栈顶的左括号匹配不到当前的右括号,返回false
                if (stk.empty() || stk.top() != pairs[ch]) {
                    return false;
                }
                stk.pop();  // 匹配成功后,移除栈顶元素
            }
            // 添加左括号到栈中
            else {
                stk.push(ch);  // 在栈顶增加元素
            }
        }
        return stk.empty();  // 若所有的括号都匹配完毕,那么stk.empty()为true
    }
};

 >>> 如有疑问,欢迎评论区一起探讨。

猜你喜欢

转载自blog.csdn.net/qq_54185421/article/details/129517787