《劍指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
                

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章