程序员代码面试指南 第二章 链表问题

9 篇文章 3 订阅

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 按照左右半区的方式重新排列组合单链表

思路:遍历链表找到左半区的最后一个节点,将左右半区分离成两个链表,然后按题目要求合并。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值