2.1 打印两个有序链表的公共部分
思路:因为是有序链表,所以从两个链表的头开始进行如下判断:如果head1的值小于head2,则head1往下移动。如果head2的值小于head1,则head2往下移动。如果head1的值与head2的值相等,则打印这个值,然后head1和head2都往下移动。head1和head2有任何一个移动到null,则整个过程停止。
2.2 在单链表和双链表中删除倒数第k个节点(LeetCode 19)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
//if(head->next==NULL)return NULL;
ListNode* first=head,*second=head;
for(int i=0;i<n;i++){
first=first->next;
}
if(first==NULL){
head=head->next;
return head;
}
while(first->next!=NULL){
second=second->next;
first=first->next;
}
second->next=second->next->next;
return head;
}
};
双链表处理方式与单链表相似。
剑指offer
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
if(pListHead==NULL || k<1)return NULL;
ListNode* left=pListHead,*right=pListHead;
for(int i=1;i<k;i++){
right=right->next;
if(right==NULL)return NULL;
}
while(right->next){
right=right->next;
left=left->next;
}
return left;
}
};
2.3 删除链表的中间节点和a/b处的节点
2.4 翻转单向和双向链表(LeetCode206)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* pre=NULL,*next=NULL;
while(head){
next=head->next;
head->next=pre;
pre=head;
head=next;
}
return pre;
}
};
双向链表同理。
2.5 翻转部分单向链表
2.6 环形单链表的约瑟夫问题
//此代码非链表
class Solution {
public:
int LastRemaining_Solution(int n, int m)
{/*
queue<int> q;
for(int i=0;i<n;i++){
q.push(i);
}
int cur=0,front=-1;
while(!q.empty()){
front=q.front();
q.pop();
if(++cur==m){
cur=0;
}
else{
q.push(front);
}
}
return front;*/
if(n==0)return -1;
int res=0;
for(int i=2;i<=n;i++){
res=(res+m)%i;
}
return res;
}
};
2.7判断一个链表是否为回文结构(LeetCode 234)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool isPalindrome(ListNode* head) {
temp=head;
return check(head);
}
private:
ListNode *temp;
bool check(ListNode* node){
if(node==NULL)return true;
bool flag=check(node->next)&&(temp->val==node->val);
temp=temp->next;
return flag;
}
};
//time O(n)
//space O(n)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool isPalindrome(ListNode* head) {
if(!head||!head->next)return true;
ListNode *a=head,*b=head,*c;
while(a->next&&a->next->next){
a=a->next->next;
b=b->next;
}
a=b->next;
b->next=NULL;
while(a){
c=a->next;
a->next=b;
b=a;
a=c;
}
a=head;
c=b;
bool res=true;
while(a&&b){
if(a->val!=b->val){
res=false;
break;
}
a=a->next;
b=b->next;
}
a=c;
b=NULL;
while(a){
c=a->next;
a->next=b;
b=a;
a=c;
}
return res;
}
};
//time O(n) space O(1)
2.8 将单向链表按某值划分成左边小、中间相等、右边大的形式(LeetCode 86)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* partition(ListNode* head, int x) {
ListNode *a=NULL,*b=NULL,*c=NULL,*d=NULL,*next;
while(head){
next=head->next;
head->next=NULL;
if(head->val<x){
if(a==NULL){
a=head;
b=head;
}
else{
b->next=head;
b=b->next;
}
}
else{
if(c==NULL){
c=head;
d=head;
}
else{
d->next=head;
d=d->next;
}
}
head=next;
}
if(a!=NULL){
b->next=c;
return a;
}
else return c;
}
};
2.9 复制含有随机指针节点的链表(LeetCode138)
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;
Node() {}
Node(int _val, Node* _next, Node* _random) {
val = _val;
next = _next;
random = _random;
}
};
*/
class Solution {
public:
Node* copyRandomList(Node* head) {
if(head==NULL)return NULL;
Node* temp=head;
while(temp!=NULL){
temp->next=new Node(temp->val,temp->next,temp->random);;
temp=temp->next->next;
}
temp=head;
while(temp!=NULL){
temp=temp->next;
temp->random=(temp->random==NULL)?NULL:temp->random->next;
temp=temp->next;
}
temp=head;
Node* res=head->next,*copy=head->next;
while(temp!=NULL){
temp->next=copy->next;
copy->next=(temp->next==NULL)?NULL:temp->next->next;
temp=temp->next;
copy=copy->next;
}
return res;
}
};
剑指offer
/*
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==NULL)return NULL;
RandomListNode* cur=pHead,*next;
while(cur!=NULL){
next=cur->next;
cur->next=new RandomListNode(cur->label);
cur->next->next=next;
cur->next->random=cur->random;
cur=next;
}
cur=pHead->next;
while(cur->next!=NULL){ //attention next
cur->random=cur->random?cur->random->next:NULL;//attention ?:
cur=cur->next->next;
}
RandomListNode* res=pHead->next;
cur=pHead;
while(cur!=NULL){
next=cur->next->next;
cur->next->next=next?next->next:NULL;
cur->next=next;
cur=next;
}
return res;
}
};
2.10 两个单链表生成相加链表(LeetCode 2、445)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
int a, b, x, carry = 0;
ListNode* dummy = new ListNode(0);
ListNode* temp = dummy;
while (l1 != NULL || l2 != NULL)
{
if (l1 != NULL){
a = l1->val;
l1 = l1->next;
}
else a = 0;
if (l2 != NULL){
b = l2->val;
l2 = l2->next;
}
else b = 0;
x = a + b + carry;
carry = 0;
if (x >= 10){
x -= 10;
carry = 1;
}
temp->next = new ListNode(x);
temp = temp->next;
}
if(carry>0)temp->next = new ListNode(carry);
return dummy->next;
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
stack<int> s1,s2;
while(l1){
s1.push(l1->val);
l1=l1->next;
}
while(l2){
s2.push(l2->val);
l2=l2->next;
}
ListNode* temp=NULL;
int a,b,sum=0,carry=0;
while(!s1.empty()||!s2.empty()||carry){
if(!s1.empty()){
a=s1.top();
s1.pop();
}
else a=0;
if(!s2.empty()){
b=s2.top();
s2.pop();
}
else b=0;
sum=a+b+carry;
carry=0;
if(sum>=10){
sum-=10;
carry=1;
}
ListNode *add=new ListNode(sum);
add->next=temp;
temp=add;
}
return temp;
}
};
2.11 两个单链表相交的一系列问题
子问题一:判断一个链表是否有环(LeetCode 142)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if(!head||!head->next)return NULL;
ListNode *l=head;
ListNode *r=head;
do{
if(!r->next||!r->next->next)return NULL;
r=r->next->next;
l=l->next;
}while(l!=r);
r=head;
while(l!=r){
r=r->next;
l=l->next;
}
return r;
}
};
子问题二:如何判断两个无环链表是否相交(LeetCode160)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if(headA==NULL||headB==NULL)return NULL;
ListNode *a=headA, *b=headB;
while(a!=b) {
if(a==NULL)a=headB;
else a=a->next;
if(b==NULL)b=headA;
else b=b->next;
}
return a;
}
};
子问题三:如何判断两个有环链表是否相交
思路:若两个环的入口相同,则转变为子问题二;若两个环的入口不同,遍历其中一个环,看是否有节点和另一个环节点相同,有的话是相交的。
2.12 将单链表的每K个节点之间逆序(LeetCode 25)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
if(k<2)return head;
ListNode *pre=NULL,*start,*cur=head,*next;
int count=1;
while(cur!=NULL){
next=cur->next;
if(count==k){
if(pre==NULL){
start=head;
head=cur;
}else{
start=pre->next;
}
reverse(pre,start,cur,next);
pre=start;
count=0;
}
count++;
cur=next;
}
return head;
}
void reverse(ListNode* left ,ListNode* start,ListNode* end, ListNode* right){
ListNode* pre=start;
ListNode* cur=start->next;
ListNode* next=NULL;
while(cur!=right){
next=cur->next;
cur->next=pre;
pre=cur;
cur=next;
}
if(left!=NULL)left->next=end;
start->next=right;
}
};
2.13 删除无序列表中值重复出现的节点(LeetCode 83)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
ListNode *cur=head, *pre=NULL,*next=NULL;
int val;
while(cur!=NULL){
pre=cur;
next=cur->next;
while(next!=NULL){
if(cur->val==next->val){
pre->next=next->next;
delete next;
next=pre->next;
}else{
pre=pre->next;
next=next->next;
}
}
cur=cur->next;
}
return head;
}
};
2.14 在单链表中删除指定值的节点(LeetCode 203)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
while(head!=NULL){
if(head->val==val)head=head->next;
else break;
}
ListNode *pre=head,*cur=head; //use pre to save last valid node
while(cur!=NULL){
if(cur->val==val){
pre->next=cur->next;
}else{
pre=cur;
}
cur=cur->next;
}
return head;
}
};
2.15 将搜索二叉树转换成双向链表(LeetCode 426)
思路:方法一、将二叉树中序遍历,按顺序放入队列,从队列中依次弹出节点,重连为双向链表;方法二、待续。
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
TreeNode* Convert(TreeNode* pRootOfTree)
{
if(pRootOfTree==NULL)return NULL;
TreeNode* pre=NULL;
inorder(pRootOfTree,pre);
TreeNode* res=pRootOfTree;
while(res->left)res=res->left;//注意是while
return res;
}
void inorder(TreeNode* cur, TreeNode* &pre)
{
if(cur==NULL) return;
inorder(cur->left,pre);
if(pre)pre->right=cur;
cur->left=pre;
pre=cur;
inorder(cur->right,pre);
}
};
2.16 单链表的选择排序
2.17 一种怪异的节点删除方式(LeetCode 237)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
void deleteNode(ListNode* node) {
ListNode* next=node->next;
*node=*next;
delete next;
}
};
2.18 向有序的环形单链表中插入新节点(LeetCode 708)
2.19 合并两个有序的链表(LeetCode 21)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if(l1==NULL)return l2;
if(l2==NULL)return l1;
if(l1->val<l2->val){
l1->next=mergeTwoLists(l1->next,l2);
return l1;
}else{
l2->next=mergeTwoLists(l1,l2->next);
return l2;
}
}
};
2.20 按照左右半区的方式重新排列组合单链表
思路:遍历链表找到左半区的最后一个节点,将左右半区分离成两个链表,然后按题目要求合并。