LeetCode之链表

1 反转链表

给定一个单链表的头结点pHead,长度为n,反转该链表后,返回新链表的表头。
如当输入链表{1,2,3}时,
经反转后,原链表变为{3,2,1},所以对应的输出为{3,2,1}。

思路:
定义两个空指针 pre、next
在这里插入图片描述
将 next = head->next
在这里插入图片描述
head->next = pre
在这里插入图片描述
pre = head
在这里插入图片描述
head = next
在这里插入图片描述
next = head->next
在这里插入图片描述
pre = head->next;
在这里插入图片描述

struct ListNode* reverseList(struct ListNode* head){
    if(head == NULL || head->next == NULL){
        return head;
    }
    struct ListNode * pre = NULL;
    struct ListNode * cur = NULL;
    while(head != NULL)   {
        cur = head->next;
        head->next = pre;
        pre = head;
        head = cur;
    }
    return pre;
}

2 从尾到头打印链表

输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
示例 1:输入:head = [1,3,2]
输出:[2,3,1]

思路1:统计大小,开辟新数组,从后向前填充

int* reversePrint(struct ListNode* head, int* returnSize){
    if(head == NULL){
        *returnSize = 0;
        return NULL;
    }
    
    struct ListNode *p = head;
    int num =0;
    while(p != NULL){
        p = p->next;
        num ++;
    }

    int *res = (int *)malloc(sizeof(int)*num);
    for(int i = 0; i < num; i++){
        res[num-1-i] = head->val;
        head = head->next;
    }
    *returnSize = num;
    return res;  
}

思路2:
栈的思想,首先创建一个栈区,先入栈后出栈,根据栈的特点,出栈后的数组逆序

int* reversePrint(struct ListNode* head, int* returnSize){
    int stack[10000];
    int top = -1;
    struct ListNode *p = head;
    while(p != NULL){
        stack[++top] = p->val;
        p = p->next;
    }
    int *res = (int *)malloc(sizeof(int) * 10000);
    *returnSize = 0;
    while(top != -1){
        res[(*returnSize)++] = stack[top--];
    }
    return res;
}

思路三:递归(不是很懂)

int* reversePrint(struct ListNode* head, int* returnSize){
    if(head == NULL){
        *returnSize = 0;
        return malloc(sizeof(int) * 10000);
    }
    int *ans = reversePrint(head->next, returnSize);
    ans[(*returnSize)++] = head->val;
    return ans;
}

3 合并两个有序链表

输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。
示例1:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4

思路1:
首先开辟一个数组将两个链表中的元素保存下来,然后用一个快排排序后存入返回链表。

int cmp(const void *a, const void *b)
{
    return *(int *)a - *(int *)b;
}

struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
    if(!l1 && !l2)
        return NULL;
    int *nums = (int *)malloc(sizeof(int)*10001);
    int index = 0;
    struct ListNode *p1 = l1;
    struct ListNode *p2 = l2;
    while(p1){
        nums[index++] = p1->val;
        p1 = p1->next;
    }
    while(p2){
        nums[index++] = p2->val;
        p2 = p2->next;
    }
    qsort(nums, index, sizeof(int), cmp);
    struct ListNode *head = (struct ListNode *)malloc(sizeof(struct ListNode));
    head->val = nums[0];
    head->next = NULL;
    struct ListNode * cur = head;
    for(int i = 1; i < index; i++){
        struct ListNode *tmp = (struct ListNode *)malloc(sizeof(struct ListNode));
        tmp->val = nums[i];
        tmp->next = NULL;
        cur->next = tmp;
        cur = cur ->next;
    }
    return head;
}

思路2:
递归

struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
    if(!l1 && !l2)
        return NULL;
    if(!l1)
        return l2;
    if(!l2)
        return l1;
    struct ListNode *p = NULL;
    if(l1->val < l2->val){
        p = l1;
        p->next = mergeTwoLists(l1->next, l2);
    } else {
        p = l2;
        p->next = mergeTwoLists(l1, l2->next);
    }
    return p;
}

