一、写在前面
最近在练习编程题目,每天写一道以上剑指编程题。加油,坚持就是胜利!
二、题目一
1 题目描述
这是剑指上的一个链表题目。
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
2 解题思路
这道题有两种思路,一种是递归方式解决,这个方式的代码较为简单,但是时间复杂度会比较高,另一种是非递归方式解决。递归方式不讲,大体讲一下非递归方式的思路。
非递归方式的流程:首先通过比较pHead1和pHead2两个结点的值,来确定新链表的表头head,将表尾tail也指向表头head。之后通过一个while循环,每次通过比较pHead1和pHead2两个结点的值来构建新链表,直到pHead1或者pHead2全部遍历完,循环结束。由于此时pHead1和pHead2两个链表中还有一个没有遍历完(不是NULL),所以还需要把pHead1或者是pHead2剩余的链表链接到tail后面。最后return表头也就是head。
3 通过的代码
(1)递归代码
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if(pHead1==NULL)
return pHead2;
if(pHead2==NULL)
return pHead1;
ListNode* Head=NULL;
if(pHead1->val>pHead2->val)
{
Head=pHead2;
Head->next=Merge(pHead2->next,pHead1);
}
else
{
Head=pHead1;
Head->next=Merge(pHead1->next,pHead2);
}
return Head;
}
};
(2)非递归代码
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
ListNode* head;//表头
ListNode* tail;//表尾
if(pHead2==NULL)
return pHead1;//如果pHead2是空链表,直接返回pHead1。
else if(pHead1==NULL)
return pHead2;//这里和上面一个意思
if(pHead1->val<=pHead2->val)
{
head=pHead1;
pHead1=pHead1->next;
}//这里是为了构建好新链表的表头head,也就是以pHead1和pHead2中较小的结点作为新链表表头head
else
{
head=pHead2;
pHead2=pHead2->next;
}//这里和上面一个意思
tail=head;//此时将tail表尾指向head表头
while(pHead1&&pHead2)//while循环是主体部分,构建新链表。
{
if(pHead1->val<=pHead2->val)
{
tail->next=pHead1;//tail一直是表尾,这里用的是尾插法,将pHead1插到tail后面
pHead1=pHead1->next;
}
else
{
tail->next=pHead2;
pHead2=pHead2->next;
}
tail=tail->next;//由于tail一直指向表尾,所以这里tail指向tail->next。
}
if(pHead2)
{
tail->next=pHead2;
}//由于pHead1或者pHead2可能还没有全部构建到新链表中,这里需要把剩余部分挂到新链表后面。
else if(pHead1)
{
tail->next=pHead1;
}//和上面一个意思
return head;
}
};
题目二
1 题目描述
这是小红书2019年校园招聘技术类在线笔试题目。
给出一个链表,每 k 个节点一组进行翻转,并返回翻转后的链表。k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么将最后剩余节点保持原有顺序。
说明:
- 你需要自行定义链表结构,将输入的数据保存到你的链表中;
- 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换;
- 你的算法只能使用常数的额外空间。
输入描述:
第一行输入是链表的值
第二行输入是K的值,K是大于或等于1的整数
输入形式为:
1 2 3 4 5
2
输出描述:
当 k = 2 时,应当输出:
2 1 4 3 5
当 k = 3 时,应当输出:
3 2 1 4 5
当k=6时,应当输出:
1 2 3 4 5
2 解题思路
可以采用递归的思想,每次对K个结点进行反转,并且返回K个结点反转后的头结点。
下面描述了一下在k=3的条件下,reverse(ListNode *head,int k)函数在一次递归的结点变化过程。可以看到,在k=3的条件下,前面3个结点最后顺序被反转。
3 通过的代码
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
vector<int>input;
struct ListNode{
int val;
ListNode *next;
};
ListNode* Create()
{
ListNode *head=new ListNode;
head->val=input[0];
head->next=NULL;
ListNode *tail=head;
for(int i=1;i<input.size();i++)
{
ListNode *node=new ListNode;
node->val=input[i];
node->next=NULL;
tail->next=node;
tail=tail->next;
}
return head;
}
ListNode *reverse(ListNode *head,int k)
{
if(k==1||!head)
return head;
ListNode *pre=head;
ListNode *tail=head;
ListNode *q;
ListNode *p;
for(int i=1;i<k;i++)
{
if(!(tail->next))
{
return head;
}
tail=tail->next;
}
p=pre;
while(p->next!=tail)
{
q=p->next;
p->next=p->next->next;
q->next=pre;
pre=q;
}
p->next=reverse(tail->next,k);
tail->next=pre;
return tail;
}
void print(ListNode *head)
{
while(head!=NULL)
{
cout<<head->val<<" ";
head=head->next;
}
cout<<endl;
}
int main()
{
int value;
int K;
int num;
while(cin>>value)
{
input.push_back(value);
if(cin.get()=='\n')
break;
}
num=input.size();
ListNode *head=Create();
cin>>K;
ListNode *newHead=reverse(head,K);
print(newHead);
}