链表的一些leetcode题目+python(c++)

主要常见下面几个知识点: 

1-1.请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。

python:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def deleteNode(self, node):
        """
        :type node: ListNode
        :rtype: void Do not return anything, modify node in-place instead.
        """
        node.val = node.next.val
        node.next = node.next.next

c++实现:

/**
 * 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) {
        node->val = node->next->val;
        node->next = node->next->next;
    }
};

1-2.删除排序链表中的重复元素

通过将结点的值与它之后的结点进行比较来确定它是否为重复结点。如果它是重复的,我们更改当前结点的 next 指针,以便它跳过下一个结点并直接指向下一个结点之后的结点。如果不是重复的,则节点进行下移。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def deleteDuplicates(self, head: ListNode) -> ListNode:
        node = head
        while node and node.next:
            if node.val == node.next.val:
                node.next = node.next.next
            else:
                node = node.next
        return head

c++实现:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        ListNode* node = head;
        while(node !=nullptr && node->next !=nullptr){
            if(node->val == node->next->val){
                node->next = node->next->next;
            }
            else
            {
                node = node->next;
            }
        }
        return head;
    }
};

1-3.删除链表的倒数第N个节点

思路:找到链表长度,通过在头结点补充一个节点找到要删除的节点的上一个节点,然后在进行删除

方法1:循环

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        length = 0 
        node = head
        #获取链表长度
        while node:
            length+=1
            node= node.next
        # print(length)

        curr_length = 0
        new_head = ListNode(0)
        new_head.next = head
        node2=new_head
        stop_length = length - n
        #循环走到要删除节点的前一个节点
        while stop_length:
            stop_length-=1
            node2 = node2.next
        #跳过要删除的节点即可
        node2.next = node2.next.next
        return new_head.next

方法2:递归

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def __init__(self):
        self.count = 0
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        if not head:            
            return head  
        
        head.next = self.removeNthFromEnd(head.next, n) # 递归调用
        self.count += 1 # 回溯时进行节点计数
        return head.next if self.count == n else head 

方法3:双指针

fist 指针与second指针相隔n,这样first跑到尾部,second的下一个节点就是倒数第n个

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    # def __init__(self):
    #     self.count = 0
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        new_head =  ListNode(0)
        new_head.next = head
        first  = head
        second = new_head
        for i in range(n):
            first = first.next
        while first:
            first = first.next
            second = second.next
        second.next = second.next.next
        return new_head.next

c++实现: 

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* new_head = new ListNode(0);
        new_head ->next = head;
        ListNode* first = head;
        ListNode* second = new_head;
        for(int i=0;i<n;i++){
            first = first->next;
        }
        while(first){
            first = first->next;
            second = second->next;
        }
        second->next = second->next->next;
        return new_head->next;
    }
};

1-4. 删除链表的节点

思路:双指针

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    def deleteNode(self, head: ListNode, val: int) -> ListNode:
        if head is None:
            return head
        new_head = ListNode(0)
        new_head.next = head
        pre = new_head
        cur = head
        while cur.val != val:
            pre = cur
            cur = cur.next
        pre.next = cur.next
        return new_head.next

c++实现:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* deleteNode(ListNode* head, int val) {
        if(head == NULL){
            return NULL;
        }
        ListNode* new_head = new ListNode(0);
        new_head->next = head;
        ListNode* pre = new_head;
        ListNode* cur = head;
        while(cur->val != val){
            pre = cur;
            cur = cur->next;
        }
        pre->next = cur->next;
        return new_head->next;
    }
};

1-5.两两交换链表中的节点

思路:迭代法

python代码: 

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def swapPairs(self, head: ListNode) -> ListNode:
        new_head = ListNode(0)
        new_head.next = head
        temp = new_head
        while temp.next and temp.next.next:
            node1 = temp.next
            node2 = temp.next.next
            temp.next = node2
            node1.next = node2.next
            node2.next = node1
            temp = node1
        return new_head.next

c++实现:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* new_head = new ListNode(0);
        new_head->next = head;
        ListNode* temp = new_head;
        while(temp->next && temp->next->next){
            ListNode* head1 = temp->next;
            ListNode* head2 = temp->next->next;
            temp->next = head2;
            head1->next = head2->next;
            head2->next = head1;
            temp = head1;
        }
        return new_head->next;
    }
};

2-1.反转链表

思路1:双指针 

class Solution(object):
	def reverseList(self, head):
		"""
		:type head: ListNode
		:rtype: ListNode
		"""
		# 申请两个节点,pre和 cur,pre指向None
		pre = None
		cur = head
		# 遍历链表,while循环里面的内容其实可以写成一行
		while cur:
			# 记录当前节点的下一个节点
			tmp = cur.next
			# 然后将当前节点指向pre
			cur.next = pre
			# pre和cur节点都前进一位
			pre = cur
			cur = tmp
		return pre	

c++实现:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* pre = nullptr;
        ListNode* temp = head;
        while(head){
            temp = head->next;
            head->next = pre;
            pre = head;
            head = temp;
        }
        return pre;
    }
};

思路2.递归法

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        # pre = None
        # cur = head

        # while cur:
        #     node = cur.next
        #     cur.next = pre
        #     pre = cur
        #     cur = node
        # return pre
        if head is None or head.next is None:
            return head
        new_node = self.reverseList(head.next)
        print('head.val',head.val)
        head.next.next = head
        head.next = None
        return new_node

2-2:旋转链表

思路:

构成循环列表以后 找到移动的节点 在拆分

python:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def rotateRight(self, head: ListNode, k: int) -> ListNode:
        if k == 0 or head is None or head.next is None:
            return head
        #计算链表长度
        cur = head        
        n = 1
        while cur.next:
            cur = cur.next
            n += 1
        # print('==n:', n)        
        add = n - k % n
        if add == n:#k是n的整数倍直接返回原节点
            return head
        cur.next = head #构成环
        while add:
            cur = cur.next
            add -= 1
        new_head = cur.next#找到移动后的开始节点
        cur.next = None#拆开
        return new_head

c++实现:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if(k == 0 || head == nullptr || head->next == nullptr){
            return head;
        }
        int n = 1;//得到环长度
        ListNode* cur = head;
        while(cur->next){
            cur = cur->next;
            n++;
        }
        //找到移动的add长度
        int add = n - k % n;
        if(add == n){
            return head;
        }
        cur->next = head;//构成环
        while(add){
            cur = cur->next;
            add--;
        }
        ListNode* new_node = cur->next;
        cur->next = nullptr;//拆环
        return new_node;


    }
};

3-1.合并两个排序的链表

思路:引入一个指针头 python实现

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:

        head = ListNode(0)
        node = head

        while l1 and l2:
            if l1.val < l2.val:
                node.next = l1
                l1 = l1.next
            else:
                node.next = l2
                l2 = l2.next
            node = node.next
        if l1 is not None:
            node.next= l1
        if l2 is not None:
            node.next= l2
        return head.next

c++实现:

/**
 * 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) {
        ListNode* new_head = new ListNode(0);
        ListNode* node = new_head;

        while(l1!=NULL && l2 !=NULL){
            if(l1->val<l2->val){
                node->next = l1;
                l1 = l1->next;
            }
            else{
                node->next  = l2;
                l2 = l2->next;                
            }
            node = node->next;
        }

        if (l1!=NULL){
            node->next = l1;
        }
        if(l2!=NULL){
            node->next = l2;
        }
        return new_head->next;
    }
};

3-2.合并K个升序链表

思路1:上一题合并两个变成for循环顺序合并

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def mergeTwo(self, l1, l2):
        if l1 is None:
            return l2
        if l2 is None:
            return l1
        head = ListNode(0)
        node = head
        while l1 and l2:
            if l1.val <l2.val:
                node.next = l1
                l1 = l1.next
            else:
                node.next = l2
                l2 = l2.next
            node = node.next
        if l1:
            node.next = l1
        if l2:
            node.next = l2
        return head.next

    def mergeKLists(self, lists: List[ListNode]) -> ListNode:
        ans  = None
        for i in range(len(lists)):
            ans = self.mergeTwo(ans,lists[i])
        return ans

c++:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* mergtwo(ListNode* l1, ListNode* l2){
        if(l1==nullptr){
            return l2;
        }
        if(l2==nullptr){
            return l1;
        }
        ListNode* new_head= new ListNode(0);
        ListNode* node = new_head;
        while(l1 && l2){
            if(l1->val<l2->val){
                node->next = l1;
                l1= l1->next;
            }
            else{
                node->next = l2;
                l2= l2->next;
            }
            node = node->next;
        }
        if(l1){
            node->next = l1;
        }
        if(l2){
            node->next = l2;
        }
        return new_head->next;
    }
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        ListNode* res = nullptr;
        for (int i=0;i<lists.size();i++){
            res = mergtwo(res,lists[i]);
        }
        return res;
    }
};

思路2:分治归并1

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def mergeTwo(self, l1, l2):
        if l1 is None:
            return l2
        if l2 is None:
            return l1
        head = ListNode(0)
        node = head
        while l1 and l2:
            if l1.val <l2.val:
                node.next = l1
                l1 = l1.next
            else:
                node.next = l2
                l2 = l2.next
            node = node.next
        if l1:
            node.next = l1
        if l2:
            node.next = l2
        return head.next
    def mergeSort(self, lists, left, right):
        if left==right:
            return lists[left]
        middle = left + (right-left)//2
        # print('== middle:', middle)
        l1 = self.mergeSort(lists,left,middle)
        # print('== l1:', l1)
        l2 = self.mergeSort(lists,middle+1,right)
        return self.mergeTwo(l1, l2)


    def mergeKLists(self, lists: List[ListNode]) -> ListNode:
        # print('==hahah')
        if len(lists)==0:
            return None
        return self.mergeSort(lists,0,len(lists) - 1)

c++实现: 

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* mergetwo(ListNode* l1, ListNode* l2){
        if(l1==nullptr){
            return l2;
        }
        if(l2==nullptr){
            return l1;
        }
        ListNode* new_head= new ListNode(0);
        ListNode* node = new_head;
        while(l1 && l2){
            if(l1->val<l2->val){
                node->next = l1;
                l1= l1->next;
            }
            else{
                node->next = l2;
                l2= l2->next;
            }
            node = node->next;
        }
        if(l1){
            node->next = l1;
        }
        if(l2){
            node->next = l2;
        }
        return new_head->next;
    }
    ListNode* mergesort(vector<ListNode*>& lists,int left, int right){
        if(left==right){
            return lists[left];
            }
        int middle = left+(right -left)/2;
        ListNode* l1 = mergesort(lists,left,middle);
        ListNode* l2 = mergesort(lists,middle+1,right);
        return mergetwo(l1,l2);
        
    }
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        // ListNode* res = nullptr;
        // for (int i=0;i<lists.size();i++){
        //     res = mergtwo(res,lists[i]);
        // }
        // return res;
        if (lists.size()==0){
            return nullptr;
        }
        return mergesort(lists,0,lists.size()-1);
    }
};

思路3:分支归并2 参考排序算法的归并排序 https://blog.csdn.net/fanzonghao/article/details/81270601


class Solution:
    def mergeTwo(self, l1, l2):
        if l1 is None:
            return l2
        if l2 is None:
            return l1
        head = ListNode(0)
        node = head
        while l1 and l2:
            if l1.val < l2.val:
                node.next = l1
                l1 = l1.next
            else:
                node.next = l2
                l2 = l2.next
            node = node.next
        if l1:
            node.next = l1
        if l2:
            node.next = l2
        return head.next
    def mergeSort(self, L):
        if len(L) <= 1:
            return L[0]
        mid = len(L) // 2 
        l1 = self.mergeSort(L[:mid])
        l2 = self.mergeSort(L[mid:])
        return self.mergeTwo(l1, l2)
    def mergeKLists(self, lists: List[ListNode]) -> ListNode:
        if len(lists)==0:
            return None
        return self.mergeSort(lists)

3-3.合并两个有序链表

思路:递归 终止条件就是节点为None.

1.递归法 

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
        #递归的终止条件
        if l1 is None:
            return l2
        elif l2 is None:
            return l1    

        elif l1.val < l2.val:
            l1.next = self.mergeTwoLists(l1.next,l2)
            return l1
        else:
            l2.next = self.mergeTwoLists(l1,l2.next)
            return l2
        

2.迭代法:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
        fake_head_node  = ListNode(0)

        cur = fake_head_node

        while l1 and l2:
            if l1.val<l2.val:
                cur.next = l1
                l1 = l1.next
            else:
                cur.next = l2
                l2 = l2.next            
            cur = cur.next
        
        if l1:
            cur.next = l1
        else:
            cur.next = l2

        return fake_head_node.next
            

3-4.排序链表

思路1:归并排序 先通过快慢指针找到中心点 进行截断以后一直递归拆开 在进行合并即可

python代码:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def merge(self, left, right):
        res = ListNode(0)
        temp = res
        while left and right:
            if left.val < right.val:
                temp.next, left = left, left.next
            else:
                temp.next, right = right, right.next
            temp = temp.next
        temp.next = left if left else right
        return res.next

    def sortList(self, head: ListNode) -> ListNode:
        if head is None or head.next is None:
            return head 
        #快慢指针找到链表中心点
        slow, fast = head, head.next
        while fast and fast.next:
            fast, slow = fast.next.next, slow.next
        mid, slow.next = slow.next, None#将找到的中心点进行截断故 slow.next = None
        
        left, right = self.sortList(head), self.sortList(mid)#递归一直进行拆分

        return self.merge(left, right)#合并操作
        

c++代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* mergetwo(ListNode* l1,ListNode* l2){
        ListNode* new_head = new ListNode(0);
        ListNode* node = new_head;
        while(l1 && l2){
            if(l1->val<l2->val){
                node->next = l1;
                l1 = l1->next;
            }
            else{
                node->next = l2;
                l2 = l2->next;
            }
            node = node->next;
        }
        if(l1){
            node->next = l1;
        }
        if(l2){
            node->next = l2;
        }
        return new_head->next;
    }
    ListNode* sortList(ListNode* head) {
        if(head==nullptr || head->next==nullptr){
            return head;
        }
        ListNode* slow = head;
        ListNode* fast = head->next;
        while(fast && fast->next){
            slow = slow->next;
            fast = fast->next->next;
        }
        ListNode* middle = slow->next;
        slow->next = nullptr;
        ListNode* l1 = sortList(head);
        ListNode* l2 = sortList(middle);
        return mergetwo(l1,l2);
    }
};

思路2:合并也是递归

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    # def merge(self, left, right):
    #     res = ListNode(0)
    #     temp = res
    #     while left and right:
    #         if left.val < right.val:
    #             temp.next, left = left, left.next
    #         else:
    #             temp.next, right = right, right.next
    #         temp = temp.next
    #     temp.next = left if left else right
    #     return res.next
    def merge(self,left,right):
        if left is None:
            return right
        if right is None:
            return left
        if left.val < right.val:
            left.next = self.merge(left.next, right)
            return left
        else:
            right.next = self.merge(left, right.next)
            return right

    def sortList(self, head: ListNode) -> ListNode:
        if head is None or head.next is None:
            return head 
        #快慢指针找到链表中心点
        slow, fast = head, head.next
        while fast and fast.next:
            fast, slow = fast.next.next, slow.next
        mid, slow.next = slow.next, None#将找到的中心点进行截断故 slow.next = None
        
        left, right = self.sortList(head), self.sortList(mid)#递归一直进行拆分

        return self.merge(left, right)#合并操作
        

3-5.两数相加 

思路:开出一个head头,利用一个指针进行遍历,需要注意的是进位

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        head = ListNode(0)
        new_node = head
        carry = 0
        while l1 and l2:
            new_node.next =ListNode(l1.val+l2.val+carry)
            carry = new_node.next.val//10 
            new_node.next.val = new_node.next.val%10
            l1 = l1.next
            l2= l2.next
            new_node = new_node.next
        # print(carry)
        while l1:
            new_node.next = ListNode(l1.val+carry)
            carry  = new_node.next.val//10
            new_node.next.val = new_node.next.val%10
            l1 = l1.next
            new_node = new_node.next
        while l2:
            new_node.next =  ListNode(l2.val+carry)
            carry  = new_node.next.val//10
            new_node.next.val = new_node.next.val%10
            l2 = l2.next
            new_node = new_node.next
        if carry:
            new_node.next =  ListNode(carry)
        return head.next

c++实现:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode* head = new ListNode(0);
        ListNode* new_head = head;
        int carry = 0;
        while(l1 && l2){
            new_head->next = new ListNode(l1->val + l2->val + carry);
            carry = new_head->next->val/10;
            new_head->next->val = new_head->next->val%10;            
            new_head = new_head->next;
            l1 = l1->next;
            l2 = l2->next;
        }

        while(l1){
            new_head->next = new ListNode(l1->val + carry);
            carry = new_head->next->val/10;
            new_head->next->val = new_head->next->val%10;  
            new_head = new_head->next;
            l1 = l1->next;
        }
        while(l2){
            new_head->next = new ListNode(l2->val + carry);
            carry = new_head->next->val/10;
            new_head->next->val = new_head->next->val%10;  
            new_head = new_head->next;
            l2 = l2->next;
        }
        if(carry){
            new_head->next = new ListNode(carry);
        }
        return head->next;



    }
};

4-1.环形链表

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        #快慢指针 人追人
        slow,fast = head,head

        while fast:
            if fast and fast.next:
                slow = slow.next
                fast=fast.next.next
            else:
                return False
            if slow==fast:
                return True
            
            
        return False

c++实现:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool hasCycle(ListNode *head) {
        ListNode* slow = head;
        ListNode* fast = head;
        while(fast){
            if(fast && fast->next){
                slow = slow->next;
                fast = fast->next->next;
            }
            else{
                return false;
            }
            if(slow==fast){
                return true;
            }
        }
        return false;
    }
};

4-2.给定一个有环链表,实现一个算法返回环路的开头节点。

假设有两个指针,分别为快慢指针fast和slow, 快指针每次走两步,慢指针每次前进一步,如果有环则两个指针必定相遇;

反证法:假设快指针真的 越过 了慢指针,且快指针处于位置 i+1,而慢指针处于位置 i,那么在前一步,快指针处于位置 i-1,慢指针也处于位置 i-1,它们相遇了。

A:链表起点
B:环起点
C:相遇点
X:环起点到相遇点距离
Y:链表起点到环起点距离
R:环的长度
S:第一次相遇时走过的路程

1.慢指针slow第一次相遇走过的路程 S1 = Y + X;(11)
快指针fast第一次相遇走过的路程 S2=2S1 = Y + X + NR;(2)
说明:快指针的速度是慢指针的两倍,相同时间内路程应该是慢指针的两倍,Y + X + NR是因为快指针可能经过N圈后两者才相遇;
把(1)式代入(2)式得:Y = NR -X; 

2..在将慢指针回到A点,满指针和快指针同时走,在B点相遇,此处就是环节点.

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def detectCycle(self, head: ListNode) -> ListNode:
        slow = head
        fast = head;
        while fast:
            if fast and fast.next:
                slow = slow.next
                fast = fast.next.next
            else:
                return None
            if slow==fast:
                break
        if fast ==None or fast.next==None:
            return None
        slow= head
        while slow!=fast:
            slow = slow.next
            fast = fast.next

        return slow

c++实现:

/**
 * 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) {
        ListNode* slow = head;
        ListNode* fast = head;
        while(fast){
            if(fast && fast->next){
                slow = slow->next;
                fast = fast->next->next;
            }
            else{
                return NULL;
            }
            if(slow==fast){
                break;
            }
        }
        if(!fast || !fast->next){
            return NULL;
        }
        slow = head;
        while(slow!=fast){
            slow = slow->next;
            fast = fast->next;
        }
        return slow;
        
    }
};

4-3.链表相交

如这题应该是比较明显的双指针题,要是能实现一种算法让两个指针分别从A和B点往C点走,两个指针分别走到C后,又各自从另外一个指针的起点,也就是A指针第二次走从B点开始走,B指针同理,这样,A指针走的路径长度 AO + OC + BO 必定等于B指针走的路径长度 BO + OC + AO,这也就意味着这两个指针第二轮走必定会在O点相遇,相遇后也即到达了退出循环的条件,代码如下:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        index_a =  headA
        index_b = headB
        while index_a !=index_b:
            if index_a !=None:
                index_a = index_a.next
            else:
                index_a = headB
            if index_b != None:
                index_b = index_b.next
            else:
                index_b = headA
        return index_a

            

c++实现:

/**
 * 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) {
        ListNode* node_A = headA;
        ListNode* node_B = headB;
        while(node_A!=node_B){
            if(node_A!=NULL){
                node_A=node_A->next;
            }
            else{
                node_A = headB;
            }
            if(node_B!=NULL){
                node_B=node_B->next;
            }
            else{
                node_B = headA;
            }
        }
        return node_A;
        
        
    }
};

4-4.两个链表的第一个公共节点

思路:双指针 两个指针轮流走一遍各自的路程,这样相遇就是公共节点,对于没有公共节点的情况,所以需要判断自身节点不是none,而不是.next是none,在去交换指针,否则会陷入无穷循环,而此时输出就是none。

python

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        first_head = headA
        second_head = headB
        while first_head !=second_head:
            if first_head is not None:
                first_head = first_head.next 
            else:
                first_head = headB
            if second_head is not None:
                second_head = second_head.next
            else:
                second_head = headA
        # print(first_head)
        return first_head

c++:

/**
 * 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) {
    ListNode *first_node;
    first_node = headA;
    ListNode *second_node;
    second_node= headB;
    while(first_node != second_node)
    {
        if(first_node !=NULL)
        {
            first_node = first_node->next;
        }
        else
        {
            first_node = headB;
        }

        if(second_node !=NULL)
        {
            second_node = second_node->next;
        }
        else
        {
            second_node = headA;
        }
    }
    return first_node;
        
    }
};

5-1.输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。

1.借用栈

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def reversePrint(self, head: ListNode) -> List[int]:
        stack = []
        while head:
            stack.append(head.val)
            head = head.next
        return stack[::-1]

c++:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> reversePrint(ListNode* head) {
        vector<int> res;
        while(head){
            res.push_back(head->val);
            head = head->next;
        }
        reverse(res.begin(),res.end());
        return res;

    }
};

2.递归回溯

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def reversePrint(self, head: ListNode) -> List[int]:
        if head:
            return self.reversePrint(head.next)+[head.val]
        else:
            return []

5-2.请判断一个链表是否为回文链表

利用列表将列表值进行拷贝,在判断是否是回文字符串

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def isPalindrome(self, head: ListNode) -> bool:
        stack= []
        while head:
            stack.append(head.val)
            head = head.next
        return stack==stack[::-1]

c++实现:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        vector<int> res;
        while(head){
            res.push_back(head->val);
            head = head->next;
        }
        int left=0;
        int right=res.size()-1;
        while(left<right){
            if(res[left]==res[right]){
                left+=1;
                right-=1;
            }
            else{
                return false;
            }
        }
        return true;

    }
};

5-3.分隔链表

思路:开出两个大小节点,用于指向大于x和小于x的,遍历结束以后在合并即可

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def partition(self, head: ListNode, x: int) -> ListNode:
        small_head = ListNode(0)
        large_head = ListNode(0)

        small_node = small_head
        large_node = large_head


        while head:
            if head.val < x:
                small_node.next = head
                small_node = small_node.next
            else:
                large_node.next  = head
                large_node = large_node.next
            head= head.next
        large_node.next = None
        small_node.next = large_head.next
        return small_head.next

c++写法:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* partition(ListNode* head, int x) {
        ListNode* small_head = new ListNode(0);
        ListNode* big_head = new ListNode(0);
        ListNode* small_node =small_head;
        ListNode* big_node = big_head;
        while(head){
            if (head->val<x){
                small_node->next = head;                
                small_node = small_node->next;
            }
            else{
                big_node->next = head;
                big_node = big_node->next;
            }
            head = head->next;
        }
        big_node->next = nullptr;
        small_node->next = big_head->next;
        return small_head->next;
    }
};

6-1.二叉树展开为链表

思路:可看出是根据前序遍历的节点统统放在右子树上

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def help(self, node):
        if node is not None:
            self.res.append(node)
            self.help(node.left)
            self.help(node.right)
    def flatten(self, root: TreeNode) -> None:
        """
        Do not return anything, modify root in-place instead.
        """
        self.res = []
        self.help(root)
        # print(self.res)
        length = len(self.res)
        for i in range(1,length):
            pre,cur = self.res[i-1],self.res[i]
            pre.left = None
            pre.right = cur
        return root

c++实现:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<TreeNode* >res;

    void help(TreeNode* node){
        if(node){
            res.push_back(node);
            help(node->left);
            help(node->right);
        }
    }
    void flatten(TreeNode* root) {
        help(root);
        for(int i=1;i<res.size();i++){
            TreeNode* pre = res[i-1];
            TreeNode* cur =  res[i];
            pre->left = nullptr;
            pre->right = cur;
        }
        // return root;
    }
};

猜你喜欢

转载自blog.csdn.net/fanzonghao/article/details/113889824