1.反转链表II
反转从位置m到n的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度
思路:一次遍历的同时采用指针记录关键节点的位置
ListNode* reverseBetween(ListNode* head, int m, int n) {
if(head == nullptr || head -> next == nullptr)
{
return head;
}
ListNode* cur = head;
ListNode* start = nullptr; //记录要反转的链表的前一个节点
ListNode* end = nullptr; //记录要反转的链表的最后一个节点
ListNode* pre = nullptr;
ListNode* temp;
//cur记录要反转链表的第一个节点,start记录要反转的链表的前一个节点
if(m > 1)
{
for(int i = 1; i < m; i++)
{
start = cur;
cur = cur -> next;
end = cur;
}
}
//对链表的第m到n个节点进行反转
for(int i = m; i <= n; i++)
{
temp = cur -> next;
cur -> next = pre;
pre = cur;
cur = temp;
}
if(m == 1)
{
head -> next = cur;
return pre;
}
end -> next = cur;
start -> next = pre;
return head;
}
2. 复原IP地址
给定一个只包含数字的字符串,复原它并返回所有可能的IP地址格式
思路:回溯算法
从字符串的第一个字符开始,分别检查从当前字符开始的第1、2、3位组成的数,若该数符合要求(即小于256)则加入到结果IP中,然后再从当前数的后一位置递归向后寻找。若遍历到第四个数,则判断最后几位组成的数是否满足要求,符合则加入到最后的集合中。注意当遇到当前数的起始位是0时,仅将0加入到字符串中就停止当前数的寻找
vector<string> restoreIpAddresses(string s) {
vector<string> res;
traceback(s, 4, "", res);
return res;
}
//k代表还需要分段的个数
void traceback(string s, int k, string temp, vector<string>& res)
{
if(k == 0)
{
if(s.empty())
{
res.push_back(temp);
}
}
else
{
for(int i = 1; i <= 3; i++)
{
if(s.size() >= i && isValid(s.substr(0,i)))
{
if(k == 1)
{
traceback(s.substr(i), k - 1, temp + s.substr(0, i), res);
}
else
{
traceback(s.substr(i), k - 1, temp + s.substr(0, i) + ".", res);
}
}
}
}
}
bool isValid(string s)
{
if(s.empty() || s.size() > 3 || (s.size() > 1 && s[0] == '0'))
{
return false;
}
int res = atoi(s.c_str());
return res <= 255 && res >= 0;
}