1.两数之和
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
当对元素进行查找时,优先使用哈希表解决问题,因为哈希表的查找元素的时间复杂度为O(1),可以大大降低时间复杂度。
unordered_map<int,int>hashtable;//C++可以使用unordered_map来使用STL中的哈希表
每一次当遍历数组时,在哈希表中查找key为目标值减去当前值的数组下标,如果没有找到,哈希表会返回指向哈希表结尾元素的下一位置的迭代器,并把该数组的下标和值存入哈希表中,其中key为数组的值,value为数组的下标,,如果成功找到就返回哈希表中存储的下标和当前遍历数组的下标。
void solution(int target,int length){
unordered_map<int,int>hashtable;
for(int i=0;i<length;i++)
{
auto it = hashtable.find(target-nums[i]);
if(it != hashtable.end())
{
cout<<i<<endl;
cout<<it->second<<" "<<i<<endl;
return;
}
hashtable[nums[i]]=i;
}
}
2.回文数
给你一个整数 x
,如果 x
是一个回文整数,返回 true
;否则,返回 false
。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
- 例如,
121
是回文,而123
不是。
解法:利用while循环将x逆置并与逆置前的元素比较,相等则返回true,不相等则返回false。
问题:因为-231 <= x <= 231 - 1所以
此法会造成数据的溢出。因此采用逆置后半段与前半段比较的方法。
bool isHw(int x)
{
int revnum=0;//后半段数初始化
while(x>revnum)
{
revnum=revnum*10+x%10;
x=x/10;
}
return x==revnum||revnum/10==x;//存在奇数位和偶数位两种情况
}
3.罗马数字转整数
罗马数字包含以下七种字符: I
, V
, X
, L
,C
,D
和 M
。
字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000
例如, 罗马数字 2
写做 II
,即为两个并列的 1 。12
写做 XII
,即为 X
+ II
。 27
写做 XXVII
, 即为 XX
+ V
+ II
。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII
,而是 IV
。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX
。这个特殊的规则只适用于以下六种情况:
I
可以放在V
(5) 和X
(10) 的左边,来表示 4 和 9。X
可以放在L
(50) 和C
(100) 的左边,来表示 40 和 90。C
可以放在D
(500) 和M
(1000) 的左边,来表示 400 和 900。
给定一个罗马数字,将其转换成整数。
由于不会存在非法输入情况,所以先用哈希表存储7种字符和对应的数值,从左向右遍历字符串(也可从右向左),关键在于当当前字符对应的key元素对应value值小于下一个字符对应key元素对应value值时,则需减去当前value值再加上下一个value值。大于或等于则直接加上当前value值。从右向左则相反。
int romanTolent(string s)
{
int num=0;
unordered_map<char,int> hashtable{{'I',1},{'V',5},{'X',10},{'L',50},{'C',100},{'D',500},{'M',1000}};
for(int i=0;i<s.size();i++)
{
if(i==s.size()-1)//防止i溢出
{
auto it = hashtable.find(s[i]);//最后一个元素不用判断直接相加
num+=it->second;
break;
}
auto it1=hashtable.find(s[i]);
auto it2=hashtable.find(s[i+1]);
if(it1->second<it2->second)
{
num=num+it2->second-it1->second;
i++
}else
{
num=num+it1->second;
}
}
return num;
}
4.最长公共前缀子串
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""
。
解法一:字符串数组长度长短不一,所以在字符串数组中寻找最短的那个,以最短长度为条件,纵向比较每个字符串的各位置的字符,当出现不相等时退出循环返回公共前缀或空字符串。
string longestCommonPrefix(vector<string>& strs) {
int min=200;
for(int i=0;i<strs.size();i++){
if(strs[i].size()<min)
{
min = strs[i].size();
}
}
string s;
for(int i=0;i<min;i++)
{
char x = strs[0][i];
int flag=1;
for(int j=0;j<strs.size();j++){
if(strs[j][i]!=x){
flag=0;
}
if(strs[j][i]!=x&&i==0)
{
return "";
}
}
if(flag==1){
s.push_back(x);
}else{
break;
}
}
return s;
}
解法二:采用分治法,将问题分解成两个子问题,对两个子问题分别计算最长公共前缀,最后计算总的最长公共前缀。
5.罗马数字转为整数
罗马数字包含以下七种字符: I
, V
, X
, L
,C
,D
和 M
。
字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000
例如, 罗马数字 2 写做 II
,即为两个并列的 1。12 写做 XII
,即为 X
+ II
。 27 写做 XXVII
, 即为 XX
+ V
+ II
。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII
,而是 IV
。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX
。这个特殊的规则只适用于以下六种情况:
I
可以放在V
(5) 和X
(10) 的左边,来表示 4 和 9。X
可以放在L
(50) 和C
(100) 的左边,来表示 40 和 90。C
可以放在D
(500) 和M
(1000) 的左边,来表示 400 和 900。
给你一个整数,将其转为罗马数字。
解法:贪心算法,罗马数字表示唯一,选择不超过num的最大罗马数字即可。