Datawhale编程学习之数组和链表(1)


任务1:1~2天

1.学习目标

自己知识还是有很多不足,学习这个课程还是有难度的,身边真的是有很多优秀的人,希望可以跟随你们的脚步好好学习。

1.1 数组

实现一个支持动态扩容的数组
实现一个大小固定的有序数组,支持动态增删改操作
实现两个有序数组合并为一个有序数组
学习哈希表思想,并完成leetcode上的两数之和(1)及Happy Number(202)!(要求全部用哈希思想实现!)(选做)

1.2 链表

实现单链表、循环链表、双向链表,支持增删操作
实现单链表反转
实现两个有序的链表合并为一个有序链表
实现求链表的中间结点

1.3 LeetCode练习题

数组
Three Sum(求三数之和,第15题,难度:Medium)
英文版:Loading…
中文版:Loading…

Majority Element(求众数,第169题,难度:Easy)
英文版:Loading…
中文版:Loading…

Missing Positive(求缺失的第一个正数,第41题,难度:hard)
英文版:Loading…
中文版:Loading…

链表
Linked List Cycle I(环形链表,第141题,难度:Easy)
英文版:Loading…
中文版:Loading…

Merge k Sorted Lists(合并 k 个排序链表,第23题,难度:hard)
英文版:Loading…
中文版:Loading…

2.学习过程

2.1数组

2.1.1实现一个支持动态扩容的数组

class dyArray(object):
    def __init__(self, obj, capacity=10):
        self._data_type = obj
        self._data = [None] * capacity
        self._size = 0

    def __str__(self):
        return f"size: {self._size}, " \
               f"capacity: {len(self._data)}\n{str(self._data[:self._size])}"

    def _resize(self, new_cap):
        if new_cap == 0:
            raise ValueError('capacity can not be zero!')
        new_data = [None] * new_cap
        new_data[:self._size] = self._data[:self._size]
        self._data = new_data

    def push(self, v, k):
        if self._size == len(self._data):
            self._resize(2*self._size)
        for i in range(self._size-1, k-1, -1):
            self._data[i+1] = self._data[i]
        self._data[k] = v
        self._size += 1

if __name__ == '__main__':
    A = dyArray(int)
    for i in range(12):
        A.push(i, i)
    print(A.__str__())

2.1.2实现一个大小固定的有序数组,支持动态增删改操作

class dyArray(object):
    def __init__(self, obj, capacity=10):
        self._data_type = obj
        self._data = [None] * capacity
        self._size = 0

    def __str__(self):
        return f"size: {self._size}, " \
               f"capacity: {len(self._data)}\n{str(self._data[:self._size])}"
    """
    def _resize(self, new_cap):
        if new_cap == 0:
            raise ValueError('capacity can not be zero!')
        new_data = [None] * new_cap
        new_data[:self._size] = self._data[:self._size]
        self._data = new_data

    """
    # 增
    def insert(self, v, k):
        #if self._size == len(self._data):
            #self._resize(2*self._size)
        if k >= len(self._data):
            raise IndexError('Index out of range!')
        for i in range(self._size-1, k-1, -1):
            self._data[i+1] = self._data[i]
        self._data[k] = v
        self._size += 1

    def push_last(self, v):
        self.insert(v, self._size)

    def push_first(self, v):
        self.insert(v, 0)

    # 删
    def delete(self, k):
        value = self._data[k]
        for i in range(k+1, self._size):
            self._data[i - 1] = self._data[i]
        self._size -= 1
        return value
    def delete_ele(self, v):
        key = self.find(v)
        if key != -1:
            return self.delete(key)

    # g改
    def set(self, k, v):
        self._data[k] = v

    # 查
    def find(self, v):
        for idx, item in enumerate(self._data):
            if item == v:
                return idx
        return -1

if __name__ == '__main__':
    A = dyArray(int)

    for i in range(10):
        A.insert(i, i)
    print(A.__str__())
    A.delete(5)
    print(A.__str__())
    A.set(3,100)
    print(A.__str__())
    A.find(8)

2.1.3实现两个有序数组合并为一个有序数组

def merge(a, b):
    indexa = 0
    indexb = 0
    li = []
    while indexa < len(a) and indexb < len(b):
        if a[indexa] <= b[indexb]:
            li.append(a[indexa])
            indexa += 1
        else:
            li.append(b[indexb])
            indexb += 1
        li = li + a[indexa:] + b[indexb:]
        return li

if __name__ == '__main__':
    b = [1,2,3,6,7,8,9,101]
    a = [2,4,5,9,100]
    print(merge(a,b))

2.2链表

2.2.1实现单链表、循环链表、双向链表,支持增删操作

class LNode:   # 定义节点类
    def __init__(self, elem, next_=None):
        self.elem = elem
        self.next = next_

