Problem 21 Merge Two Sorted Lists
合并两个有序队列,这是合并排序中的基础,只是这里把数组换成了队列,主要的思想没有变化。
首先,当有一个队列为空时,返回另一个队列;
若都不为空,则从头开始遍历两个队列,比较对应元素,选择其中较小的元素,将新的队列的指针指向它,将该元素所在队列的指针向后移动以为,如此往复直至其中一个队列的为空
如果一个队列为空,那么将另一个队列直接新队列的后面
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if (l1 == NULL)
return l2;
if (l2 == NULL)
return l1;
ListNode* new_head, *move;
bool first = true;
while (l1 != NULL && l2 != NULL) {
if (first) {
if (l1->val < l2->val) {
move = new_head = l1;
l1 = l1->next;
}
else {
move = new_head = l2;
l2 = l2->next;
}
first = false;
continue;
}
if (l1->val < l2->val) {
move->next = l1;
l1 = l1->next;
}
else {
move->next = l2;
l2 = l2->next;
}
move = move->next;
}
if (l1 != NULL)
move->next = l1;
else if (l2 != NULL)
move->next = l2;
return new_head;
}
Problem 22 Generate Parentheses
给定小括号的对数n
,给出所有的成对组合的可能性。
总体来说,实际上我们只知道每种组合可能的最大长度是
2n
,比较直接的方法就是遍历所有可能性。
这里采用递归的思想来求解。递归函数的参数包括还可以放入多少个括号,存储结果的向量,上层函数产生结果,以及存储括号的栈(这个栈是用来检查是否配对的。简单的思路就是当遇到(
时,压栈;当遇到)
时,和栈顶的元素比较看是否能配对,如果不能配对则失败。)
每次都一次将last_string + '('
和last_string + ')'
作为下一次函数的参数;对于last_string + ')'
,首先应该判断加入新的括号之后是否能够配对,如果能够配对则继续,否则返回。
递归结束点有两个:一是之前提到的无法配对;二是当只能放入0个括号时,如果栈为空,那么将last_string
放入结果向量中,否则返回。
void recurseGenerate(int n_left, vector<string>& result, string last_string, stack<char> before) {
if (n_left == 0) {
if (before.empty())
result.push_back(last_string);
return;
}
string temp_string = last_string + '(';
stack<char> temp_stack = before;
temp_stack.push('(');
recurseGenerate(n_left - 1, result, temp_string, temp_stack);
temp_stack = before;
temp_string = last_string + ')';
if (!temp_stack.empty() && temp_stack.top() == '(') {
temp_stack.pop();
recurseGenerate(n_left - 1, result, temp_string, temp_stack);
}
return;
}
vector<string> generateParenthesis(int n) {
vector<string> result;
stack<char> before;
recurseGenerate(2 * n, result, "",before);
return result;
}
Problem 23 Merge k Sorted Lists
这个问题比较简单的方法就是两个两个合并,直到所有的队列都被合并了,那么最后得到的队列就是有序的。合并的方法之前已经解决过一次,这里不再赘述。
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if (l1 == NULL)
return l2;
if (l2 == NULL)
return l1;
ListNode* new_head, *move;
bool first = true;
while (l1 != NULL && l2 != NULL) {
if (first) {
if (l1->val < l2->val) {
move = new_head = l1;
l1 = l1->next;
}
else {
move = new_head = l2;
l2 = l2->next;
}
first = false;
continue;
}
if (l1->val < l2->val) {
move->next = l1;
l1 = l1->next;
}
else {
move->next = l2;
l2 = l2->next;
}
move = move->next;
}
if (l1 != NULL)
move->next = l1;
else if (l2 != NULL)
move->next = l2;
return new_head;
}
ListNode* mergeKLists(vector<ListNode*>& lists) {
int size = lists.size();
if (size == 0) return NULL;
if (size == 1) return lists[0];
ListNode* new_head = NULL;
for (int i = 0; i < size; i++) {
new_head = mergeTwoLists(new_head, lists[i]);
}
return new_head;
}
Problem 24 Swap Nodes in Pairs
这道题还是挺简单的,就两种情况:
第一种是头上的节点需要交换。
这时候需要记录下第三个节点的位置,然后把第二个节点向后指向头,头向后指向第三个节点;
第二种情况是中间的两个节点需要交换。
这时候需要记录下前一个节点,和第三个节点的位置,然后前一个节点向后指向第二个节点,第二个节点向后指向第一个节点,第一个节点向后指向第三个节点。
最后组成一个递归算法,当第一个节点为null或者第二个节点为null时递归结束。
void recursiveSwap(ListNode* before_head, ListNode* current_head) {
if (current_head == NULL || current_head->next == NULL) return;
ListNode* second = current_head->next, *next_head, *before;
current_head->next = second->next;
second->next = current_head;
before_head->next = second;
next_head = current_head->next;
before = current_head;
recursiveSwap(before, next_head);
}
ListNode* swapPairs(ListNode* head) {
if (head == NULL || head->next == NULL) return head;
ListNode* second = head->next, *next_head, *before;
head->next = second->next;
second->next = head;
next_head = head->next;
before = head;
recursiveSwap(before, next_head);
return second;
}