[Leetcode] 刷题2
13. 罗马数字转整数
方法一 比较当前字符,并获取下一位字符
class Solution {
public:
int GetRomanValue(const char ch)
{
if(ch == 'I') return 1;
else if(ch == 'V') return 5;
else if(ch == 'X') return 10;
else if(ch == 'L') return 50;
else if(ch == 'C') return 100;
else if(ch == 'D') return 500;
else if(ch == 'M') return 1000;
else return 0;
}
int GetValue(const string s,int iPos)
{
int iSize = s.size();
int iPos2 = iPos+1;
int iValue = 0;
if(iPos < iSize) iValue = GetRomanValue(s[iPos]);
if(iPos2 < iSize)
{
if(s[iPos] == 'I' && (s[iPos2] == 'V' || s[iPos2] == 'X')) iValue *= -1;
else if(s[iPos] == 'X' && (s[iPos2] == 'L' || s[iPos2] == 'C')) iValue *= -1;
else if(s[iPos] == 'C' && (s[iPos2] == 'D' || s[iPos2] == 'M')) iValue *= -1;
}
return iValue;
}
int romanToInt(string s) {
int iValue = 0;
for(int i=0; i < s.size(); ++i)
{
iValue += GetValue(s,i);
}
return iValue;
}
};
方法一改进 GetValue方法中,判断下一位字符时,直接取值,并修改iPos的值
int GetValue(const string s,int& iPos)
{
int iSize = s.size();
int iPos2 = iPos+1;
int iValue = 0;
char ch1 =s[iPos];
if(iPos < iSize) iValue = GetRomanValue(ch1);
if(iPos2 < iSize)
{
char ch2 = s[++iPos];
if((ch1 == 'I' && (ch2 == 'V' || ch2 == 'X')) ||
(ch1 == 'X' && (ch2 == 'L' || ch2 == 'C')) ||
(ch1 == 'C' && (ch2 == 'D' || ch2 == 'M')))
{iValue = -1*iValue + GetRomanValue(ch2);}
else --iPos;
}
return iValue;
}
修改完之后运行时间更快了,因为空间复杂度为O(n)了。
方法二 可使用map,直接将可搭配的组合写入map中,然后根据前后字符查找即可,但须开辟额外空间。
2. 两数相加
思路 每次相加需要记录进位carry
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
if(l1->val==0 && !l1->next) return l2;
if(l2->val==0 && !l2->next) return l1;
ListNode *result= new ListNode(0);
ListNode *current = result;
int carry = 0;
while(l1 || l2)
{
int x = l1?l1->val:0;
int y = l2?l2->val: 0;
int sum = x+y+carry;
carry = sum/10;
current->next = new ListNode(sum%10);
current = current->next;
if (l1) l1 = l1->next;
if(l2) l2= l2->next;
}
if(carry > 0)
{
current->next = new ListNode(carry);
}
return result->next;
}
};
3. 无重复字符的最长子串
方法一 创建一个vector,记录每次不重复的字符串
class Solution {
public:
bool hasRepeatChar(vector<char>& vec, const char ch,int& iPos)
{
std::vector<char>::iterator iter;
for (iter = vec.begin(); iter!=vec.end();++iter)
{
if (*iter == ch)
{
iPos = iter - vec.begin();
return true;
}
}
return false;
}
int lengthOfLongestSubstring(string s) {
int iSize = s.size();
if (iSize == 0 || iSize == 1)
return iSize;
vector<char> vec;
int iLeft = 0;
int iRight = 1;
int iMax = 0;
int iPos = -1;
vec.push_back(s[0]);
while (iRight <= iSize)
{
if (hasRepeatChar(vec, s[iRight], iPos))
{
iLeft = iPos;
if(vec.size() > iMax) iMax = vec.size();
vec.erase(vec.begin(), vec.begin() + iPos+1);
}
vec.push_back(s[iRight]);
++iRight;
}
if (vec.size()-1 > iMax) iMax = vec.size()-1;
return iMax;
}
};
方法二 每次通过iLeft和iRight记录不重复字符串左右索引
class Solution {
public:
bool hasRepeatChar(const string& s, int& iLeft, int& iRight,int& iPos)
{
if (iRight < iLeft) return false;
char ch = s[iRight];
for (int i = iLeft; i < iRight; ++i)
{
if (s[i] == ch)
{
iPos = iRight - iLeft;
iLeft =i+1;
return true;
}
}
return false;
}
int lengthOfLongestSubstring(string s) {
int iSize = s.size();
if (iSize == 0 || iSize == 1)
return iSize;
int iLeft = 0;
int iRight = 1;
int iMax = 1;
int iPos = -1;
while (iRight < iSize)
{
if (hasRepeatChar(s, iLeft, iRight,iPos))
{
if (iPos > iMax) iMax = iPos;
}
++iRight;
}
if (iRight - iLeft > iMax) iMax = iRight - iLeft;
return iMax;
}
};
4. 寻找两个正序数组的中位数
方法 先判断总个数为奇数还是偶数,然后依次比较两个数组中的值,奇数取iSum / 2的值,偶数取iSum / 2与iSum / 2+1的平均数
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int iSize1 = nums1.size();
int iSize2 = nums2.size();
int iSum = iSize1 + iSize2;
if (iSize1 == 0 && iSize2 == 0)
{
return 0.0;
}
else if (iSize1 == 0 && iSize2 != 0)
{
if ((iSize2 & 1) != 0) return nums2[iSize2 / 2];
else if ((iSize2 & 1) == 0) return (nums2[iSize2 / 2] + nums2[iSize2 / 2 - 1]) / 2.0;
}
else if (iSize1 != 0 && iSize2 == 0)
{
if ((iSize1 & 1) != 0) return nums1[iSize1 / 2];
else if ((iSize1 & 1)== 0) return (nums1[iSize1 / 2] + nums1[iSize1 / 2 - 1]) / 2.0;
}
else
{
int i1 = 0;
int i2 = 0;
int num = 0;
int iCount = 0;
if ((iSum & 1) != 0) //总个数为奇数
{
while (iCount != iSum / 2+1)
{
if (i1 < iSize1 && i2 < iSize2 && nums1[i1] > nums2[i2])
{
num = nums2[i2];
++i2;
}
else if (i1 < iSize1 && i2 < iSize2 && nums1[i1] <= nums2[i2])
{
num = nums1[i1];
++i1;
}
else if (i1 >= iSize1 && i2 < iSize2)
{
num = nums2[i2];
++i2;
}
else if (i2 >= iSize2 && i1 < iSize1)
{
num = nums1[i1];
++i1;
}
++iCount;
}
return num;
}
else if ((iSum & 1) == 0) //总个数为偶数
{
while (iCount != iSum / 2+1)
{
++iCount;
if (i1 < iSize1 && i2 < iSize2 && nums1[i1] > nums2[i2])
{
if (iCount == iSum / 2 || iCount == iSum / 2+1) num += nums2[i2];
++i2;
}
else if (i1 < iSize1 && i2 < iSize2 && nums1[i1] <= nums2[i2])
{
if (iCount == iSum / 2 || iCount == iSum / 2 + 1) num += nums1[i1];
++i1;
}
else if (i1 >= iSize1 && i2 < iSize2)
{
if (iCount == iSum / 2 || iCount == iSum / 2 + 1) num += nums2[i2];
++i2;
}
else if (i2 >= iSize2 && i1 < iSize1)
{
if (iCount == iSum / 2 || iCount == iSum / 2 + 1) num += nums1[i1];
++i1;
}
}
return num/2.0;
}
}
return 0.0;
}
};
5. 最长回文子串
参考官方 中心扩展算法:我们枚举所有的「回文中心」并尝试「扩展」,直到无法扩展为止,此时的回文串长度即为此「回文中心」下的最长回文串长度。我们对所有的长度求出最大值,即可得到最终的答案。
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/longest-palindromic-substring/solution/zui-chang-hui-wen-zi-chuan-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
class Solution {
public:
pair<int,int> FindMaxLength(const string& s,int iLeft,int iRight)
{
int iSize = s.size();
while(iLeft >=0 && iRight <= iSize && s[iLeft] == s[iRight])
{
--iLeft;
++iRight;
}
return{++iLeft,--iRight};
}
string longestPalindrome(string s) {
int iSize = s.size();
int iStart = 0;
int iEnd = 0;
if(iSize == 0) return "";
else if(iSize == 1) return s;
else
{
for(int i=0; i < iSize; ++i)
{
auto[iLeft1,iRight1] = FindMaxLength(s,i,i);
if((iRight1 - iLeft1) > (iEnd -iStart))
{
iStart = iLeft1;
iEnd = iRight1;
}
auto[iLeft2,iRight2] = FindMaxLength(s,i,i+1);
if((iRight2 - iLeft2) > (iEnd -iStart))
{
iStart = iLeft2;
iEnd = iRight2;
}
}
}
return s.substr(iStart,iEnd-iStart+1);
}
};
8. 字符串转换整数 (atoi)
方法 设置一个long long lRes存储结果, 并且当lRes超过了INT最大最小范围时,会溢出,所以每次需要判断,防止结果溢出:lRes = bPositive ? min(lRes, (long long)INT_MAX) : min(lRes, -(long long)INT_MIN)
class Solution {
public:
int myAtoi(string s) {
int iSize = s.size();
if (iSize == 0) return 0;
string sRes;
char c;
bool bPositive = true;
bool bStart = false;
long long lRes = 0;
int i = 0;
while (!bStart)
{
if (i >= iSize) break;
c = s[i++];
if (c == ' ') continue;
else if (c == '-' || c == '+')
{
bPositive = c == '-' ? false : true;
bStart = true;
}
else if (c >= '1' && c <= '9')
{
sRes += c;
lRes = c - '0';
bStart = true;
}
else if (c == '0')
{
bStart = true;
}
else break;
}
if (!bStart) return 0;
while (bStart)
{
if (i >= iSize) break;
c = s[i++];
if (sRes == "" && c == '0') continue;
if (c >= '0' && c <= '9')
{
sRes += c;
lRes = lRes * 10 + c - '0';
lRes = bPositive ? min(lRes, (long long)INT_MAX) : min(lRes, -(long long)INT_MIN); //防止溢出
}
else break;
}
if (sRes == "")
{
return 0;
}
if (!bPositive)
{
lRes *= -1;
}
return lRes;
}
};