leetcode 刷题日志 2018-03-26
58. 最后一个单词的长度
分析:找最后一个非空格,向前找
int lengthOfLastWord(string s) { int i = s.find_last_not_of(' '); int j = i; for(;j >= 0; j--){ if(s[j] == ' ') break; } return i - j; }
7. 颠倒整数
分析:注意题意,超范围 LL ,结尾去0
int reverse(int x) { long long res = 0; if(x!=0){ while(!x%10){ x /= 10; } } while(x){ res *= 10; res += x % 10; x /= 10; } if(res> INT_MAX || res < -INT_MAX){ res = 0; } return res; }
13. 罗马数字转整数
分析:罗马数字共有7个,即Ⅰ(1)、Ⅴ(5)、Ⅹ(10)、Ⅼ(50)、Ⅽ(100)、Ⅾ(500)和Ⅿ(1000)。按照下述的规则可以表示任意正整数。需要注意的是罗马数字中没有“0”,与进位制无关。一般认为罗马数字只用来记数,而不作演算。
字母对应数字相加,后面字母比前面字母大代表前面字母需要减去
被减的字母最多一个!
int singleCharToInt(char x){ int num = -1; if(x == 'i') num = 1; else if(x == 'v') num = 5; else if(x == 'x') num = 10; else if(x == 'l') num = 50; else if(x == 'c') num = 100; else if(x == 'd') num = 500; else if(x == 'm') num = 1000; return num; } int romanToInt(string s) { int len = s.size(); transform(s.begin(), s.end(), s.begin(), ::tolower); int res = 0; for(int i=0;i<len;i++){ int num=singleCharToInt(s[i]); if(singleCharToInt(s[i+1]) > num){ num=(-1)*num; } res += num; } return res; }
38. 数数并说
分析:步步迭代
整数字符串转换
string fun(string s){ string tmp = ""; int len = s.size(); int con =0; char t ; for(int i=0;i<len;){ t=s[i++];con = 1; while(s[i] == t){ con++; i++; } ostringstream stream; stream<<con; //n为int类型 tmp =tmp + stream.str(); tmp+=t; } return tmp; } string countAndSay(int n) { string s="1"; int en = s.size(); int con =0; while(--n){ s=fun(s); //cout<<s<<endl; } return s; }
67. 二进制求和
分析:对齐,相加,首位进位处理
string addBinary(string a, string b) { //对齐 int lena = a.size(), lenb = b.size(); int n = abs(lena - lenb); string tmp(n,'0'); if(lena < lenb) { a = tmp + a; } if(lena > lenb) { b = tmp + b; } //加法 int len = a.size(); int x = 0, c = 0; // 计算结果,进位标记 for(int i = len - 1; i >= 0; --i){ x = a[i] - '0' + b[i] -'0' + c; if( x > 1){ c = 1; x -= 2; } else{ c = 0; } a[i] = (char)('0' + x ); } if(c) //首部进位 a = "1" + a; return a; }
14. 最长公共前缀
分析:拿第一个字符串作为标准,遍历所有字符串,期间不断缩小条件
string longestCommonPrefix(vector<string>& strs) { int len = strs.size(),lenS = 0; if(0 == len) return ""; string s = strs[0]; for(int i=0; i<len; ++i){ lenS = s.length(); for(int j=0; j<lenS; ++j){ if(s[j] != strs[i][j]){ s = s.substr(0 , j); //对比所有字符串,不断缩减条件 break; } } } return s; }
20. 有效的括号
给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串,判断字符串是否有效。
括号必须以正确的顺序关闭,"()"
和 "()[]{}"
是有效的但是 "(]"
和 "([)]"
不是。
分析:栈的应用
我用的比较别扭
每次压入一个字符,深入栈内看是否还有配对成功的括号可以弹出
最终所有配对成功的话,栈为空
bool isValid(string s) { stack<char> stack_tmp; int len = s.length(); char x,y;
stack_tmp.push(s[0]); for(int i=1; i<len; i++){ stack_tmp.push(s[i]); while(stack_tmp.size()>=2){ //要想配对成功,至少有两个 y = stack_tmp.top(); stack_tmp.pop(); x = stack_tmp.top(); //取两数 if(')' == y && x == '('){ stack_tmp.pop(); } else if('}' == y && x == '{'){ stack_tmp.pop(); } else if(']' == y && x == '['){ stack_tmp.pop(); } else{ stack_tmp.push(y); //不行,再压回去 break; } } } return stack_tmp.empty(); }
29. 两数相除
不使用乘号,除号和取模符号将两数相除。如果溢出返回 MAX_INT。
感谢:https://www.liuchuo.net/archives/3140
//1. 利用 a/b = exp(log(a)-log(b)) //注意定义域>0 需取绝对值,并抽取符号位(抑或运算用的巧妙)
//2. 注意越界情况,可能分母==0 可能负数反号
int divide(int dividend, int divisor) { if(divisor == 0 || dividend == INT_MIN && divisor == -1) return INT_MAX; //溢出两种情况 int sign = ((dividend >> 31) ^ (divisor >> 31)) == 0 ? 1 : -1; //符号位 判断 long a = abs((long)dividend); long b = abs((long)divisor); double c = exp(log(a) - log(b)) + 0.0000000001; return (int)(sign * c); }
125. 验证回文字符串
给定一个字符串,确定它是否是回文,只考虑字母数字字符和忽略大小写。
例如:"A man, a plan, a canal: Panama"
是回文字符串。"race a car"
不是回文字符串。
注意:
你有考虑过这个字符串可能是空的吗? 在面试中这是一个很好的问题。
针对此题目,我们将空字符串定义为有效的回文字符串。
分析:空串处理、提取主要字符串、双向搜索判断
bool isPalindrome(string s) { if (""== s) return true; //1. deal with empty string int len = s.length(); string tmp=""; for(int i=0; i <len; i++){ //2. filter string if(s[i]>='A' &&s[i]<='Z'){ tmp +=s[i] +32; } if((s[i]>='a'&& s[i]<='z') ||(s[i] >='0' &&s[i] <='9')){ tmp +=s[i]; } } len = tmp.length(); int m = (len +1)/2; for (int i=0; i <= m; i++) { //3. Bidirectional search if(tmp[i] != tmp[len -i -1]) return false; } return true; }