思路3:

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

        cur = v_h

        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
        cur.next = l1 if l1 else l2

        return v_h.next

4 链表中倒数第k个节点

示例:
给定一个链表: 1->2->3->4->5, 和 k = 2.
返回链表 4->5.

思路一:双指针
定义两个指针同时指向头指针head,fast 向后移动 k 位,这时 fast 和 slow 之间的差距是 k 位,接着两个指针一起移动,当 fast 移动到尾部时,slow 刚好定位到我们需要输出的位置。

struct ListNode* getKthFromEnd(struct ListNode* head, int k){
    if(head == NULL)
        return head;
    struct ListNode* fast = head;
    struct ListNode* slow = head;
    while(k--){
        fast = fast->next;
    }
    while(fast){
        fast  = fast->next;
        slow = slow->next;
    }
    return slow;
}

思路二:顺序查找
首先用 num 作为数组的长度,接着定位到链表的后 k 位输出。

struct ListNode* getKthFromEnd(struct ListNode* head, int k) {
    if(head == NULL)
        return head;
    int num = 0;
    struct ListNode* p = head;
    while(p) {
        p = p->next;
        num++;
    }
    p = head;
    while(k != num) {
        num --;
        p = p->next;
    }
    return p;
}

5 两个链表的第一个公共交点

在这里插入图片描述
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Reference of the node with value = 8
输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。

思路一:遍历链表

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    if(headA == NULL || headB == NULL)
        return NULL;
    struct ListNode *b = headB;
    while(headA){
        if(headA == headB)
            return headA;
        while(headB){
            if(headA == headB)
                return headA;
            headB = headB->next;
        }
        headB = b;
        headA = headA->next;
    }    
    return NULL;
}

思路二:双指针
假设俩个链表的长度分别是 L1+C 和 L2+C,当两者都遍历 L1+L2+C 的时候就相遇了,我们就定义两个指针pA pB 分别指向头,循环,pA遍历完 A 链表后指向B的头 pB遍历完 B 链表后指向 B 的头。

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    if(headA == NULL || headB == NULL)
        return NULL;
    struct ListNode *pA = headA;
    struct ListNode *pB = headB;
    while(pA != pB){
        pA = pA == NULL ? headB: pA->next;
        pB = pB == NULL ? headA: pB->next;
    }
    return pA;
}

6 删除链表中的元素

思路一:定位到要删除的元素,执行 p->next = p->next->next

struct ListNode* deleteNode(struct ListNode* head, int val){
    if(head == NULL)
        return NULL;
    if(head->val == val) /* 如果要删除的元素为第一个 */
        return head->next;
    struct ListNode *p = head;
    while((p->next->val != val) && (p->next != NULL)){
        p = p->next;
    }
    if(p->next != NULL){
        p->next = p->next->next;
    }
    return head;
}

思路二:双指针
原理同思路一

struct ListNode* deleteNode(struct ListNode* head, int val){
    if(head == NULL)
        return NULL;
    if(head->val == val)
        return head->next;
    struct ListNode *p1 = head->next;
    struct ListNode *p2 = head;
    while((p1->val != val) && (p1 != NULL)){
        p2 = p1;
        p1= p1->next;
    }
    if(p1 != NULL){
        p2->next = p1->next;
    }
    return head;
}

7 HJ51 输出单向链表中倒数第k个结点

class Node(object):
    def __init__(self, data, next = None):
        self.data = data
        self.next = next
    
class LinkedList(object):
    def __init__(self, node=None):
        self.head = None
        
    def is_empty(self):
        return self.head == None
    
    def append(self, item):
        node = Node(item)
        if self.is_empty():
            self.head = node
        else:
            cur = self.head 
            while cur.next != None:
                cur = cur.next 
            cur.next = node
            
    def pos_search(self, long, pos):
        cur = self.head 
        cur_c = 0
        if pos <= 0:
            print("0")
            return False
        else:
            while cur != None:
                cur_c += 1
                if cur_c == (long-pos+1):
                    print(cur.data)
                    return True
                else:
                    cur = cur.next 
            return False
        
