您的位置:首页 > 其它

2019年5月31日 第四天练习(13罗马数字转整数)+2019年6月3日 第五天练习(14最长公共前缀)

2019-06-05 22:52 274 查看

13.罗马数字转整数

题目的大致意思就是将罗马数字转换成对应的整数。我的想法是依次读出字符,然后变成相应的数字就ok了,但这里有一个难点是如何进行”小数位置在大数左边“这种行为的处理?
解决方法
要不一次读取两个字符,如果左边字符小于右边字符,则只输出左边字符,若左边字符大于右边字符,则二者一起输出。
首先要解决的是如何一次读取两个字符?
方法一: 还是用字符串的数组来判断

class Solution {
public:
int romanToInt(string s) {
int sum = 0;
for(int i = 0; i < s.size(); ++i)
{
if(s[i] == 'I')
{
if(i != s.size() - 1 && (s[i+1] == 'V' || s[i+1] == 'X'))
{
sum -= 1;
}
else
sum += 1;
}

if(s[i] == 'V')
sum += 5;
if(s[i] == 'X')
{
if(i != s.size() - 1 && (s[i+1] == 'L' || s[i+1] == 'C'))
{
sum -= 10;
}
else
sum += 10;
}
if(s[i] == 'L')
sum += 50;
if(s[i] == 'C')
{
if(i != s.size() - 1 && (s[i+1] == 'D' || s[i+1] == 'M'))
{
sum -= 100;
}
else
sum += 100;
}
if(s[i] == 'D')
sum += 500;
if(s[i] == 'M')
sum += 1000;
}
return sum;

}
};

执行后:

方法二 调用string中的一个函数方法substr()进行实现,这样可以实现一次读取两个字符。

string substr (size_t pos = 0, size_t len = npos) const
主要功能是复制子字符串,要求从指定位置开始,并具有指定的长度。如果没有指定长度或超出了源字符串的长度,则子字符串将延续到源字符串的结尾。

所以实现的代码如下:

class Solution {
public:
int romanToInt(string s)
{
if(s=="")
return 0;
int sum=0;
int len=s.size();
int i=0;
while(i<len)
{
if(s.substr(i,2)=="IV")
{
sum=sum+4;
i=i+2;
continue;
}
if(s.substr(i,2)=="IX")
{
sum=sum+9;
i=i+2;
continue;
}
if(s.substr(i,2)=="XL")
{
sum=sum+40;
i=i+2;
continue;
}
if(s.substr(i,2)=="XC")
{
sum=sum+90;
i=i+2;
continue;
}
if(s.substr(i,2)=="CD")
{
sum=sum+400;
i=i+2;
continue;
}
if(s.substr(i,2)=="CM")
{
sum=sum+900;
i=i+2;
continue;
}
if(s.substr(i,1)=="I")
{
sum=sum+1;
i=i+1;
continue;
}
if(s.substr(i,1)=="V")
{
sum=sum+5;
i=i+1;
continue;
}
if(s.substr(i,1)=="X")
{
sum=sum+10;
i=i+1;
continue;
}
if(s.substr(i,1)=="L")
{
sum=sum+50;
i=i+1;
continue;
}
if(s.substr(i,1)=="C")
{
sum=sum+100;
i=i+1;
continue;
}
if(s.substr(i,1)=="D")
{
sum=sum+500;
i=i+1;
continue;
}
if(s.substr(i,1)=="M")
{
sum=sum+1000;
i=i+1;
continue;
}

}

return sum;
}
};

执行后:发现调用函数并不如直接用数组进行执行的效率更高些

后来看到别人的代码,发现在C++语言中用哈希算法构造对应关系也可以完成,比如某位大神写的

class Solution {
public:
int romanToInt(string s) {
int result=0;
map<char,int> myMap;
myMap.insert(map<char,int>::value_type('I',1));
myMap.insert(map<char,int>::value_type('V',5));
myMap.insert(map<char,int>::value_type('X',10));
myMap.insert(map<char,int>::value_type('L',50));
myMap.insert(map<char,int>::value_type('C',100));
myMap.insert(map<char,int>::value_type('D',500));
myMap.insert(map<char,int>::value_type('M',1000));
for(int i=0;i<s.length();i++){
if(myMap[s[i]]>=myMap[s[i+1]])
result+=myMap[s[i]];
else{
result+=myMap[s[i+1]]-myMap[s[i]];
i++;
}

}
return result;

}
};

但这个效率…函数用的太多的过,但代码简洁,易于增长

14 最长公共前缀

首先忏悔,六月一日二日过儿童节太快乐了,不仅导致31日的没有发出去还耽误了两天没有写…我忏悔==。但6.1日还顺便考了个试,EMMMM考的人工智能的一个训练营,突然发现要学机器学习和人工智能,是很要数学功底的啊啊啊啊,照样是题都看不懂,不说了都是泪,继续好好刷题吧…

今天继续刷easy类的题,这道题的大致意思就是数组里存几个字符串,判断这些字符串的公共前缀是什么。

好吧,看到第一眼毫无思路,觉得是要一个字符一个字符拿出来比较,总不能有几个字符串建立几个栈或者指针吧==。

看了答案,果然不是,有以下几种思路(因为不会,只能照搬了,学习了)

方法一:水平扫描法
首先,我们将描述一种查找一组字符串的最长公共前缀 LCP(S1…Sn)的简单方法我们将会用到这样的结论:
LCP(S1…Sn)=LCP(LCP(LCP(S 1​,S2​),S3​),…S n​ )

我个人感觉这个方法很容易理解,而且也很容易实现,所以用代码敲一敲试试:

class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
if(strs.empty()) return"";
string s=strs[0];
for(int i=1;i<strs.size();i++){ //要注意数组中只有size()方法,没有length()方法。
for(int j=0;j<s.length();j++){
if(s[j]==strs[i][j])
continue;
else{
s.erase(j);
break;
}
}
}
return s;

}
};

方法二:水平扫描
想象数组的末尾有一个非常短的字符串,使用方法一依旧会进行S​ 次比较。优化这类情况的一种方法就是水平扫描。我们从前往后枚举字符串的每一列,先比较每个字符串相同列上的字符(即不同字符串相同下标的字符)然后再进行对下一列的比较。

class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
if (strs.empty()) return "";
for (int i = 0; i < strs[0].length() ; i++){
char c = strs[0].at(i);
for (int j = 1; j < strs.size(); j ++) {
if (i == strs[j].length() || strs[j].at(i) != c)
return strs[0].substr(0, i);
}
}
return strs[0];
}
};

可以看到执行用时以最短的字符串为标准,执行时间大大减少,但是若字符串长度相等,则这个方法效率并不会很明显。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: