leetcode解题思路分析(二)8-14题

2024-09-05 05:18
文章标签 leetcode 分析 14 解题 思路

本文主要是介绍leetcode解题思路分析(二)8-14题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  1. 请你来实现一个 atoi 函数,使其能将字符串转换成整数。

首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。

当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。

该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。

注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。

在任何情况下,若函数不能进行有效的转换时,请返回 0。

说明:

假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,请返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。

不算优秀的做法

class Solution {
public:int myAtoi(string str) {int result = 0;stringstream ss;ss << str;ss >> result;return result;}
};

先排除特殊情况,再逐步检查

class Solution {
public:int myAtoi(string str) {int res = 0;int i = 0;int flag = 1;// 1. 检查空格while (str[i] == ' ') { i++; }// 2. 检查符号if (str[i] == '-') { flag = -1; }if (str[i] == '+' || str[i] == '-') { i++; }// 3. 计算数字while (i < str.size() && isdigit(str[i])) {int r = str[i] - '0';// ------ 4. 处理溢出,这是关键步骤 ------if (res > INT_MAX / 10 || (res == INT_MAX / 10 && r > 7)) { return flag > 0 ? INT_MAX : INT_MIN;}// ------------------------------------res = res * 10 + r;i++;}return flag > 0 ? res : -res;}
};
  1. 判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

本题有两种做法:1.转化为字符串再进行检索 2. 获取一半的整数和另一半比较。第二种空间使用更少,更优

class Solution {
public:bool isPalindrome(int x) {// 特殊情况:// 如上所述,当 x < 0 时,x 不是回文数。// 同样地,如果数字的最后一位是 0,为了使该数字为回文,// 则其第一位数字也应该是 0// 只有 0 满足这一属性if(x < 0 || (x % 10 == 0 && x != 0)) {return false;}int revertedNumber = 0;while(x > revertedNumber) {revertedNumber = revertedNumber * 10 + x % 10;x /= 10;}// 当数字长度为奇数时,我们可以通过 revertedNumber/10 去除处于中位的数字。// 例如,当输入为 12321 时,在 while 循环的末尾我们可以得到 x = 12,revertedNumber = 123,// 由于处于中位的数字不影响回文(它总是与自己相等),所以我们可以简单地将其去除。return x == revertedNumber || x == revertedNumber/10;}
};
  1. 正则表达式匹配
    给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘*’ 的正则表达式匹配。

‘.’ 匹配任意单个字符
‘*’ 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。

说明:

s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *。

采用从后向前检索的方式进行

class Solution {
public:vector<vector<int> > memo;int dfs(const string& s, const string& p, int i, int j) {if (i == s.size()) return j == p.size() ? 1 : -1;if (j == p.size()) return i == s.size() ? 1 : -1;if (memo[i][j] != 0) return memo[i][j];if (j == p.size() - 1 || p[j + 1] != '*') {if (p[j] == '.' || p[j] == s[i]) {memo[i][j] = dfs(s, p, i + 1, j + 1);return memo[i][j];}} else {if (dfs(s, p, i, j + 2) > 0) {memo[i][j] = 1;return memo[i][j];}if (p[j] == '.' || p[j] == s[i]) {bool t = dfs(s, p, i + 1, j + 2) > 0 || dfs(s, p, i + 1, j) > 0;memo[i][j] = t ? 1 : -1;return memo[i][j];}}memo[i][j] = -1;return memo[i][j];}bool isMatch(string s, string p) {s += '#';p += '#';memo = vector<vector<int> >(s.size(), vector<int>(p.size(), 0));return dfs(s, p, 0, 0) > 0;}
};
  1. 盛最多水的容器
    给定 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

说明:你不能倾斜容器,且 n 的值至少为 2。

最简单无脑的做法:直接双层循环:

class Solution {
public:int maxArea(std::vector<int>& height) {int i = 0;int j = 0;int capacity = 0;int size = height.size();while(i < size - 1){j = i + 1;while (j < size){int tmpCap = std::min(height[i], height[j]) * (j - i);if (tmpCap >= capacity){capacity = tmpCap;}j++;}i++;}return capacity;}
};

第二种思路是:形成的区域受限制于较短的那条,同时距离越远则可能的收益越大。因此我们从最左和最右开始检索,移动较短的那端。

    int maxArea(vector<int> &height){int result = 0;int heightSize = int(height.size());int leftIndex = 0;int rightIndex = heightSize - 1;while (leftIndex != rightIndex){int tmpHeight;int tmpWidth = rightIndex - leftIndex;//短的一侧向中间移动if (height[leftIndex] < height[rightIndex]){tmpHeight = height[leftIndex];leftIndex++;}else{tmpHeight = height[rightIndex];rightIndex--;}int tmpResult = tmpWidth * tmpHeight;if (tmpResult > result){result = tmpResult;}}return result;}
  1. 整数转罗马数字

最简单的方式就是将罗马数字存储在数组中,然后依次查找填表即可,简单粗暴但是低效而且不美观:

class Solution {
public:string intToRoman(int num){string result;vector<string> tmpVec1 = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};vector<string> tmpVec2 = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};vector<string> tmpVec3 = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};vector<string> tmpVec4 = {"", "M", "MM", "MMM"};vector<vector<string>> store = {tmpVec1, tmpVec2, tmpVec3, tmpVec4};result.append(store[3][num / 1000 % 10]);result.append(store[2][num / 100 % 10]);result.append(store[1][num / 10 % 10]);result.append(store[0][num % 10]);return result;}
};

更好的做法是贪心算法:存储一个特殊数字的情况,挨个查找并减少数字

class Solution {
public:string intToRoman(int num){string result;int store[] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};string strs[] = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};//贪心法for (int i = 0; i < 13; i++){while (num >= store[i]){result.append(strs[i]);num -= store[i];}}return result;}
};
  1. 罗马数字转整数
