[算法] 4.力扣题目讲解

前缀和


前缀和是一个数组,多次询问区间和的时候,空间换时间
前缀和从num[1]开始存,num[0]空出来防止访问越界

7. 整数反转

在这里插入图片描述

class Solution {
public:
    int reverse(int x) {
        int ans = 0;
        while (x) {
            // 输出0的情况特判
            if (ans > INT_MAX / 10 || ans < INT_MIN / 10 || // ans大或小:*10超出上界或下界
                ans == INT_MAX / 10 && x % 10 > 7 || // ans大:加上个位超出上界
                ans == INT_MIN / 10 && x % 10 < -8 // ans小:加上个位超出下界
                ) return 0;
            ans = ans * 10 + x % 10;
            x /= 10;
        }
        return ans;
    }
};
  1. 假设环境不允许存储 64 位整数(有符号或无符号),意思是只能使用int型(区别于第9题)
  2. int范围:-2147483648 ~ 2147483647[-231 ~ 231-1]

9. 回文数

class Solution {
public:
    bool isPalindrome(int x) {
        if (x < 0) return false;
        long long raw = x, t = 0;
        while (x) {
            t = t * 10 + x % 10;
            x /= 10;
        }
        return t == raw;
    }
};
  1. int 反转防止越界,必须用 long long 定义 t

13. 罗马数字转整数

class Solution {
public:
    int romanToInt(string s) {
        int ans = 0;
        for (int i = 0; i < s.size(); i++) {
            if (s[i] == 'I') {
                if (s[i + 1] == 'V' || s[i + 1] == 'X') { // 特殊规则的2种情况
                    ans += (s[i + 1] == 'V' ? 4 : 9); // 三目运算符
                    i++; // i后移
                } else { 
                    ans += 1;
                }
            } else if (s[i] == 'X') {
                if (s[i + 1] == 'L' || s[i + 1] == 'C') {
                    ans += (s[i + 1] == 'L' ? 40 : 90);
                    i++;
                } else {
                    ans += 10;
                }
            } else if (s[i] == 'C') {
                if (s[i + 1] == 'D' || s[i + 1] == 'M') {
                    ans += (s[i + 1] == 'D' ? 400 : 900);
                    i++;
                } else {
                    ans += 100;
                }
            } else if (s[i] == 'V') {
                ans += 5;
            } else if (s[i] == 'L') {
                ans += 50;
            } else if (s[i] == 'D') {
                ans += 500;
            } else {
                ans += 1000;
            }
        }
        return ans;
    }
};
  1. 用switch或 if 都可以实现
  2. if实现时用了三目运算符

14. 最长公共前缀

class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) { // vector<string> 可以理解为字符串动态数组
        if (strs.size() == 0) return ""; // 返回空串
        string ans = strs[0]; // ans赋值为第一个串
        for (int i = 1; i < strs.size(); i++) {
            string t = ans;
            ans = ""; // 置为空串
            for (int j = 0; j < strs[i].size() && j < t.size(); j++) { // 两个串中必须有字符
                if (strs[i][j] == t[j]) {
                    ans += t[j];
                } else {
                    break;
                }
            }
            if (ans == "") break; // 某一轮后ans串为空,不必判断后续
        }
        return ans;
    }
};
  1. 字符串为空,访问下标为0的字符串会报错
  2. j是按位遍历第i个字符串,同时j要小于现有的t的长度

26. 删除有序数组中的重复项

在这里插入图片描述

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        if (nums.size() == 0) return 0;
        // 第一个肯定不会重复
        int last = nums[0], pos = 1; // last上一个存好的数字,pos当前存到了第几个数
        for (int i = 1; i < nums.size(); i++) {
            if (nums[i] != last) {
                last = nums[i];
                nums[pos] = nums[i];
                pos++;
            }
        }
        return pos;
    }
};
  1. 第一个数一定不会重复,删掉后面的数即可
  2. 有序说明相等的数在一起,本题无序也可以,但是要保证相等的数在一起

27. 移除元素

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        if (nums.size() == 0) return 0;
        int pos = 0;
        for (int i = 0; i < nums.size(); i++) {
            if (nums[i] != val) {
                nums[pos] = nums[i];
                pos++;
            }
        }
        return pos;
    }
};
  1. 遍历数组判断val,不是val的往前存
  2. 26,27题就是遍历一次的问题

35. 搜索插入位置

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        if (nums[nums.size() - 1] < target) return nums.size(); // 特判最大值<taregt
        int l = 0, r = nums.size() - 1;
        while (l != r) {
            int mid = (l + r) / 2;
            if (nums[mid] >= target) r = mid; // 返回第一个大于等于它的值的下标,00001111
            else l = mid + 1;
        }
        return l;
    }
};
  1. 返回第一个大于等于它的位置
  2. 添加一个特判,大于数组最大值时输出nums.size()
  3. 添加一个极大值在数组尾部,进行二分

38. 外观数列

  1. 2个数组来回倒,通过 swap(a, b) 两个指针
  2. cnt计数

58. 最后一个单词的长度

  1. 思路:2个指针从后往前遍历,一个找到第一个不为 “” 的下标,另一个从当前位置继续找第一个为 ""的下标,长度是 r - l
  2. l 和 r 都初始化为-1
    r 初始化为-1是:字符串只有1个字符时指向下标0,会产生歧义;出了循环 r 还为 -1,表示空串直接输出0
    l 初始化为-1是:字符串只有1个单词时,l 值还是为-1,充当下标0前面的“”(空格)
  3. 本题要求输出的话有一个讨巧的方法:while 循环 cin 时,最后直接输出 s.size()

53. 最大子序和

  1. 经典动态规划
  2. ans[i] 以 i 结尾的最大连续和,不需要维护一个数组,只需要维护一个变量就够了

66. 加一

  1. 处理进位

67. 二进制求和

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
题目描述: 给你两个版本号 version1 和 version2 ,请你比较它们。 版本号由一个或多个修订号组成,各修订号由一个 '.' 连接。每个修订号由多位数字组成,可能包含前导零。每个版本号至少包含一个字符。修订号从左到右编号,下标从0开始,最左边的修订号下标为0 ,下一个修订号下标为1,以此类推。例如,2.5.33 和 0.1 都是有效的版本号。 比较版本号时,请按从左到右的顺序依次比较它们的修订号。比较修订号时,只需比较忽略任何前导零后的整数值。也就是说,修订号1和修订号001相等。如果版本号没有指定某个下标处的修订号,则该修订号视为0。例如,版本1.0 小于版本1.1,因为它们下标为0的修订号相同,而下标为1的修订号分别为0和1,0 < 1。 返回规则如下: 如果 version1 > version2 返回 1, 如果 version1 < version2 返回 -1, 否则返回 0。 示例 1: 输入:version1 = "1.01", version2 = "1.001" 输出:0 解释:忽略前导零,"01" 和 "001" 都表示相同的整数 "1" 示例 2: 输入:version1 = "1.0", version2 = "1.0.0" 输出:0 解释:version1 没有指定下标为 2 的修订号,即视为 "0" 示例 3: 输入:version1 = "0.1", version2 = "1.1" 输出:-1 解释:version1 中下标为 0 的修订号是 0,version2 中下标为 0 的修订号是 1 。0 < 1,所以 version1 < version2 示例 4: 输入:version1 = "1.0.1", version2 = "1" 输出:1 示例 5: 输入:version1 = "7.5.2.4", version2 = "7.5.3" 输出:-1 提示: 1 <= version1.length, version2.length <= 500 version1 和 version2 仅包含数字和 '.' version1 和 version2 都是 有效版本号

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值