一、对于一个链表,我们需要用一个特定阈值完成对它的分化,使得小于等于这个值的结点移到前面,大于该值的结点在后面,同时保证两类结点内部的位置关系不变。
给定一个链表的头结点head,同时给定阈值val,请返回一个链表,使小于等于它的结点在前,大于等于它的在后,保证结点值不重复。
测试样例:
{1,4,2,5},3
{1,2,4,5}
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Divide {
public:
ListNode* listDivide(ListNode* head, int val) {
ListNode small(0);
ListNode large(0);
ListNode *p=head;
ListNode *psmall=&small,*plarge=&large;
while(p){
if(p->val>val){
plarge->next=p;
plarge=plarge->next;
}
else{
psmall->next=p;
psmall=psmall->next;
}
p=p->next;
}
psmall->next=large.next;
plarge->next=NULL;
return small.next;
}
};
二、现有两个升序链表,且链表中均无重复元素。请设计一个高效的算法,打印两个链表的公共值部分。
给定两个链表的头指针headA和headB,请返回一个vector,元素为两个链表的公共部分。请保证返回数组的升序。两个链表的元素个数均小于等于500。保证一定有公共值
测试样例:
{1,2,3,4,5,6,7},{2,4,6,8,10}
返回:[2,4,6]
class Common {
public:
vector<int> findCommonParts(ListNode* headA, ListNode* headB) {
vector<int> result;
ListNode* LA = headA;
ListNode* LB = headB;
//如果两个链表有任意一个为空,则直接返回
if(LA==NULL||LB==NULL)
return result;
//链表均不为空时
while(LA != NULL && LB != NULL){
if(LA->val == LB->val){
result.push_back(LA->val);
LA = LA->next;
LB = LB->next;
}
else if(LA->val > LB->val){
LB = LB->next;
}
else
LA = LA->next;
}
return result;
}
};
三、有一个单链表,请设计一个算法,使得每K个节点之间逆序,如果最后不够K个节点一组,则不调整最后几个节点。例如链表1->2->3->4->5->6->7->8->null,K=3这个例子。调整后为,3->2->1->6->5->4->7->8->null。因为K==3,所以每三个节点之间逆序,但其中的7,8不调整,因为只有两个节点不够一组。
给定一个单链表的头指针head,同时给定K值,返回逆序后的链表的头指针。
class KInverse {
public:
ListNode* inverse(ListNode* head, int k) {
if(head==NULL||head->next==NULL||k<2)
return head;
ListNode *p=head;
int n=0; //n为链表中结点的个数
while(p){
n++;
p=p->next;
}
ListNode *node=new ListNode(0);
node->next=head;
ListNode *pre=node,*cur=head,*temp=cur->next;
for(int i=0;i<n/k;i++){ //i为需要逆序的子链表的个数
for(int j=1;j<k;j++){ //链表中k个结点逆序
cur->next=temp->next;
temp->next=pre->next;
pre->next=temp;
temp=cur->next;
}
if(temp&&temp->next){
pre=cur;
cur=temp;
temp=cur->next;
}
else
break;
}
return node->next;
}
};
附:单链表逆序
从图(1)到图(2)的伪代码如下:
p->next = prev; //当前结点指向前驱结点
prev = p; //后移
p = latter;
latter = p->next;
template<class T>
void List<T>::Inverse()
{
if(first == NULL) return;
LinkNode<T> *p, *prev, *latter;
p = first->next; // 当前结点
prev = NULL; // 前一结点
latter = p->next; // 下一结点
while(p != NULL)
{
p->next = prev; // 当前结点指针指向前一结点
prev = p; // 后移
p = latter;
if(p != NULL) // 如果p指针是NULL,已经满足终止条件
latter = p->next;
}
first->next = prev;; // 最后连上附加头结点
}
四、现在有一个单链表。链表中每个节点保存一个整数,再给定一个值val,把所有等于val的节点删掉。
给定一个单链表的头结点head,同时给定一个值val,请返回清除后的链表的头结点,保证链表中有不等于该值的其它值。请保证其他元素的相对顺序。
测试样例:
{1,2,3,4,3,2,1},2
{1,3,4,3,1}
class ClearValue {
public:
ListNode* clear(ListNode* head, int val)
{
if(head==NULL)
return head;
ListNode *pointer=head;
ListNode newHead(0);
ListNode *nHead=&newHead;
while(pointer!=NULL)
{
if(pointer->val!=val) //保留与val值不一样的结点
{
nHead->next=pointer;
nHead=nHead->next;
}
pointer=pointer->next;
}
nHead->next=NULL;
return newHead.next;
}
};
五、请编写一个函数,检查链表是否为回文。
给定一个链表ListNode* pHead,请返回一个bool,代表链表是否为回文。
测试样例:
{1,2,3,2,1}
返回:true
{1,2,3,2,3}
返回:false
class Palindrome {
public:
bool isPalindrome(ListNode* pHead) {
stack<int> s;
ListNode *p1=pHead,*p2=pHead;
while(p1){ //将链表中的数据域压入栈中
s.push(p1->val);
p1=p1->next;
}
//如果栈中弹出的数据完全等于链表中的数据域,则表示为回文
while(p2){
if(p2->val==s.top()){
p2=p2->next;
s.pop();
}
else
return false;
}
return true;
}
};