【数据结构与算法】task1 数组&链表

https://github.com/datawhalechina/Programming

https://github.com/TheAlgorithms/Python

c++ https://github.com/wangzheng0822/algo/tree/master/c-cpp

python https://github.com/wangzheng0822/algo/tree/master/python

数组

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

参考:https://blog.csdn.net/u013109501/article/details/88020739

#通过python实现动态数组
 
"""
数组特点:
    占用一段连续的内存空间,支持随机(索引)访问,且时间复杂度为O(1)
    添加元素时间复杂度:O(n)
    删除元素时间复杂度:O(n)
"""
 
class Arr:
    def __init__(self, capacity=10):
        """
        构造函数
        :param capacity: 数组最大容量,不指定的话默认为10
        """
        self._capacity = capacity
        self._size = 0                                  # 数组有效元素的数目,初始化为0
        self._data = [None] * self._capacity    # 由于python的list是动态扩展的,而我们要实现底层具有固定容量、占用一段连续的内存空间的数组,所以用None来作为无效元素的标识
 
    def __getitem__(self, item):
        """让Arr类支持索引操作"""
        return self._data[item]
 
    def getSize(self):
        """返回数组有效元素的个数"""
        return self._size
 
    def getCapacity(self):
        """返回当前数组的容量"""
        return self._capacity
 
    def isEmpty(self):
        """判断当前数组是否为空"""
        return self._size == 0
 
    def add(self, index, elem):
        """
        向数组中添加一个元素,注意数组占用的是一段连续的内存空间,所以在添加元素后,数组还是要保证这个特点的,因此需要将后面的元素都向后挪一个位置,而且要注意要先从
        尾部开始挪,防止元素之间的覆盖
        时间复杂度:O(n)
        :param index:   添加的元素所在的索引
        :param elem:    所要添加的元素
        """
        if index < 0 or index > self._size:     # 插入的位置无效
            raise Exception('Add Filed. Require 0 <= index <= self._size')
        if self._size == self._capacity:        # 满了
            self._resize(self._capacity * 2)    # 默认扩容当前容量的二倍。容量翻倍要比容量加上一个固定值要好,这样做均摊复杂度为O(1)。具体请百度
 
        for i in range(self._size - 1, index - 1, -1):  # 从尾部开始挪动元素,在index处腾出一个空间
                                                        # 一定要注意在步长为负数的情况下,区间是左开右闭区间,即(index, self._size - 1],所以是index-1,与正常的左闭右开区间是相反的!
            self._data[i + 1] = self._data[i]
        self._data[index] = elem        # 将该位置赋值为elem
        self._size += 1                 # 数组有效元素数加1
 
    def addLast(self, elem):
        """
        向数组尾部添加元素
        时间复杂度:O(1)
        :param elem: 所要添加的元素
        """
        self.add(self._size, elem) # 直接调用add方法,注意不用再次判定合法性了,因为add函数中已经判断过了
 
    def addFirst(self, elem):
        """
        想数组头部添加元素
        时间复杂度:O(n)
        :param elem: 所要添加的元素
        """
        self.add(0, elem)   # 同理直接调用add方法
 
    def get(self, index):
        """
        获得索引index处的元素
        时间复杂度:O(1)
        :param index: 数组索引
        :return:      数组索引处的值
        """
        if index < 0 or index >= self._size:        # 判断index的合法性
            raise Exception('Get failed. Index is illegal.')
        return self._data[index]
 
    def getFirst(self):
        """
        获得数组首位置元素的值
        :return: 首位置元素的值
        """
        return self.get(0)      # 直接调用get函数,安全可靠
 
    def getLast(self):
        """
        获得数组末尾元素的值
        :return: 末尾元素的值
        """
        return self.get(self._size - 1)  # 直接调用get函数,安全可靠
 
    def set(self, index, elem):
        """
        将索引为index的元素的值设为elem
        时间复杂度:O(1)
        :param index:  索引
        :param elem:   新的值
        """
        if index < 0 or index >= self._size:        # 判断index的合法性
            raise Exception('Sat failed. Index is illegal.')
        self._data[index] = elem
 
    def contains(self, elem):
        """
        查看数组中是否存在元素elem,最好不要传入一个浮点数,你懂得。。
        时间复杂度:O(n)
        :param elem: 目标元素
        :return:     bool值,存在为真
        """
        for i in range(self._size):        # 遍历
            if self._data[i] == elem:
                return True                # 找到了就返回True
        return False                       # 遍历完了还没找到,就返回False
 
    def find(self, elem):
        """
        在数组中查找元素,并返回元素所在的索引。(如果数组中存在多个elem,只返回最左边elem的索引)
        时间复杂度:O(n)
        :param elem: 目标元素
        :return:     元素所在的索引,没找到则返回-1(无效值)
        """
        for i in range(self._size):         # 遍历数组
            if self._data[i] == elem:
                return i                    # 找到就返回索引
        return -1                           # 没找到返回-1
 
    def findAll(self, elem):
        """
        找到值为elem全部元素的索引
        :param elem: 目标元素
        :return:     一个列表,值为全部elem的索引
        """
        ret_list = Arr()                # 建立一个新的数组用于存储索引值
        for i in range(self._size):     # 遍历数组
            if self._data[i] == elem:
                ret_list.addLast(i)     # 找到就将索引添加进ret_list
        return ret_list
 
    def remove(self, index):
        """
        删除索引为index的元素。index后面的元素都要向前移动一个位置
        时间复杂度:O(n)
        :param index: 目标索引
        :return:      位于该索引的元素的值
        """
        if index < 0 or index >= self._size:    # index合法性检查
            raise Exception('Remove failed.Require 0 <= index < self._size')
        ret = self._data[index]                 # 拷贝一下index处的元素,便于返回
        for i in range(index + 1, self._size):  # index后面的元素都向前挪一个位置
            self._data[i - 1] = self._data[i]
        self._size -= 1         # 维护self._size
        self._data[self._size] = None   # 最后一个元素的垃圾回收
 
        if self._size and self._capacity // self._size == 4:   # 如果当前有效元素为总容量的四分之一且还存在有效元素,则将容量缩减为原来的一半
            self._resize(self._capacity // 2)
        return ret
 
    def removeFirst(self):
        """
        删除数组首位置的元素
        时间复杂度:O(n)
        :return: 数组首位置的元素
        """
        return self.remove(0)   # 调用remove函数
 
    def removeLast(self):
        """
        删除数组末尾的元素
        时间复杂度:O(1)
        :return: 数组末尾的元素
        """
        return self.remove(self._size - 1)      # 调用remove函数
 
    def removeElement(self, elem):
        """
        删除数组中为elem的元素,如果数组中不存在elem,那么什么都不做。如果存在多个相同的elem,只删除最左边的那个
        时间复杂度:O(n)
        :param elem: 要删除的目标元素
        """
        index = self.find(elem)         # 尝试找到目标元素(最左边的)的索引
        if index != -1:                 # elem在数组中就删除,否则什么都不做
            self.remove(index)          # 调用remove函数
 
    def removeAllElement(self, elem):
        """
        删除数组内所有值为elem的元素,可以用递归来写,这里用的迭代的方法。elem不存在就什么都不做
        :param elem: 要删除的目标元素
        """
        while True:
            index = self.find(elem)     # 循环来找elem,如果还存在就继续删除
            if index != -1:             # 若存在
                self.remove(index)
            else:
                break
 
    def get_Max_index(self):
        """
        获取数组中的最大元素的索引,返回最大元素的索引值,如果有多个最大值,默认返回最左边那个的索引
        时间复杂度:O(n)
        :return: 最大元素的索引
        """
        if self.isEmpty():
            raise Exception('Error, array is Empty!')
        max_elem_index = 0    # 记录最大值的索引,初始化为0 
        for i in range(1, self.getSize()):   # 从索引1开始遍历,一直到数组尾部
            if self._data[i] > self._data[max_elem_index]:   # 如果当前索引的值大于最大值索引处元素的值
                max_elem_index = i     # 更新max_elem_index,这样它还是当前最大值的索引
        return max_elem_index     # 遍历完后,将数组的最大值的索引返回
 
    def removeMax(self):
        """
        删除数组中的最大元素,返回最大元素的值,如果有多个最大值,默认值删除最左边那个
        时间复杂度:O(n)
        :return: 最大元素
        """
        return self.remove(self.get_Max_index())   # 直接调用remove函数删除最大值
 
    def get_Min_index(self):
        """
        获取数组中的最小元素的索引,返回最小元素的索引值,如果有多个最小值,默认返回最左边那个的索引
        时间复杂度:O(n)
        :return: 最小元素的索引
        """
        if self.isEmpty():
            raise Exception('Error, array is Empty!')
        min_elem_index = 0    # 记录最小值的索引,初始化为0 
        for i in range(1, self.getSize()):   # 从索引1开始遍历,一直到数组尾部
            if self._data[i] < self._data[min_elem_index]:   # 如果当前索引的值小于最小值索引处元素的值
                min_elem_index = i     # 更新min_elem_index,这样它还是当前最小值的索引
        return min_elem_index     # 遍历完后,将数组的最小值的索引返回
 
    def removeMin(self):
        """
        删除数组中的最小元素,返回最小元素的值,如果有多个最小值,默认值删除最左边那个
        时间复杂度:O(2n),可以看成是O(n)的
        :return: 最小元素
        """
        return self.remove(self.get_Min_index())
 
    def swap(self, index1, index2):
        """
        交换分别位于索引index1和索引index2处的元素
        :param index1: 索引1
        :param index2: 索引2
        """ 
        if index1 < 0 or index2 < 0 or index1 >= self._size or index2 >= self._size:        # 合法性检查
            raise Exception('Index is illegal')
        self._data[index1], self._data[index2] = self._data[index2], self._data[index1]     # 交换元素
 
    def printArr(self):
        """对数组元素进行打印"""
        for i in range(self._size):
            print(self._data[i], end='  ')
        print('\nSize: %d-----Capacity: %d' % (self.getSize(), self.getCapacity()))
 
    # private
    def _resize(self, new_capacity):
        """
        数组容量放缩至new_capacity,私有成员函数
        :param new_capacity: 新的容量
        """
        new_arr = Arr(new_capacity)         # 建立一个新的数组new_arr,容量为new_capacity
        for i in range(self._size):
            new_arr.addLast(self._data[i])  # 将当前数组的元素按当前顺序全部移动到new_arr中
        self._capacity = new_capacity       # 数组容量变为new_capacity
        self._data = new_arr._data          # 将new_arr._data赋值给self._data,从而完成数组的容量放缩操作

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

参考:https://github.com/wangzheng0822/algo/blob/master/python/05_array/myarray.py

class MyArray:
    """A simple wrapper around List.
    You cannot have -1 in the array.
    """

    def __init__(self, capacity: int):
        self._data = []
        self._capacity = capacity

    def __getitem__(self, position: int) -> object:
        return self._data[position]

    def __setitem__(self, index: int, value: object):
        self._data[index] = value

    def __len__(self) -> int:
        return len(self._data)

    def __iter__(self):
        for item in self._data:
            yield item

    def find(self, index: int) -> object:
        try:
            return self._data[index]
        except IndexError:
            return None

    def delete(self, index: int) -> bool:
        try:
            self._data.pop(index)
            return True
        except IndexError:
            return False

    def insert(self, index: int, value: int) -> bool:
        if len(self) >= self._capacity:
            return False
        else:
            return self._data.insert(index, value)

    def print_all(self):
        for item in self:
            print(item)


def test_myarray():
    array = MyArray(5)
    array.insert(0, 3)
    array.insert(0, 4)
    array.insert(1, 5)
    array.insert(3, 9)
    array.insert(3, 10)
    assert array.insert(0, 100) is False
    assert len(array) == 5
    assert array.find(1) == 5
    assert array.delete(4) is True
    array.print_all()


if __name__ == "__main__":
    test_myarray()

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

参考:https://www.cnblogs.com/LanTianYou/p/8976671.html

def merge_sort(a, b):
    ret = []
    i = j = 0
    while len(a) >= i + 1 and len(b) >= j + 1:
        if a[i] <= b[j]:
            ret.append(a[i])
            i += 1
        else:
            ret.append(b[j])
            j += 1
    if len(a) > i:
        ret += a[i:]
    if len(b) > j:
        ret += b[j:]
    return ret

if __name__ == '__main__':
    a = [1,3,4,6,7,78,97,190]
    b = [2,5,6,8,10,12,14,16,18]
    print(merge_sort(a, b))

 

15. 三数之和(中等)

https://leetcode-cn.com/problems/3sum/

题目

答案

思路:

先对数组进行排序,如果是计算两个元素的和,则分别设置头和尾两个指针,向中间靠拢。

如果是计算两个元素的和,则只需要先对第一个数进行循环取值下标i,剩下的两个指针分别指向i+1和数组的最后一个元素,这样的复杂度是 排序O(nlogn) + 查找O(n^2) = O(n^2)。

class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        nums.sort()
        result = []
        lenn = len(nums)
        for i in range(lenn-2):
            if i > 0 and nums[i] == nums[i-1]:
                continue
            l, r = i+1, lenn - 1 
            while l < r:
                s = nums[i] + nums[l] + nums[r]
                if  s < 0:
                    l += 1    
                elif s > 0:
                    r -= 1
                else:
                    result.append([nums[i], nums[l], nums[r]])
                    while l < r and nums[l] == nums[l+1]:
                        l += 1
                    while l < r and nums[r] == nums[r-1]:
                        r -= 1
                    l, r = l+1, r-1
        return result

169. 求众数(简单)

https://leetcode-cn.com/problems/majority-element/

题目

答案

思路1:set使元素唯一,然后统计元素的出现次数

class Solution(object):
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        res=set(nums)
        n=len(nums)/2
        for item in res:
            if(nums.count(item)>n):
                return item

思路2:排序后位于中间位置的数字

class Solution(object):
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        return sorted(nums)[len(nums)//2]

41. 缺失的第一个正数(困难)

https://leetcode-cn.com/problems/first-missing-positive/

题目

答案

思路:

题目要求时间复杂度为O(n),空间复杂度为O(1)。可以采用类似于桶排序的思想进行求解。

  1. 首先把数组内,范围在 ( 0, n ] 元素x,放到nums[x - 1],类似桶排序中的找位置;
  2. 放好之后,进行遍历,找第一个 i + 1 != nums[i],返回 i + 1,就是结果,如果没有就返回 n + 1。
class Solution:
    def firstMissingPositive(self, nums):
 
        n, i = len(nums), 0
        if n == 0: 
        	return 1

        while i < n:
            w = nums[i] - 1  # 获取当前位置的数据,减去1是为了得到 在list要插入的位置
            if 0 < nums[i] <= n and nums[i] != nums[w]:  # 0 < nums[i] <= n 判断是否出界
                nums[i], nums[w] = nums[w], nums[i]       # nums[i] != nums[w] 如果相等或者是本身就没必要替换了,避免死循环
            else:
                i += 1  # 当前位置上的数,没有找到合适的位置,进行下一个位置
 
        for i in range(n):  # 遍历返回
            if i + 1 != nums[i]:
                return i + 1
        return n + 1

if __name__ == '__main__':
    nums = [7, 8, 9, 11, 12]
    solu = Solution()
    print(solu.firstMissingPositive(nums))

参考

https://blog.csdn.net/xx_123_1_rj/article/details/80840451

https://blog.csdn.net/Jaster_wisdom/article/details/80660467

链表

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

参考:https://blog.csdn.net/Daputao_net/article/details/81589675

单链表

class Node(object):
    """定义一个节点"""
    def __init__(self, elem):
        self.elem = elem
        self.next = None
 
 
class SingleLinkList(object):
    """单链表"""
    def __init__(self, node=None):
        # 因为不需要让用户知道我的头结点在哪里所以head定义为私有的属性。
        self.__head = node
 
    def is_empty(self):
        """链表是否为空"""
        return self.__head is None
 
    def length(self):
        """链表的长度"""
        # cur游标,用来移动遍历节点
        cur = self.__head
        # count记录数量
        count = 0
        while cur != None:
            count += 1
            cur = cur.next
        return count
 
    def travel(self):
        """遍历整个链表"""
        cur = self.__head
        while cur != None:
            print(cur.elem, end=" ")
            cur = cur.next
        print("")
 
    def add(self, item):
        """链表头部添加元素"""
        node = Node(item)
        node.next = self.__head
        self.__head = node
 
    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
 
    # pos/position:位置,方位 param:参数
    def insert(self, pos, item):
        """指定位置添加元素
        :param pos 从0开始(即将链表的第一个节点记为0节点)"""
        # pre/previous以前的,在什么之前
        if pos <= 0:
            self.add(item)
        elif pos > (self.length()-1):
            self.append(item)
        else:
            node = Node(item)
            pre = self.__head
            count = 0
            while count < (pos-1):
                count += 1
                pre = pre.next
            node.next = pre.next
            pre.next = node
 
    def remove(self, item):
        """删除节点"""
        pre = self.__head
 
        # 判断是不是空链表
        if pre == None:
            return False
        # 判断是不是头结点,包含了只有一个节点情况
        elif pre.elem == item:
            self.__head = pre.next
            # pre = None
            return True
        else:
            while pre.next != None:
                if pre.next.elem == item:
                    pre.next = pre.next.next
                    return True
                else:
                    pre = pre.next
            return False
        # 也可以使用这种方法
        # cur = self.__head
        # pre = None
        # while cur != None:
        #     if cur.elem == item:
        #         # 先判断此结点是否是头节点
        #         # 头节点
        #         if cur == self.__head:
        #             self.__head = cur.next
        #         else:
        #             pre.next = cur.next
        #         break
        #     else:
        #         pre = cur
        #         cur = cur.next
 
    def search(self, item):
        """查找节点是否存在"""
        cur = self.__head
 
        while cur != None:
            if cur.elem == item:
                return True
            else:
                cur = cur.next
        return False
 
 
if __name__ == '__main__':
    sll = SingleLinkList()
 
    print(sll.remove(4))
    sll.travel()
    print("----------")
    sll.append(2)
    print(sll.search(2))
    print(sll.remove(2))
    print("----------")
    sll.append(2)
    sll.append(3)
    sll.append(5)
    sll.append(6)
    sll.append(7)
    sll.travel()
    sll.add(1)
    sll.travel()
    sll.insert(3, 4)
    sll.travel()
    sll.remove(1)
    sll.travel()
    sll.remove(7)
    sll.travel()
    sll.remove(4)
    sll.travel()
    print(sll.remove(100))
    sll.travel()
    print(sll.search(6))

单向循环链表

class Node(object):
    """定义一个节点"""
    def __init__(self, elem):
        self.elem = elem
        self.next = None
 
 
class SingleLinkList(object):
    """单向循环链表"""
    def __init__(self, node=None):
        # 因为不需要让用户知道我的头结点在哪里所以head定义为私有的属性。
        self.__head = node
        if node != None:
            node.next = node
 
    def is_empty(self):
        """链表是否为空"""
        return self.__head is None
 
    def length(self):
        """链表的长度"""
        if self.is_empty():
            return 0
        # cur游标,用来移动遍历节点
        cur = self.__head
        # count记录数量,因为循环不会进入最后一个节点所以初始值为1
        count = 1
        while cur.next != self.__head:
            count += 1
            cur = cur.next
        return count
 
    def travel(self):
        """遍历整个链表"""
        cur = self.__head
        if cur == None:
            return
        else:
            while cur.next != self.__head:
                print(cur.elem, end=" ")
                cur = cur.next
            # 退出循环后cur指向尾节点,但是尾节点没有打印。
            print(cur.elem)
 
    def add(self, item):
        """链表头部添加元素"""
        node = Node(item)
        if self.is_empty():
            self.__head = node
            node.next = self.__head
            # 或者
            # self.__head = node
            # node.next = node
        else:
            cur = self.__head
            while cur.next != self.__head:
                cur = cur.next
            # 循环结束后cur指向尾节点
            node.next = self.__head
            self.__head = node
            cur.next = node
 
    def append(self, item):
        """链表尾部添加元素"""
        node = Node(item)
        if self.is_empty():
            self.__head = node
            node.next = node
        else:
            cur = self.__head
            while cur.next != self.__head:
                cur = cur.next
            # 循环结束cur指向最后一个节点
            cur.next = node
            node.next = self.__head
 
    # pos/position:位置,方位 param:参数
    def insert(self, pos, item):
        """指定位置添加元素
        :param pos 从0开始(即将链表的第一个节点记为0节点)"""
        # pre/previous以前的,在什么之前
        if pos <= 0:
            self.add(item)
        elif pos > (self.length()-1):
            self.append(item)
        else:
            node = Node(item)
            pre = self.__head
            count = 0
            while count < (pos-1):
                count += 1
                pre = pre.next
            node.next = pre.next
            pre.next = node
 
    def remove(self, item):
        """删除节点"""
        pre = self.__head
        cur = self.__head
        # 判断是不是空链表
        if cur == None:
            return False
        # 判断是不是头结点
        elif cur.elem == item:
            # 判断是不是只有一个节点
            if cur.next == self.__head:
                self.__head = None
                return True
            else:
                while pre.next != self.__head:
                    pre = pre.next
                self.__head = cur.next
                pre.next = self.__head
                return True
        else:
            while pre.next != self.__head:
                if pre.next.elem == item:
                    pre.next = pre.next.next
                    return True
                else:
                    pre = pre.next
            return False
 
    def search(self, item):
        """查找节点是否存在"""
 
        cur = self.__head
        # 判断是否为空链表
        if self.__head == None:
            return False
        # 判断是不是头结点
        elif cur.elem == item:
            return True
        else:
            while cur.next != self.__head:
                if cur.elem == item:
                    return True
                else:
                    cur = cur.next
            # 循环退出后cur指向最后一个节点,但是没有进入最后一个节点
            if cur.elem == item:
                return True
        return False
 
 
if __name__ == '__main__':
    sll = SingleLinkList()
    print(sll.remove(4))
    sll.travel()
    print("----------")
    sll.append(2)
    print(sll.search(2))
    print(sll.remove(2))
    print("----------")
    sll.append(2)
    sll.append(3)
    sll.append(5)
    sll.append(6)
    sll.append(7)
    sll.travel()
    sll.add(1)
    sll.travel()
    sll.insert(3, 4)
    sll.travel()
    sll.remove(1)
    sll.travel()
    sll.remove(7)
    sll.travel()
    sll.remove(4)
    sll.travel()
    print(sll.remove(100))
    sll.travel()
    print(sll.search(6))

双向链表

class Node(object):
    """节点"""
 
    def __init__(self, item):
        self.elem = item
        self.next = None
        self.prev = None
 
 
class DoubleLinkList(object):
    """双向链表"""
 
    def __init__(self, node=None):
        self.__head = node
 
    def is_empty(self):
        """链表是否为空"""
        return self.__head is None
 
    def length(self):
        """链表长度"""
        # cur游标,用来移动遍历节点
        cur = self.__head
        # counter:记录数量
        counter = 0
        while cur != None:
            counter += 1
            cur = cur.next
        return counter
 
    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
            node.prev = cur
 
    def add(self, item):
        """链表头部添加节点,头插法"""
        node = Node(item)
        node.next = self.__head
        self.__head = node
        node.next.prev = node
 
    def insert(self, pos, item):
        """任意位置添加节点"""
        # pos的初始值为0
        if pos <= 0:
            self.add()
        elif pos > (self.length()-1):
            self.append()
        else:
            cur = self.__head
            counter = 0
            while counter != pos:
                counter += 1
                cur = cur.next
            node = Node(item)
            node.prev = cur.prev
            cur.prev.next = node
            node.next = cur
            cur.prev = node
 
    def travel(self):
        """遍历整个链表"""
        cur = self.__head
        while cur != None:
            print(cur.elem, end=" ")
            cur = cur.next
        print("")
 
    def remove(self, item):
        """根据元素删除节点"""
        cur = self.__head
        while cur != None:
            if cur.elem == item:
                # 先判断此结点是否是头节点
                # 头节点
                if cur == self.__head:
                    self.__head = cur.next
                    if cur.next != None:
                    # 链表不只有一个节点
                        cur.next.prev = None
                else:
                    cur.prev.next = cur.next
                    if cur.next != None:
                        cur.next.prev = cur.prev
                return True
            else:
                cur = cur.next
        return False
 
    def search(self, item):
        """根据元素查找节点是否存在"""
        cur = self.__head
        while cur != None:
            if cur.elem == item:
                return True
            else:
                cur = cur.next
        return False
 
 
if __name__ == '__main__':
    dll = DoubleLinkList()
 
    print(dll.remove(4))
    dll.travel()
    print("----------")
    dll.append(2)
    print(dll.search(2))
    print(dll.remove(2))
    print("----------")
    dll.append(2)
    dll.append(3)
    dll.append(5)
    dll.append(6)
    dll.append(7)
    dll.travel()
    dll.add(1)
    dll.travel()
    dll.insert(3, 4)
    dll.travel()
    dll.remove(1)
    dll.travel()
    dll.remove(7)
    dll.travel()
    dll.remove(4)
    dll.travel()
    print(dll.remove(100))
    dll.travel()

实现单链表反转

参考:https://blog.csdn.net/su_bao/article/details/81072849

https://blog.csdn.net/The__Apollo/article/details/78769400

class Node(object):
    def __init__(self, data, next=None):
        self.val = data
        self.next = next
 
def fun4(head):
    if head == None:
        return None
    L,M,R = None,None,head
    while R.next != None:
        L = M
        M = R
        R = R.next
        M.next = L
    R.next = M
    return R
#测试用例
if __name__ == '__main__':
    l1 = Node(3)
    l1.next = Node(2)
    l1.next.next = Node(1)
    l1.next.next.next = Node(9)
    l = fun4(l1)
    print (l.val, l.next.val, l.next.next.val, l.next.next.next.val)

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

参考leetcode-023

实现求链表的中间结点

方法1

参考:https://blog.csdn.net/qq_27060423/article/details/82891248

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
 
class Solution:
    def middleNode(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        p=head
        count=0
        while p:
            count+=1
            p=p.next
        i=0
        p=head
        while i<count//2:
            p=p.next
            i+=1
        return p

方法2

参考:https://blog.csdn.net/weixin_41722370/article/details/83314501

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
import math
class Solution:
    def middleNode(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        # 首先要知道链表一共有多少个结点
        count = 0
        res = {}
        while head != None:
            count += 1
            res[count] = head
            head = head.next
        #j = math.ceil(count/2)
        #if count % 2 == 0:
        #    return res[j+1]
        #else:
        #    return res[j]
        j = math.ceil((count-1)/2) + 1
        return res[j]

141. 环形链表

https://leetcode-cn.com/problems/linked-list-cycle/

题目

答案

思路:

设置两个指针slow和fast,一个步长为1,一个步长为2进行遍历。如果有环,则slow和fast总会在某一点相遇。如果没有环,则fas或者fast.next会先为空。

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

class Solution(object):
    def hasCycle(self, head):
        """
        :type head: ListNode
        :rtype: bool
        """
        fast = slow = head #fast每次跑2步,slow每次跑1步
        while fast and fast.next: #判断跑得快的是否为空
            fast = fast.next.next
            slow = slow.next
            if slow == fast: #存在环则必然会出现相等
                return True
        return False

参考

https://blog.csdn.net/qq_34364995/article/details/80518191

23. 合并K个排序链表

https://leetcode-cn.com/problems/merge-k-sorted-lists/

题目

答案

思路:

先将所有列表按照第一个元素的大小放入小根堆中,然后每次取回最小的元素的列表,将该列表下一个元素放入小根堆中。直到小根堆为空。这样就得到了排好序的一个列表。小根堆构建的复杂度为O(NlogN),每次取最小值的复杂度为O(logN),向小根堆添加元素的复杂度为O(logN)。所有总的实现复杂度为O(NlogN)。 

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

class Solution(object):
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        heap = []
        for l in lists:
            if l != None:
                heap.append((l.val,l))
        heapq.heapify(heap) #调整a,使得其满足最小堆
        dummy = ListNode(0)
        cur = dummy
        while heap:
            _,h = heapq.heappop(heap) #从最小堆中弹出最小的元素 
            cur.next = h
            cur = cur.next
            if h.next:
                heapq.heappush(heap,(h.next.val,h.next)) #向最小堆中压入新的元素
        return dummy.next

参考

https://blog.csdn.net/qian2729/article/details/50528385

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值