LeetCode 8_String to Integer (atoi)

这几天时间比较宽松,尽量多整理几道吧,希望每个人的努力都能换来想要的生活。。。

这是leetcode第八题,说实在的,本人感觉是出的不如前面几道,这道题怎么说呢,很平常,但一些特殊情况考虑的很多很杂散,不像是在做算法,倒像是在玩儿“找茬儿”,我着重说点有用的吧,原题如下:

Implement atoi to convert a string to an integer.

Hint: Carefully consider all possible input cases. If you want a challenge, please do not see below and ask yourself what are the possible input cases.

Notes: It is intended for this problem to be specified vaguely (ie, no given input specs). You are responsible to gather all the input requirements up front.

题目的要求可以用一句话说明白:把字符串转化为整数。

这个想对于一点儿编程基础的人都不会有什么问题,而题目中的Notes也说了,这个题目主要是考察你对“各种”输入的考虑是否周全。字符串转数字大家时并不是都能转化的,这一点大家都能理解。比如说字符串中有不是数字的字符,再进一步可能会考虑的有负数,再再进一步可能会考虑到转化溢出的情况。个人认为能考虑到这些基本就可以了,不过通过编程发现其实要通过验证还要处理很多“变态输入”。比如,字符串中有空格,这种情况本来就应该是每个情况都有自己处理方式的,但题目中并没有这样的具体要求,通过实验发现题目是要求把前面的空格忽略,然后中间的空格当做一般的非数字字符处理。而对于非数字字符的处理也挺奇怪,遇到非数字字符时转化停止,只算前面的数字就可以了,总之这种情况很多,其实只要要求明确了,这些并不算难,但题目中没有要求,要通过实验得到,好像评判标准也是凑出来的,好了不吐槽了,上代码吧。

class Solution {
public:
    int myAtoi(string str) {
		//滤除空格
		string str1;
		string::iterator it=str.begin();
		for(;*it==' ';++it);
		for(string::iterator it2=it;it2!=str.end();++it2)
		{
			str1.push_back(*it2);
		}

		str=str1;
		//确定是否有正负号
		bool neg=false;
		if(str[0]=='-')//前面有负号
			neg=true;
		bool pos=false;
		if(str[0]=='+')//前面有正号
			pos=true;
		int len=str.size();
		int result=0;
		for(int i=(neg||pos)?1:0;i<len;++i)
		{
			if(str[i]<'0'||str[i]>'9')//不是数字,返回
				return neg?(-1*result):result;
			if(result > INT_MAX/10)return neg?INT_MIN:INT_MAX;
			result *= 10;
			if(result > INT_MAX-str[i]+'0')return neg?INT_MIN:INT_MAX;
			result += str[i]-'0';
		}
          return neg?(-1*result):result;
    }
};
里面的各种“补丁”语句大家没必要纠结,大体思路明白就好了,注意并学会这几点就好:

(1)“-”和“+”。一般人可能会想到符号而忘了正号,这种“灯下黑”的错误还是要注意一下的。

(2)不是数字的情况。这个大家一定要考虑到,这是转化数字最基本的要求嘛。

(3)溢出判断。这一点要在这里着重说一下,并为上一题(第七题)的错误作出改正。

溢出判断也是数字转化过程中要注意的很重要的一点,严谨的说,每一次算术都有溢出的可能,所以每次运算都应该进行溢出判断。当然实际编程过程中溢出毕竟只是少数情况,所以一般是不需要进行判断的,但这种转化的题目就必须要考虑了,因为这不是一个实际中的有意义的数值,而是通过机械式的转化得到的一种形式或者成为符号。

那该怎么进行溢出判断呢?是在运算前,还是运算后?是利用符号改变还是大小改变?这些情况很多,我们先来看一下溢出的本质:

我们知道(我假设你知道,不知道的话可以查看相关资料)数字在机器中,也可以说在电脑中,是用补码表示的,那数字的补码是怎么表示的呢,又是怎么溢出的呢,我们不去讨论里面的各种原理,只是来看一些实例:假设某种型的存储空间为4为二进制编码,我们知道,它一共可以表示2^4=16种不同的数字,我们就让它来表示-8—7这16个数字。-8—7的原码、反码和补码列于下表:



