《剑指offer---链表》:第3、15、16、14、56题(python、C++)

第3题:

输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。

解题思路:

不改变原有链表的结构,使用栈实现反向输出。遍历链表,每经过一个节点,把该节点放到栈中。遍历结束后,从栈顶逐个输出节点的值,保存在vector中。

C++
/**
*  struct ListNode {
*        int val;
*        struct ListNode *next;
*        ListNode(int x) :
*              val(x), next(NULL) {
*        }
*  };
*/

class Solution
{
public:
	vector<int> printListFromTailToHead(ListNode *head)
	{
		stack<int> tmp_stack;
		vector<int> v1;
        ListNode *ptr = head;
		while (ptr != nullptr)
		{
			tmp_stack.push(ptr->val);
			ptr = ptr->next;
		}
		while (!tmp_stack.empty())
		{
			v1.push_back(tmp_stack.pop());
			tmp_stack.pop();
		}
		return v1;
	}
};

 

python

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    # 返回从尾部到头部的列表值序列,例如[1,2,3]
    def printListFromTailToHead(self, listNode):
        # write code here
        res=[]
        while(listNode != None):
            res.append(listNode.val)
            listNode=listNode.next
        return res[::-1]

第15题:

输入一个链表,反转链表后,输出新链表的表头。

C++

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if(pHead==nullptr)
            return nullptr;
        ListNode* p=pHead;
        ListNode* q=nullptr;
        while(p!=nullptr)//运行3ms
        {
            ListNode*tmp=p->next;//在逆置前先缓存下一个节点的位置,存在tmp里
            p->next=q;//逆置,q为p之前的一个节点
            q=p;//让q下移一个节点
            p=tmp;
        }
/*方法2:运行2ms
while (p != nullptr)
{
	ListNode* tmp = q;
	q = p;//q向后移,移动到p
	p = p->next;//p向后移
	q->next = tmp;//q->next 置为null
}
*/

        return q;
    }
};

 

python
# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    # 返回ListNode
    def ReverseList(self, pHead):
        # write code here
        p=pHead
        q=None
        while p!=None:
            tmp=p.next
            p.next=q
            q=p
            p=tmp
        return q

第16题:

输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

C++
/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
    {
        ListNode* p1=pHead1;
        ListNode* p2=pHead2;
        ListNode* head=new ListNode(0);
        head->next=nullptr;
        ListNode* ptr=head;
        while(p1!=nullptr && p2!=nullptr)
        {
            if(p1->val<p2->val)
            {
                ptr->next=p1;
                p1=p1->next;
            }
            else
            {    
                ptr->next=p2;
                p2=p2->next;
            }
            ptr=ptr->next;
        }
        if(p1==nullptr)
            ptr->next=p2;
        if (p2==nullptr)
            ptr->next=p1;
            
        return head->next;
    }
};

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};*/
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=pHead1;
            head->next=Merge(pHead1->next,pHead2);
        }
        if(pHead1->val >pHead2->val)
        {
            head=pHead2;
            head->next=Merge(pHead1,pHead2->next);
        }
        return head;

    }
};


python
方法一:
# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    # 返回合并后列表
    def Merge(self, pHead1, pHead2):
        # write code here
        head = ListNode(22)
        p = head  # p用来当做循环操作的指针
        # 当两个链表全都不为空,执行循环
        while pHead1 and pHead2:
            if pHead1.val <= pHead2.val:
                p.next = pHead1
                # 从pHead1中取出头结点时,头结点变为原头结点的next节点
                pHead1 = pHead1.next    
            elif pHead1.val > pHead2.val:
                p.next = pHead2
                pHead2 = pHead2.next    # 同理
            p = p.next    # 每次向head3追加一个节点时,指针p偏倚
        # 如果pHead1不为None,直接把剩下的pHead1追加到pHead3后
        while pHead1:
            p.next = pHead1
            pHead1 = pHead1.next
            p = p.next
        # 同理
        while pHead2:
            p.next = pHead2
            pHead2 = pHead2.next
            p = p.next
        # 返回的结果,去掉head3创建时的无意义首节点
        return head.next


