首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >程序员进阶之算法练习(四十九)LeetCode

程序员进阶之算法练习(四十九)LeetCode

作者头像
落影
修改2023-09-24 14:26:03
4200
修改2023-09-24 14:26:03
举报
文章被收录于专栏:落影的专栏落影的专栏

正文

题目1.两数之和

题目链接 题目大意: 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

示例: 给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1]

题目解析: 先不考虑复杂度,直接两个for循环,对于每个数字nums[i],寻找target-nums[i]是否也在数组; 这样的时间复杂度为O(N^2),可以牺牲一些空间来换取更快的速度:比如说把已经出现过的数字用hash表直接存下来,这样下次用hash表直接循环该数字是否存在。 题目的要求还要输出数组下标,那么可以用hash表的值来存数组下标。

class Solution {
    unordered_map<int, int> mp;
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        mp.clear();
        vector<int> ans;
        
        for (int i = 0; i < nums.size(); ++i) {
            if (mp[target - nums[i]]) {
                ans.push_back(i);
                ans.push_back(mp[target - nums[i]] - 1);
                break;
            }
            mp[nums[i]] = i + 1;
        }
        return  ans;
    }
}leetcode;
2.整数反转

题目链接 题目大意: 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。

示例 1: 输入: 123 输出: 321

示例 2: 输入: -123 输出: -321

示例 3: 输入: 120 输出: 21

注意: 假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231, 231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。

题目解析: 将负号单独拿出来考虑,只考虑整数的翻转。

因为最终结果可能超过int范围,那么可以用long long来处理。

class Solution {
public:
   int reverse(int x) {
       lld ret = 0, flag = x < 0 ? -1 : 1;
       lld tmp = abs(x), sz = 1;
       while (tmp) {
           ret = tmp % 10 + ret * 10;
           tmp /= 10;
       }
       lld intLeft = -(1LL << 31), intRight = (1LL << 31) - 1;
       if (ret < intLeft || ret > intRight) {
           ret = 0;
       }
       return (int)ret * flag;
   }
}leetcode;

注意: 1在位移的时候,是按int来处理的,需要改成1LL;

3.字符串转换整数 (atoi)

题目链接 题目大意: 请你来实现一个 atoi 函数,使其能将字符串转换成整数。 首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。接下来的转化规则如下: 如果第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字字符组合起来,形成一个有符号整数。 假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成一个整数。 该字符串在有效的整数部分之后也可能会存在多余的字符,那么这些字符可以被忽略,它们对函数不应该造成影响。 注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换,即无法进行有效转换。 在任何情况下,若函数不能进行有效的转换时,请返回 0 。

提示: 本题中的空白字符只包括空格字符 ' ' 。 假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,请返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。

示例 1: 输入: "42" 输出: 42

示例 2: 输入: " -42" 输出: -42 解释: 第一个非空白字符为 '-', 它是一个负号。 我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。

示例 3: 输入: "4193 with words" 输出: 4193 解释: 转换截止于数字 '3' ,因为它的下一个字符不为数字。

示例 4: 输入: "words and 987" 输出: 0 解释: 第一个非空字符是 'w', 但它不是数字或正、负号。 因此无法执行有效的转换。

示例 5: 输入: "-91283472332" 输出: -2147483648 解释: 数字 "-91283472332" 超过 32 位有符号整数范围。 因此返回 INT_MIN (−231) 。

题目解析: 按照题目的要求实现,拆分出来具体的过程。 1、还未进行数字转换的状态,hasConvert=false,此时可以允许空格跳过; 2、遇到+、-、数字之后,hasConvert=true,不允许空格跳过,遇到非数字符号结束转化; 3、符号和数字分开处理,超过int大小分别出来,可以用long long来暂存;

整体代码不复杂。

class Solution {
public:
   int myAtoi(string str) {
       long long ret = 0;
       int flag = 0; // 前置符号, 0表示还没放过, 1 是正数,-1是负数
       bool hasConvert = false;
       for (int i = 0; i < str.length(); ++i) {
           if (str[i] == '-' || str[i] == '+') {
               if (flag) {
                   return flag * ret;
               }
               flag = str[i] == '-' ? -1 : 1;
               hasConvert = true;
           }
           else if (str[i] >= '0' && str[i] <= '9') {
               if (!flag) flag = 1;
               hasConvert = true;
               ret = ret * 10 + str[i] - '0';
               if (flag * ret < -(1LL << 31)) {
                   return -(1LL << 31);
               }
               if (flag * ret > (1LL << 31) - 1) {
                   return (1LL << 31) - 1;
               }
           }
           else if (!hasConvert && str[i] == ' ') {
               continue;
           }
           else {
               return flag * ret;
           }
       }
       return flag * ret;
   }
}lc;

注意: 题目很坑,+1 这种数据也没有说明; +03这种,会认为是数字3,题目的严谨程度较差;

4.回文数

题目链接 题目大意: 判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

示例 1: 输入: 121 输出: true

示例 2: 输入: -121 输出: false 解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。

示例 3: 输入: 10 输出: false 解释: 从右向左读, 为 01 。因此它不是一个回文数。

题目解析: 将数字转成字符串,然后开始从左右两边开始遍历,如果遇到不一样的字符串则输出false; 如果没有发现不一样的字符,则左右边界递进,则最后输出true;

class Solution {
public:
    bool isPalindrome(int x) {
        char s[20];
        sprintf(s, "%d", x);
        int end = strlen(s) - 1, st = 0;
        while (st < end) {
            if (s[st] != s[end]) {
                return false;;
            }
            ++st;
            --end;
        }
        return true;
    }
}leetcode;

思考: 如果是要在字符串中找出最长的回文串呢?

5.最长公共前缀

题目链接 题目大意: 编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 ""。

示例 1: 输入: ["flower","flow","flight"] 输出: "fl"

示例 2: 输入: ["dog","racecar","car"] 输出: ""

解释: 输入不存在公共前缀。 说明: 所有输入只包含小写字母 a-z 。

题目解析: 前缀和,直接for循环遍历。

class Solution {
public:
   string longestCommonPrefix(vector<string>& strs) {
       string ret;
       while (true && strs.size()) {
           for (int i = 0; i < strs.size(); ++i) {
               if (strs[i].size() < ret.length() + 1) {
                   return ret;
               }
               if (i > 0 && strs[i][ret.length()] != strs[0][ret.length()]) {
                   return ret;
               }
           }
           ret.push_back(strs[0][ret.length()]);
       }
       return ret;
   }
}leetcode;

注意: vector为空的情况。

总结

题目1,需要用hash来降低复杂度,unordered_map是很不错的hash选项; 题目2,反过来计算整数即可,边界问题是int范围,改一改就是很不错的题目; 题目3,这是一道题意比较复杂的模拟题,但是拆分出几点规则之后,代码还是比较清爽; 题目4,直接转成字符串,走字符串匹配;(思考题 O(N)回文串算法-Manacher) 题目5,直接遍历计算,算法的复杂度也没有太多优化空间;

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 正文
    • 题目1.两数之和
      • 2.整数反转
        • 3.字符串转换整数 (atoi)
          • 4.回文数
            • 5.最长公共前缀
            • 总结
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档