从这个图中可以看到,-0和+0的原码是不同的,但补码是相同的,所以“多出来“的位置正好给了-8,而没有+8。另外通过补码一列我们可以总结出这样的规律:补码从0000到1111,对应的数字为从0到7然后突变成-8然后到-1。而这里的突变点,就是我们所说的溢出点,也就是说7再加1就溢出了(本来应该是8,变成-8了),而-8再减1也会溢出(本来应该是-9变成7了)。从突变点看貌似可以通过符号的改变判断是否溢出,但仔细思考一下会发现,这只是”小的“溢出,如果7再加16呢?它还是7!所以这种方法是不对的。我们在上一题中提到了用”还原法“,当时并没有出现错误且通过了验证,但通过今天的分析我们知道,其实上次的成功只是侥幸罢了。能还原的并不一定没有溢出,当然不能还原的是一定溢出了,这个例子就不用再举了吧。那么话说回来,我们该怎么判断溢出呢?

通过分析可知,溢出是一个很随意的过程,溢出的结果也是很难捉摸。所以我们应该把溢出扼杀在摇篮里,也就是说要把”溢出后判断“的思维改为”判断要溢出“。说直白点儿,就是在运算前判断是否会溢出,有了这个思路就容易入手了,具体的语句已经写在程序里了。如果你还是会写成if(result*10>INT_MAX),那证明,怎么说呢,你要走的路还很长啊,加油吧。

明天是抗战70周年的纪念日,在此向我们的革命先烈致以敬意,也希望每个人都能珍惜来之不易的和平,珍惜来之不易的幸福生活。

题目描述: 给定一个字符串,请将字符串里的字符按照出现的频率降序排列。 示例 1: 输入: "tree" 输出: "eert" 解释: 'e'出现两次,'r'和't'都只出现一次。因此'e'必须出现在'r'和't'之前。此外,"eetr"也是一个有效的答案。 示例 2: 输入: "cccaaa" 输出: "cccaaa" 解释: 'c'和'a'都出现三次。此外,"aaaccc"也是有效的答案。注意"cacaca"是不正确的,因为相同的字母必须放在一起。 示例 3: 输入: "Aabb" 输出: "bbAa" 解释: 此外,"bbaA"也是一个有效的答案,但"Aabb"是不正确的。注意'A'和'a'被认为是两种不同的字符。 Java代码如下: ``` import java.util.*; public class Solution { public String frequencySort(String s) { if (s == null || s.length() == 0) { return ""; } Map<Character, Integer> map = new HashMap<>(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); map.put(c, map.getOrDefault(c, 0) + 1); } List<Map.Entry<Character, Integer>> list = new ArrayList<>(map.entrySet()); Collections.sort(list, (o1, o2) -> o2.getValue() - o1.getValue()); StringBuilder sb = new StringBuilder(); for (Map.Entry<Character, Integer> entry : list) { char c = entry.getKey(); int count = entry.getValue(); for (int i = 0; i < count; i++) { sb.append(c); } } return sb.toString(); } } ``` 解题思路: 首先遍历字符串,使用HashMap记录每个字符出现的次数。然后将HashMap转换为List,并按照出现次数从大到小进行排序。最后遍历排序后的List,将每个字符按照出现次数依次添加到StringBuilder中,并返回StringBuilder的字符串形式。 时间复杂度:O(nlogn),其中n为字符串s的长度。遍历字符串的时间复杂度为O(n),HashMap和List的操作时间复杂度均为O(n),排序时间复杂度为O(nlogn),StringBuilder操作时间复杂度为O(n)。因此总时间复杂度为O(nlogn)。 空间复杂度:O(n),其中n为字符串s的长度。HashMap和List的空间复杂度均为O(n),StringBuilder的空间复杂度也为O(n)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值