方法2:
# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    # 返回合并后列表
    def Merge(self, pHead1, pHead2):
        # write code here
        ls = []
        # 取出两个链表中头节值较小的节点,追加到ls末尾
        while pHead1 or pHead2:
            # 当pHead1链表所有节点被取光的情况
            if pHead1 == None:
                ls.append(pHead2)
                pHead2 = pHead2.next
            # 同理
            elif pHead2 == None:
                ls.append(pHead1)
                pHead1 = pHead1.next
            elif pHead1.val <= pHead2.val:
                ls.append(pHead1)
                pHead1 = pHead1.next
            elif pHead1.val > pHead2.val:
                ls.append(pHead2)
                pHead2 = pHead2.next
        # 如果ls为空,说明原两链表都为空,return None
        if ls == []:
            return None
        # 除了列表的最后一个元素,使每个元素的next指向其下一个
        for i in range(len(ls)-1):
            ls[i].next = ls[i+1]
        # 列表最后一个元素的next指向None
        ls[len(ls)-1].next = None
        # 返回结果
        return ls[0]

第14题:

链表中倒数第K个节点

C++
/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
//思路:把节点放入vector中,多定义一个计数器n即多增加内存,所以下面的代码可以改进,直接使用
//vector的size()函数求得节点的个数
class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        if(pListHead==NULL || k==0)
            return NULL;
        ListNode* ptr =pListHead;
        vector<ListNode*> v1;
        unsigned int n=0;
        while (ptr != nullptr)
        {
            v1.push_back(ptr);
            n++;
            ptr = ptr->next;
        }
        if(n<k || n==0)
            return NULL;
        return v1[n-k];
    }
};

//改进
class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
         if(pListHead==NULL || k==0)
            return NULL;
        vector<ListNode*> data;
        while(pListHead != NULL)
        {
            data.push_back(pListHead);
            pListHead=pListHead->next;
        }
        int len = data.size();
        if(len<k || k==0)
            return NULL;
        return data[len-k];

    }
};

//思路2:定义两个指针,中间相隔k-1个距离(节点)
//当第一个节点走到链表最后时,第二个指针即指向倒数第k个节点

/*
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==nullptr || k<=0 )
            return nullptr;
        ListNode *p1,*p2;
        p1=p2=pListHead;
        for(unsigned int i=0;i<k-1;i++)
        {
            if(p1->next != nullptr)
                p1=p1->next;
            else
            {
                return nullptr;
            }
        }
           
        while(p1->next != nullptr)
        {
            p1=p1->next;
            p2=p2->next;
        }
        return p2;
    }
};



python  

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def FindKthToTail(self, head, k):
        # write code here
        node=[]
        if (head==None or k==0):
            return None
        while(head != None):
            node.append(head)
            head=head.next
        length=len(node)
        if(length<k or k==0 ):
            return None
        return node[length-k]

第56题:

在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5

解题思路: #要删除有序链表中所有的重复节点,而头结点有可能就是重复节点。
        #这样的比较好的解决方式就是新建头结点,然后往后遍历,同样的值就全部略过。

C++//错误
/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead)
    {
        if(pHead==nullptr)
            return nullptr;
        if(pHead!=nullptr || pHead->next==nullptr)
            return pHead;
        ListNode *first= new ListNode(-1);
        first->next=pHead;
        ListNode *p0=first;
        ListNode *p1=pHead;
 
        
        while(p1 != nullptr && p1->next!=nullptr)
        {
            if(p1->val==p1->next->val)
            {
                int data=p1->val;
                while(p1 !=nullptr && data==p1->val)
                {
                    ListNode*tmp=p1;
                    p1=p1->next;
                    delete tmp;
                    tmp=nullptr;
                }
                p0->next=p1;
            }
            else
            {
                p0=p0->next;
                p1=p1->next;
                p0->next=p1;
            }
        }
        return first->next;

    }
};


python 
# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    def deleteDuplication(self, pHead):
        # write code here
        #要删除有序链表中所有的重复节点,而头结点有可能就是重复节点。
        #这样的比较好的解决方式就是新建头结点,然后往后遍历,同样的值就全部略过。
        first=ListNode(-1)#创建一个新的头结点
        first.next=pHead
        curr=pHead
        last=first
        while curr and curr.next:
            if curr.val != curr.next.val:
                curr=curr.next
                last=last.next
            else :
                val=curr.val
                while curr and curr.val==val:
                    curr=curr.next
                last.next=curr
        return first.next
                

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值