今天是第一天在LeetCode上进行刷题,发现这里的题目很基础。并且其提供了在线的编译器,可以直接写代码和测试用例并进行调试,很方便。做了几道难度系数为Easy的题,总结如下:
一、1. Two Sum
题目要求是给定一组数和一个目标数,返回这组数中加和为目标数的那两个数在这组数中的索引。
我的解法是用一个双层的循环,让第一个数与其他的数依次进行加和运算,判断和是否为目标数,如果是则循环结束,返回索引值;否则再让第二个数与其他的数(不包括第一个数,因为前一层循环已经计算过了)依次进行加和运算...。一直这样做直到找到索引为止。用C++进行实现后,发现时间为二百多毫秒,很慢。代码如下:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> result ;
for(int i=0; i<nums.size(); ++i) {
for(int j=i+1; j<nums.size(); ++j) {
if((nums[i] + nums[j]) == target) {
result.push_back(i) ;
result.push_back(j) ;
break ;
}
}
}
return result ;
}
};
leetcode上这道题的两种优秀解法如下:
解法一:利用C++中的map集合类型,它是一个<key,value>集合。首先将这组数的值(key)和索引位置(vlaue)添加到map当中。然后遍历map,在其中查找(目标数-当前数),如果找到了,则直接取出该(目标数-当前数)所对应的value(即其索引位置),然后返回当前数的索引和取出的value。在这种解法下,通过使用map,加快了程序的速度。
解法二:解法二是对解法一的进一步改进。首先遍历这组数,直接map中进行查找(目标数-当前数),如果找到则返回然后返回当前数的索引和取出的value;否则将当前数添加到map中。此时只需要一层循环即可完成程序所需功能。进一步提高了程序的运行效率。
二、7. Reverse Integer
题目要求是给定一个整型数,逆序输出该整型数。同时假定该整型数是32位的,逆序后如果数溢出了,输出值为0。
我的解法是对负数进行了处理,将其转换为整数后再逆序输出。同时32位整型的范围是-2^31~2^31(不包括2^31),对于溢出的判断,使用了double。代码如下:
class Solution {
public:
int reverse(int x) {
double r = 0;
int flag = 0 ;
int i=0 ;
if(x < 0) {
x = -x ;
flag = 1 ;
}
if(flag == 1 && x<0) {
return 0 ;
}
while(x!=0) {
r = r*10 + (x%10) ;
x = x/10 ;
}
return (r > pow(2,31)) ? 0 : (flag==1) ? (int)-r : (int)r ;
}
};
后来参考了优秀的解法,发现可以使用long long并且对于负数不用做特殊的处理,相比之前的程序,这样做代码变短了,时间也加快了。代码如下:
class Solution {
public:
int reverse(int x) {
long long r = 0 ;
while(x!=0) {
r = r*10 + (x%10) ;
x = x/10 ;
}
return (r > pow(2,31) || r < -pow(2,31)) ? 0 : r ;
}
};
leetcode上这道题的优秀解法是:
由于每次进行逆序变换时都要进行对10的整除和取模运算,因此在每一次计算得到逆序值之后,判断该逆序值对10整除的结果与上一次循环得到的逆序值是否相同,如果不相同则发生了溢出,否则最后可以得到逆序结果。这种解法不用进行特意溢出的判断,利用在逆序计算过程中中间值之间的关系来间接判断数据是否溢出,很巧妙。
三、9. Palindrome Number
题目要求是判断一个整型数是否为回文字符串,不能使用额外的空间。
我的解法是先计算出该整型数的首尾数字,如果相等,则计算出这个数去掉首尾数字得到的整型数,再次判断该整型数的首尾是否相等,依次类推...;如果不相等则说明该整型不是回文字符串。在循环过程中有一个计数的变量,如果这个变量最后的值为0(整型数是奇数位)或-1(整型数是偶数位),则说明该整型数是回文数,否则如果最后的数变为了0,则该整型数是回文数,否则不是回文数,这一判断是对类似100001这样的数进行的。代码如下:
class Solution {
public:
bool isPalindrome(int x) {
if(x<0) {
return false ;
}
// 判断x由几位数字
int len = 0;
int k = x ;
while(k) {
k = k/10 ;
++ len ;
}
int j = len-1 ;
while(x/10 != 0) {
if((x%10) != (x/mi(j))) {
return false ;
}
x = x/10 - (x%10)*mi(j-1) ;
j = j-2 ;
}
return (j==0 || j==-1) ? true : (x==0) ? true : false ;
}
int mi(int k) {
int res = 1 ;
for(int i=1; i<=k; ++i) {
res = res * 10 ;
}
return res ;
}
};
leetcode上的优秀解法是:将这个数逆序输出,如果逆序之后的数与原来的数相同或者逆序之后的数整除10得到的数与原来的数相同(针对100001这样的数),则这个数是回文数,否则不是回文数。
四、13. Roman to Integer
题目要求是将罗马数装换为整型数。
罗马数到整型的转换规则为:
'I' = 1 ; 'V' = 5 ; 'X' = 10 ; 'L' = 50 ; 'C' = 100 ; 'D' = 500 ; 'M' = 1000 ;
在进行计算时从右向左计算,如果小数(I,C,X)在大数左面,则用该大数减去小数;其余情况进行加法运算。
我的解法是按照上面的规则从右向左依次进行计算,代码参考了网上的代码。
class Solution {
public:
int romanToInt(string s) {
if(s.length() == 0) return 0 ;
map<char,int> m ;
m['I'] = 1 ;
m['V'] = 5 ;
m['X'] = 10 ;
m['L'] = 50 ;
m['C'] = 100 ;
m['D'] = 500 ;
m['M'] = 1000 ;
int sum = m[s[s.length()-1]] ;
for(int i=s.length()-1; i>=0; --i) {
if(m[s[i-1]] >= m[s[i]]) {
sum += m[s[i-1]] ;
} else {
sum -= m[s[i-1]] ;
}
}
return sum ;
}
};
五、14. Longest Common Prefix
题目要求是求出一组字符串中的最长公共子串。
我的解法是取出第一个字符串,依次判断其每一个字母是否在其他字符串的对应位置,如果不是则循环结束;否则一直进行下去直到达到循环终止条件。代码如下:
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
if(strs.size() == 0)
return "" ;
string pre = "";
int f = 0 ;
for(int k=0; k<strs[0].length(); ++k) {
//cout << strs[0][k] << endl ;
for(int j=1; j<strs.size(); ++j) {
//cout << strs[j][k] << endl ;
if(strs[0][k] != strs[j][k]) {
f = 1 ;
break ;
}
}
if(f == 1)
break ;
pre += strs[0][k] ;
}
return pre ;
}
};
六、20. Valid Parentheses
题目要求相当于是判断给定括号() {} []序列,判断括号是否匹配。
我的解法是使用栈结构进行判断,栈是一种先进后出的结构,很适合该题的形式。代码如下:
class Solution {
public:
bool isValid(string s) {
if(s.length()%2 !=0)
return false ;
char c[s.length()] ;
int top = 0 ;
int flag = 0 ;
for(int i=0; i<s.length(); ++i) {
if(s[i]!=')' && s[i]!='}' && s[i]!=']') {
c[top] = s[i];
++ top ;
} else {
if(top > 0) {
switch(s[i]) {
case ')' :
if(c[top-1]!='(')
return false ;
else
--top ;
break ;
case '}' :
if(c[top-1]!='{')
return false ;
else
--top ;
break ;
case ']' :
if(c[top-1]!='[')
return false ;
else
--top ;
break ;
}
} else {
return false ;
}
}
}
if(top == 0)
return true ;
else
return false ;
}
};
leetcode上的优秀解法使用了C++中的stack来进行操作。
做了这些题之后,对比自己的解法与优秀的解法,找到了自己的不足的同时也拓宽了思路。