class LList:   # 定义单链表类
    def __init__(self):
        self._head = None

    # 增,包括链表头、尾和中间位置三种方法
    def prepend(self, elem):
        self._head = LNode(elem)

    def append(self, elem):
        if not self._head:
            self._head = LNode(elem)
            return
        p = self._head
        while p.next:
            p = p.next
        p.next = LNode(elem)

    def insert(self, elem, key):
        tmp = LNode(elem)
        p = self._head
        for i in range(key-1):
            p = p.next
        tmp.next = p.next
        p.next = tmp

    # 删,也是三种方法
    def delete(self, key):
        # todo: key边界限制待添加
        p = self._head
        for i in range(key - 1):
            p = p.next
        p.next = p.next.next

    def print_all(self):
        p = self._head
        while p :
            print(p.elem, end='')
            if p.next:
                print('->', end='')
            p = p.next
        print('')

class CList:   # 定义循环链表类
    def __init__(self):
        self._head = LNode(None)
        self._head.next = self._head
        self._rear = self._head

    def insert(self, key, value):
        tmp = LNode(elem)
        p = self._head
        for i in range(key-1):
            p = p.next
        tmp.next = p.next
        p.next = tmp
        if tmp.next == self._head:
            self._rear = tmp

    def delete(self, key):
        # todo:key边界
        p = self._head
        for i in range(key-1):
            p = p.next
            if not p:
                print('WRONG POSITION!')
                return 
        tmp = p.next
        p.next = p.next.next
        del tmp
        if p.next ==self._head:
            self._rear = p
            

class DLNode(LNode):   # 定义双链表节点
    def __init__(self, elem, next_=None, prev=None):
        super(DLNode, self).__init__()
        self.prev = prev

if __name__ == '__main__':
    l = LList()
    for i in range(10):
        l.append(i)
    l.print_all()
    l.insert(50, 3)
    l.print_all()
    l.delete(10)
    l.print_all()

2.2.2实现单链表反转

class Solution(object):
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        prev = None
        cur = head
        while cur:
            nxt = cur.next
            cur.next = prev
            prev = cur
            cur = nxt
        return prev

2.2.3实现两个有序的链表合并为一个有序链表

class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution(object):
    def mergeTwoLists(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        l3 = ListNode(0)#空链表
        cur = l3
        while (l1 != None) & (l2!=None):
            if l1.val <= l2.val:
                cur.next = l1
                l1 = l1.next
            else:
                cur.next = l2
                l2 = l2.next
            cur = cur.next
        if l1 != None:
            cur.next = l1
        if l2 != None:
            cur.next = l2
        l3 = l3.next
        return l3

2.2.4实现求链表的中间结点

def find_middle_node(head):
    slow, fast = head, head
    while fast and fast.next:
        fast = fast.next.next
        slow = slow.next
    return slow

2.3LeetCode练习题

2.3.1求三数之和

class Solution:
    def threeSum(self, nums):
        nums.sort()
        ans = []
        left = 1
        right = len(nums)-1#首先设置左右指针
        cur = 0
        for i in range(0,len(nums)):
            if i==0 or nums[i]>nums[i-1]:
                if nums[i]<=0:#如果扫描到大于0的就停下
                    cur = i 
                    left =i+1#从当前位置下一个开始
                    right = len(nums)-1
                    while right>left:
                        sum = nums[cur]+nums[left]+nums[right]
                        if sum==0:#只有=0时才会出现重复情况
                            ans.append([nums[cur],nums[left],nums[right]])
                            left+=1
                            right-=1
                            while left<right and nums[left]==nums[left-1]:
                                left+=1
                            while left<right and nums[right]==nums[right+1]:
                                right-=1
                        elif sum>0:
                            right-=1
                        else:
                            left+=1
        return ans

if __name__ == '__main__':
    a = Solution()
    a.threeSum([0,0,0,0])

2.3.2求众数
方法一,最常规的方法,但是占用内存较多

class Solution(object):
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        order = list(set(nums))
        count = []
        length = len(nums)
        for i in order:
            a = 0
            for j in range(0,length):
                if nums[j] == i:
                    a+=1
            count.append(a)
        index = count.index(max(count))          
        return order[index]

##方法二,摩尔投票法,相同+1,不同-1,为0换数

class Solution(object):
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """     
        count= 0
        for num in nums:
            if count == 0:
                temp = num
            if num == temp:
                count += 1
            else:
                count -= 1
        return temp

3.参考链接

数组和链表参考:https://note.youdao.com/ynoteshare1/index.html?id=6b47b08c91b05db6c33fe92b88b53192&type=note#/
求三数之和:https://github.com/LauraWong233/Datawhale-datastructure-LinkedList/blob/master/threesum.py
求众数:https://github.com/LauraWong233/Datawhale-datastructure-LinkedList/blob/master/majorityElement.py

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值