以后每10天组一篇blog
2018.9.13 Q14(2018.9.21 补)
没什么难度,先找了最短的单词长度,以此来限制比较次数,初衷是源于磨刀不误砍柴工的想法。但其实再想想,不一定需要先计算一边每个单词的长度。匹配到不一样的自然就退出了。倒是这样做能尽可能的减小所占空间,不过二者都是O(1)。
2018.9.14 Q7
涉及到了int在内存中是如何存储的,查查资料。
计算机中所有的整型数据都是以补码来存的(正数补码是本身,负数补码是原码取反再加一)。
Java基本数据类型,byte是1B,char是2B,short 是2B,int 是4B,float是4B,double是8B,long是8B。因此int 可表示的最大数为2^31-1(Java中用 Integer.MAX_VALUE 表示),可表示的最小数为 -2^31(Integer.MIN_VALUE)。
本题中如何判断是否溢出呢?有两种思路:一是对操作后的数进行逆操作,看是否等于原来的数;二是用 long 型做运算,若结果超出了 int 型可表示的范围,则认为溢出。
什么时候会发生溢出呢?以8位的数据为例,119正常(小于127),但反转之后变为911,溢出。
2018.9.18 Q8
有要实现的任务后就一步一步逐条去实现。先测试正常的数据用例,再想想溢出(上下溢)、边界等特殊情况。若判断一定溢出(数据位过长),则可以直接结束循环执行return;特殊测试用例如 数字开始前有多个0,那么就不能用数据位的多少来判断,需要在拆出数据前将之前多余的0去掉。
贴一下代码,下面的说明需要。
int myAtoi(char* str) {
int i=0,sym=1, res=0;
while(str[i]==' '){
i++;
}
switch(str[i]){
case '+': sym=1; i++; break;
case '-': sym=-1;i++; break;
}
if(str[i]<48&&str[i]>57){
return 0;
}
char tmp[13];
while(str[i]==48){
i++;
}
int k=0;
while(str[i]>=48&&str[i]<=57&&k<12){
tmp[k]=str[i];
i++;
k++;
}
for(i=0;i<k;i++){
int t =res*10+tmp[i]-'0';
if(t/10==res){
res=t;
}
else{
switch(sym){
case 1: return INT_MAX; break;
case -1:return INT_MIN; break;
}
}
}
res = sym==1?res:-res;
return res;
}
刚开始想用Java做,但和C的语法会记混,而且之前形成的C的思路(比如对数组的操作)已经比较熟悉,感觉比Java更直接。以后可以试试两种都做,熟练后选择最合适的语言解题。或者可以了解一下C++,,,
明天学习一下正则表达式,这道题用正则表达式不知道好不好做。
2018.9.20 提取匹配正则表达式的部分:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
String str = "-5464 1asdvv";
String reg = "^[+|-]?\\d+";
Pattern pattern = Pattern.compile (reg);
Matcher matcher = pattern.matcher (str);
while (matcher.find ())
{
System.out.println (matcher.group ());
}
接着该转成int并判断是否溢出了。看到一篇解释string转int 的帖子https://my.oschina.net/u/3284953/blog/1621263,指出的问题一针见血非常正确。在普通的类型转换里,的确需要考虑128算溢出但-128不算溢出的问题。至于判断溢出的方法,通过INT_MIN逆着算肯定没问题,因为所有运算的数字都没有溢出,结果一定是正确的;
那原来判断溢出的方法对吗?来做个证明。
接着联想到做过的一个题,如果是翻转一个int数据,溢出需要这样判断吗?以8位为例,可存储的值为[ -128, 127] ,翻转后的数据可能会到达边界值吗?在8位的数据来看,应该是不会取到边界值的,所以可以通过正着算判断溢出。但当然,从边界来算判断溢出的方法是绝对不会出错的。
2018.9.19 Q28
Java有写好的函数,直接拿来用算不算犯规啊/捂脸。而且一样的代码执行耗时可能不一样。
C语言手动实现了一下,耗时比用indexOf( ) 还短。
2018.9.21 Q38
思路是很快就想出来了,但数组初始化的时候始终编译不通过,究其原因还是数组和指针的概念没有彻底弄清。另外,对于计算中可能出现的最大的数字长度没有估计,日后做题应该提前考虑所申请的数组长度应该如何确定。
2018.9.23 Q237
初始思路是对链表进行遍历,找到待删除节点的前一个节点,然后将待删除节点删除。这样其实是忽略了题目中给定的“待删除的节点不是最末端的节点”这一条件。而在按初始思路做时,因为不知道链表的初始节点(head),所以去搜了搜别人的解法,学习到了新的、更简洁的思路:不需要遍历,直接将待删除节点的下一个节点赋给待删除节点,然后将待删除节点的下一节点删除,省时省力,完美!