if __name__ == "__main__":
    while True:
        try:
            long = int(input())
            string = input()
            pos = int(input())
            item = string.split(" ")
            l1 = LinkedList()
            for i in range(long):
                l1.append(item[i])
            l1.pos_search(long, pos)          
        except:
            break
     

8 从单向链表中删除指定值的节点

class Node:
    def __init__(self, val=None, next=None):
        self.val = val
        self.next = next 

class LinkedList():
    def __init__(self):
        self.head = Node()
        self.length = 0
        
    def insert(self, val1, val2):
        cur = self.head
        node = Node(val2)
        while cur:
            if cur.val == val1:
                node.next = cur.next 
                cur.next = node
                break
            else:
                cur = cur.next 
                
    def remove(self, val):
        cur = self.head
        pre = None
        while cur:
            if cur.val == val:
                if not pre:
                    self.head = cur.next 
                else:
                    pre.next = cur.next
                break
            else:
                pre = cur
                cur = cur.next
    
    def walk(self):
        cur = self.head
        while cur:
            print(cur.val,end=' ')
            cur = cur.next 
        print()
        

while True:
    try:
        nums = list(map(int, input().split()))
        L = LinkedList()
        L.length, L.head.val = nums[0], nums[1]
        lst = nums[2:-1]
        i,j,pairs = 0,1,[]
        while i < len(lst):
            pairs.append((lst[i], lst[j]))
            i += 2
            j += 2
        for p in pairs:
            L.insert(p[1], p[0])
        L.remove(nums[-1])
        L.walk()
        
    except:
        break        

9 单链表的排序

# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    def sortInList(self , head: ListNode) -> ListNode:
        # write code here
        p = head
        nums = []
        while p:
            nums.append(p.val)
            p = p.next
        nums.sort()
        p = head
        for x in nums:
            p.val = x
            p = p.next
        
        return head
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    def sortInList(self , head: ListNode) -> ListNode:
        # write code here
        if not head or not head.next:
            return head
        
        left, mid, right = head, head.next, head.next.next
        
        while right and right.next:
            left = left.next
            mid = mid.next
            right = right.next.next
        
        left.next = None
        
        return self.merge(self.sortInList(head), self.sortInList(mid))
    
    def merge(self, pHead1:ListNode, pHead2:ListNode):
        if not pHead1:
            return pHead2
        if not pHead2:
            return pHead1
        cur = head = ListNode(0)
        while pHead1 and pHead2:
            if pHead1.val <= pHead2.val:
                cur.next = pHead1
                pHead1 = pHead1.next
            else:
                cur.next = pHead2
                pHead2 = pHead2.next                
            cur = cur.next

        cur.next = pHead1 if pHead1 else pHead2   
        return head.next            

10 删除有序链表中重复的元素

删除所有重复

# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
#
class Solution:
    def deleteDuplicates(self , head: ListNode) -> ListNode:
        if not head:
            return head
        res = ListNode(0)
        res.next = head
        cur = res
        
        while cur.next and cur.next.next:
            if cur.next.val == cur.next.next.val:
                tmp = cur.next.val
                while cur.next != None and cur.next.val == tmp:
                    cur.next = cur.next.next
            else:
                cur = cur.next          
        return res.next     

只删除重复 保留一个

class Solution:
    def deleteDuplicates(self, head):
        if not head:
            return head
        cur = head
        while cur.next:
            if cur.val == cur.next.val:
                cur.next = cur.next.next
            else:
                cur = cur.next
        return head

11 将链表中每K个为一组翻转

class Solution:
    def reverseKGroup(self , head: ListNode, k: int) -> ListNode:
        # write code here
        if not head or not head.next:
            return head
        countNum = 0
        temp = head
        while temp:
            countNum += 1
            temp = temp.next
            if countNum >= k:
                break
        if countNum < k:
            return head
        else:
            pre = None
            start = head
            for i in range(k):
                nxt = head.next
                head.next = pre
                pre = head
                head = nxt
            start.next = self.reverseKGroup(head,k)
            return pre
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值