1.环形链表插值
从小到大环形列表,测试用例:
[1,3,4,5,7],[1,2,3,4,0],2
返回:{1,2,3,4,5,7}
方法一
class InsertValue {
public:
ListNode* insert(vector<int> A, vector<int> nxt, int val) {
if(A.size()==0){
ListNode *node=new ListNode(val);
node->next=node;
return node;
}
ListNode *head=new ListNode(A[0]);
ListNode *h1=head;
for(int i=1;i<A.size();i++){
h1->next=new ListNode(A[i]);
h1=h1->next;
}
h1->next=NULL;
ListNode *pre=head,*cur=head->next;
if(pre->val>=val){
ListNode *node=new ListNode(val);
node->next=head;
head=node;
return head;
}
while(cur!=NULL){
if(pre->val<=val&&val<=cur->val){
ListNode *node=new ListNode(val);
pre->next=node;
node->next=cur;
break;
}
pre=pre->next;
cur=cur->next;
}
if(cur==NULL){
ListNode *node=new ListNode(val);
pre->next=node;
node->next=NULL;
}
return head;
}
};
方法二
class InsertValue {
public:
ListNode* insert(vector<int> A, vector<int> nxt, int val) {
ListNode* root = NULL;
if (A.empty()) return root;
root = new ListNode(A[0]);
ListNode *p = root;
for (int i = 1; i < A.size(); ++i) {
ListNode* tmp = new ListNode(A[nxt[i-1]]);
p->next = tmp;
p = tmp;
}
//p->next = root;
p->next = NULL;
if (root->val > val) {
ListNode *tmp = new ListNode(val);
tmp->next = root;
root = tmp;
//p->next = root;
p->next = NULL;
return root;
}
p = root;
//while (p->next != root) {
while (p->next) {
if (val >= p->val && val <= p->next->val) {
ListNode *tmp = new ListNode(val);
tmp->next = p->next;
p->next = tmp;
return root;
}
p = p->next;
}
ListNode *tmp = new ListNode(val);
p->next = tmp;
//tmp->next = root;
tmp->next = NULL;
return root;
}
};
题目中说是环形链接,但是实际返回返回环形链表在牛客网却通不过,而且觉得数组作用不大。
2.删除单链表中的一个节点
给出头节点和被删除的数字
class Remove {
public:
ListNode* removeNode(ListNode* pHead, int delVal) {
ListNode* pre=pHead;
ListNode* cur=pHead->next;
if(delVal==pre->val)
{
pHead=cur;
delete pre;
return pHead;
}
while(cur!=NULL)
{
if(delVal==cur->val)
{
pre->next=cur->next;
delete cur;
return pHead;
}
pre=cur;
cur=cur->next;
}
return pHead;
}
};
3.链表的分化
小的元素放前面,大的放后面
class Divide {
public:
ListNode* listDivide(ListNode* head, int val) {
ListNode small(0);//记得分配内存
ListNode big(0);
ListNode *cur=head;
ListNode *psmall=&small,*pbig=&big;
while(cur)
{
if(val>=cur->val)
{
psmall->next=cur;
psmall=psmall->next;
}
else
{
pbig->next=cur;
pbig=pbig->next;
}
cur=cur->next;
}
psmall->next=big.next;
pbig->next=NULL;
return small.next;
}
};
4.链表k逆序
方法一
每k个元素逆序一下
class KInverse {
public:
ListNode* inverse(ListNode* head, int k) {
if(head==NULL||k<2)
return head;
ListNode* p=head;
int count=0;
while(p!=NULL)
{
count++;
p=p->next;
}
ListNode* node=new ListNode(0);
ListNode* pre=node;
node->next=head;
ListNode* cur=head;
ListNode* temp=head->next;
for(int i=0;i<count/k;i++)
{
for(int j=0;j<k-1;j++)
{
cur->next=temp->next;
temp->next=pre->next;
pre->next=temp;
// pre=temp;
temp=cur->next;
}
pre=cur;
cur=cur->next;
temp=cur->next;
}
return node->next;
}
};
方法二
class KInverse {
public:
ListNode* inverse(ListNode* head, int k) {
if(head==NULL||k<2)
return head;
ListNode* p=head;
int count=0;
while(p!=NULL)
{
count++;
p=p->next;
}
ListNode* root=new ListNode(0);
p = root;
int cnt = (count % k) ? (count-(count%k)-1) : (count-1);
for(int i=0;i<=cnt;i++){
ListNode *node = new ListNode(head->val);//头插法建立链表
node->next = p->next;
p->next = node;
if ((i+1)%k==0) {//移动k的位置
int j = k;
while (j--) {
p = p->next;
}
}
ListNode *tmp = head;
head = head->next;
delete tmp;
}
p->next = head;
return root->next;
}
};
5.删除指定值
class ClearValue {
public:
ListNode* clear(ListNode* head, int val) {
ListNode* pre=new ListNode(0);
ListNode* cur=pre;
while(head)
{
if(val!=head->val)
{
cur->next=head;
cur=cur->next;
} else {
ListNode *tmp = head;
head=head->next;
delete tmp;
continue;
}
head=head->next;
}
cur->next=NULL;
return pre->next;
}
};
6.判断回文
方法一
使用一个栈
class Palindrome {
public:
bool isPalindrome(ListNode* pHead) {
stack<int> s;
int x;
ListNode* p=pHead;
ListNode* cur=pHead;
if(pHead==NULL||pHead->next==NULL)
return true;
while(p){
s.push(p->val);
p=p->next;
}
p=pHead;
while(p){
x=s.top();
if(p->val!=x)
return false;
s.pop();
p=p->next;
}
return true;
}
};
方法二
使用vector数组
class Palindrome {
public:
bool isPalindrome(ListNode* pHead) {
vector<int> vec;
int x;
ListNode* p=pHead;
ListNode* cur=pHead;
if(pHead==NULL||pHead->next==NULL)
return true;
while(p){
vec.push_back(p->val);
p=p->next;
}
int i = 0;
int j = vec.size() - 1;
while(i<=j){
if (vec[i] == vec[j]) {
++i;
--j;
continue;
}
return false;
}
return true;
}
};
方法三
不需要额外空间,直接逆转后半部分链表
class Palindrome {
public:
bool isPalindrome(ListNode* pHead) {
vector<int> vec;
int x;
ListNode* p=pHead;
ListNode* cur=pHead;
if(pHead==NULL||pHead->next==NULL)
return true;
int len = 0;
while(p){
vec.push_back(p->val);
p=p->next;
++len;
}
int i = 0;
p = pHead;
while(p){
if (i >= len/2) {
//逆转
ListNode* p1 = p->next;
p->next = NULL;
while (p1) {
ListNode* tmp = p1->next;
p1->next = p;
p = p1;
p1 = tmp;
}
break;
}
++i;
p = p->next;
}
ListNode*head = pHead;
ListNode*end = p;
while(head&&end){
if (head->val == end->val) {
head = head->next;
end = end->next;
continue;
}
return false;
}
return true;
}
};
7.复制复杂链表
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead)
{
if(!pHead) return NULL;
RandomListNode* cur=pHead;
while(cur)
{
RandomListNode* node=new RandomListNode(cur->label);
node->next=cur->next;
cur->next=node;
cur=node->next;
}
cur=pHead;
RandomListNode* fol=cur->next;
while(cur)
{
if(cur->random==NULL) fol->random=NULL;
else fol->random=cur->random->next;//指向random指针的下个节点
cur=fol->next;//等价于cur->next->next;
fol=cur->next;//等价于fol->next->next;
}
cur=pHead;
RandomListNode* pre=cur->next;
//RandomListNode* fol1=pre;
fol=pre;//这里用老指针新指针都行!!
while(cur)
{
if(cur->next->next)
{
cur->next=fol->next;//必须先维持旧链表
fol->next=cur->next->next;//才能建立新链表
}
else
{
fol->next=NULL;//这里两者的先后顺序无区别
cur->next=NULL;
}
cur=cur->next;//这里也是两者的先后顺序无区别;
fol=fol->next;
}
return pre;
}
};
8.链表判环
判断链表是否有环,并且返回入环节点的值
class ChkLoop {
public:
int chkLoop(ListNode* head, int adjust) {
if(head==NULL||head->next==NULL) return -1;
ListNode* p1=head;
ListNode* p2=head;
//while(p2->next&&p2->next->next)
while(p2&&p2->next)
{
p1=p1->next;
p2=p2->next->next;
if(p1==p2)
{
p2=head;
while(p2!=p1)
{
p2=p2->next;
p1=p1->next;
}
return p2->val;
}
}
return -1;
}
};
9.无环单链表相交练习
方法一
先走多出来的长度
class CheckIntersect {
public:
bool chkIntersect(ListNode* headA, ListNode* headB) {
if(!headA||!headB) return 0;
ListNode* pa=headA;
ListNode* pb=headB;
int ia=0,ib=0;
while(pa)
{
pa=pa->next;
++ia;
}
while(pb)
{
pb=pb->next;
++ib;
}
pa=headA;
pb=headB;
if(ia>ib)
{
//int n=ia-ib;
//while(n)
int n=0;
while(n<(ia-ib+1))
{
pa=pa->next;
//--n
++n;
}
while(pa&&pb)
{
if(pa==pb)
return true;
else
{
pa=pa->next;
pb=pb->next;
}
}
return false;
}
else
{
//int n=ib-ia;
//while(n)
int n=0;
while(n<(ib-ia+1))
{
pb=pb->next;
//--n;
++n;
}
while(pa&&pb)
{
if(pa==pb)
return true;
else
{
pa=pa->next;
pb=pb->next;
}
}
return false;
}
}
};
方法二
直接判断有没有重复的节点即可
class ChkLoop {
public:
int chkLoop(ListNode* head, int adjust) {
set<ListNode*> tmp_set;
while(head) {
if (tmp_set.count(head)) {
return head->val;
}
tmp_set.insert(head);
head = head->next;
}
return -1;
}
};
10.有环单链表相交
先找到入环节点,然后判断这两个入环节点是否一样
class ChkIntersection {
public:
bool chkInter(ListNode* head1, ListNode* head2, int adjust0, int adjust1) {
ListNode* cy1=entry(head1);
ListNode* cy2=entry(head2);
if(cy1==cy2) return true;//即如果在入环之前前相交,则入环节点必定相等,
//如果有不同的入环节点,则遍历cy1/cy2,则必定等于另一个,否则没相交;
ListNode* trycy1=cy1->next;
while(trycy1!=cy1)
{
if(trycy1==cy2)
return true;
trycy1=trycy1->next;
}
return false;
}
ListNode* entry(ListNode *&head)
{
ListNode* first=head;
ListNode* slow=head;
while(first&&first->next)
{
first=first->next->next;
slow=slow->next;
if(first==slow)
{
first=head;
while(first!=slow)
{
first=first->next;
slow=slow->next;
}
return first;
}
}
return NULL;
}
};
11.单链表相交判断
分为无环和有环两种来判断
class ChkIntersection {
public:
bool chkInter(ListNode* head1, ListNode* head2, int adjust0, int adjust1) {
if(head1==NULL||head2==NULL) return false;
ListNode* cy1=checkcyc(head1);
ListNode* cy2=checkcyc(head2);
if(cy1&&cy2)
{
if(cy1==cy2) return true;
ListNode* trycy1=cy1->next;
while(trycy1!=cy1)
{
if(trycy1==cy2)
return true;
trycy1=trycy1->next;
}
return false;
}
//要不都有环,而且是同一个环;要不都没有环;
else
{
return nocyccut(head1,head2);
}
}
//判断无环时是否相交
bool nocyccut(ListNode*& head1, ListNode*& head2)
{
ListNode* p=head1;
ListNode* q=head2;
while(p->next!=NULL)
p=p->next;
while(q->next!=NULL)
q=q->next;
if(p==q)
return true;
else
return false;
}
//判断有无环
ListNode* checkcyc(ListNode *&head)
{
ListNode* first=head;
ListNode* slow=head;
while(first&&first->next)
{
first=first->next->next;
slow=slow->next;
if(first==slow)
{
first=head;
while(first!=slow)
{
first=first->next;
slow=slow->next;
}
return first;
}
}
return NULL;//这里必须存在,少一个return 编译不通过,可能逻辑上没什么问题;
}
};