class Solution {
public:int romanToInt(string s) {unordered_map<char, int> mp;mp['I'] = 1;mp['V'] = 5;mp['X'] = 10;mp['L'] = 50;mp['C'] = 100;mp['D'] = 500;mp['M'] = 1000;int pos = 0, neg = 0;for (int i = 0;i < s.size()-1;++i){if (mp[s[i]] < mp[s[i+1]])neg -= mp[s[i]];elsepos += mp[s[i]];}pos += mp[s.back()];return pos + neg;           }
};
  1. 最长公共前缀
    编写一个函数来查找字符串数组中的最长公共前缀。
    如果不存在公共前缀,返回空字符串 “”。

最简单的办法就是循环迭代查找,该方法时间复杂度和空间复杂度均很低,而且容易想到。除此之外,还可以使用分治的方法,但是结果并没有更优秀

class Solution {
public:string longestCommonPrefix(vector<string>& strs) {int count = 0;int size = 0;char c;bool end = true;string ret;if (strs.size() == 0)return ret;vector<string>::iterator iter;iter = strs.begin();while (iter != strs.end()){if (size < (*iter).size())size = (*iter).size();iter++;}while (end){iter = strs.begin();c = (*iter)[count];while ((iter + 1) != strs.end()){iter++;if (c != (*iter)[count]){end = false;break;}}if (end){ret += c;count++;}	if (count >= size)return ret;}return ret;}
};

这篇关于leetcode解题思路分析(二)8-14题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1138046

相关文章

Springboot中分析SQL性能的两种方式详解

《Springboot中分析SQL性能的两种方式详解》文章介绍了SQL性能分析的两种方式:MyBatis-Plus性能分析插件和p6spy框架,MyBatis-Plus插件配置简单,适用于开发和测试环... 目录SQL性能分析的两种方式:功能介绍实现方式:实现步骤:SQL性能分析的两种方式:功能介绍记录

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

linux进程D状态的解决思路分享

《linux进程D状态的解决思路分享》在Linux系统中,进程在内核模式下等待I/O完成时会进入不间断睡眠状态(D状态),这种状态下,进程无法通过普通方式被杀死,本文通过实验模拟了这种状态,并分析了如... 目录1. 问题描述2. 问题分析3. 实验模拟3.1 使用losetup创建一个卷作为pv的磁盘3.

C#使用DeepSeek API实现自然语言处理,文本分类和情感分析

《C#使用DeepSeekAPI实现自然语言处理,文本分类和情感分析》在C#中使用DeepSeekAPI可以实现多种功能,例如自然语言处理、文本分类、情感分析等,本文主要为大家介绍了具体实现步骤,... 目录准备工作文本生成文本分类问答系统代码生成翻译功能文本摘要文本校对图像描述生成总结在C#中使用Deep

Redis主从/哨兵机制原理分析

《Redis主从/哨兵机制原理分析》本文介绍了Redis的主从复制和哨兵机制,主从复制实现了数据的热备份和负载均衡,而哨兵机制可以监控Redis集群,实现自动故障转移,哨兵机制通过监控、下线、选举和故... 目录一、主从复制1.1 什么是主从复制1.2 主从复制的作用1.3 主从复制原理1.3.1 全量复制

Redis主从复制的原理分析

《Redis主从复制的原理分析》Redis主从复制通过将数据镜像到多个从节点,实现高可用性和扩展性,主从复制包括初次全量同步和增量同步两个阶段,为优化复制性能,可以采用AOF持久化、调整复制超时时间、... 目录Redis主从复制的原理主从复制概述配置主从复制数据同步过程复制一致性与延迟故障转移机制监控与维

Redis连接失败:客户端IP不在白名单中的问题分析与解决方案

《Redis连接失败:客户端IP不在白名单中的问题分析与解决方案》在现代分布式系统中,Redis作为一种高性能的内存数据库,被广泛应用于缓存、消息队列、会话存储等场景,然而,在实际使用过程中,我们可能... 目录一、问题背景二、错误分析1. 错误信息解读2. 根本原因三、解决方案1. 将客户端IP添加到Re

Redis主从复制实现原理分析

《Redis主从复制实现原理分析》Redis主从复制通过Sync和CommandPropagate阶段实现数据同步,2.8版本后引入Psync指令,根据复制偏移量进行全量或部分同步,优化了数据传输效率... 目录Redis主DodMIK从复制实现原理实现原理Psync: 2.8版本后总结Redis主从复制实

JAVA利用顺序表实现“杨辉三角”的思路及代码示例

《JAVA利用顺序表实现“杨辉三角”的思路及代码示例》杨辉三角形是中国古代数学的杰出研究成果之一,是我国北宋数学家贾宪于1050年首先发现并使用的,:本文主要介绍JAVA利用顺序表实现杨辉三角的思... 目录一:“杨辉三角”题目链接二:题解代码:三:题解思路:总结一:“杨辉三角”题目链接题目链接:点击这里

锐捷和腾达哪个好? 两个品牌路由器对比分析

《锐捷和腾达哪个好?两个品牌路由器对比分析》在选择路由器时,Tenda和锐捷都是备受关注的品牌,各自有独特的产品特点和市场定位,选择哪个品牌的路由器更合适,实际上取决于你的具体需求和使用场景,我们从... 在选购路由器时,锐捷和腾达都是市场上备受关注的品牌,但它们的定位和特点却有所不同。锐捷更偏向企业级和专