LeetCode刷题思路

篇前语:刻意练习是走向卓越的必经之路!
371题:求两个整数的和,不允许使用+-运算符
7.25思路:除+-外其他运算符没有限制,如移位,乘除等。首先明确,乘除是不能代替加减运算的,移位是单目运算符,也不适用。因此通过运算符求和可能行不通。其次,调用C语言内置math函数sum本质上依然使用了+-。由此引出一个关键问题:在leetcode上能不能使用已有的函数,比如此题,如果设计两个字符串,其长度分别是两个整数值,合并字符串后求取其长度相当于间接求和两个整数。但出题人意图明显不在此,猜测答案与数据结构有关。
讨论区解决方案:1,初始化一个vector,内有2个int元素a和b,返回accumulate()计算的和。编译通过。显然本方案使用了一个stl库函数accumulate,该函数在numeric头文件中有定义,accumulate带三个形参,前两个指定要累加的元素范围,第三个是累加初始值,显然其类型应与vector元素相同。本题中如此调用:accumulate(v.begin(),v.end(),0)。关于accumulate的详尽分析见http://www.cnblogs.com/heyonggang/p/3241878.html。
2,使用位操作符,位操作符有异或^,或 | ,与 & ,移位<<,>>,取反~等6种,实质上计算机内部使用位操作构成加法器,因此此题真正意图是考察加法器的知识。加法可以看作异或操作+进位的组合,由“位与”+“左移”产生进位中间数,当无进位时中间数为0。具体代码如下:

getSum(int a,int b){
    while(b){
        int carry = a & b;
        a ^= b;
        b = carry<<1;
    }
    return a;
}

关于此解决方案的一点思考:位操作符是针对二进制数而言的,对于int型,运算时自动转化为16位二进制数。任何位操作结果都不能溢出16位数范围。

344题:翻转字符串,如输入hello,输出olleh。
7.25思路:考察string类型的使用,s.size()获取字符串的长度,即字符的个数,返回size_type类型,size_type是string类自定义类型,可转化为int型,它实现了“与具体机器无关”,可存储任意大小的string长度。标准库许多类型(string,vector,list,deque等)的配套类型及方法命名都是一致的,如size(),begin(),end(),下标读取元素等。
本题的另一个注意点是避免返回局部变量,因此在解决函数内部定义一个新string用于返回是不合适的,正确的做法是交换首尾元素,代码如下:

string reverseString(string s){
   int left = 0,right = s.size();
   while(left<right){
       int t = s[left];
       s[left++] = s[right];
       s[right--] = t;
   } 
   return s;
}

338题 统计位数:给定一个非负整数,将从0到该整数间所有整数的二进制位为1的个数输出到数组。如给定5,则输出[0,1,1,2,1,2];
7.27思路,常规做法是不断对2取余统计1的个数,时间复杂度为O(n*sizeof(整数))。但本题要求时间复杂度为O(n),因此需要找出输出数组元素与对应下标的关系。推演发现该序列为:0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,…………
规律为:当整数为2^n时,bit1的位数始终是1;整数为(2^n-1),bit1的位数始终是n;

你可能感兴趣的:(LeetCode刷题思路)