【算法】排序汇总(leetcode)

88. 合并两个有序数组

题目描述:给定两个按非递减顺序排列的整数数组nums1和nums2,另有两个整数m,n,分别表示nums1和nums2中的元素数目。
请合并nums2到nums1中,使合并后的数组同样按非递减顺序排列。
注:最终函数不返回合并后的数组,而是存储在数组nums1中。为了应对这种情况,nums1输入时,它的初始长度为m+n,其中前m项是nums1中的有效元素,后n个元素为0。例如,nums1=[1,2,3,0,0,0],nums2=[1,2,3];nums1=[4,5,6,7,0,0,0],nums2=[1,2,3]。

1. 直接调用系统函数来进行排序

class Solution(object):
    def merge(self, nums1, m, nums2, n):
        """
        :type nums1: List[int]
        :type m: int
        :type nums2: List[int]
        :type n: int
        :rtype: None Do not return anything, modify nums1 in-place instead.
        """
        nums1[m:] = nums2
        nums1.sort()

2. 双指针

 1)正序比较:
        因为有两个数组,所以我们可以定义两个指针,分别指向两个数组中的元素。最容易想到的就是从左到右(正序)依次比较,将较小元素放到前面。
        注意,这里应该利用temp数组来存储数据,因为直接存放在nums1中的话,有可能会丢失数据,比如:nums1=[3,1,2,0,0],num2=[1,2],当p1=0,p2=0,因为nums1[p1] > nums2[p2],所以我们应该把nums2[p2]换到nums1[p1]处,这样nums1=[1,1,2,0,0],这样元素“3”就被覆盖了。所以需要一个另外的数组来存储数据,这样就增加了额外的存储空间。

class Solution(object):
    def merge(self, nums1, m, nums2, n):
        """
        :type nums1: List[int]
        :type m: int
        :type nums2: List[int]
        :type n: int
        :rtype: None Do not return anything, modify nums1 in-place instead.
        """
        sorted = []
        p1, p2 = 0, 0
        while p1 < m or p2 < n:
            if p1 == m: #p1结束了nums1的遍历
                sorted.append(nums2[p2])
                p2 += 1
            elif p2 == n: #p2结束了nums2的便利
                sorted.append(nums1[p1])
                p1 += 1
            elif nums1[p1] < nums2[p2]:
                sorted.append(nums1[p1])
                p1 += 1
            else:
                sorted.append(nums2[p2])
                p2 += 1
        nums1[:] = sorted

2)逆序比较
        因为nums1数组后面是“0”,所以如果从后面开始比较(nums1从最后一个有效元素开始),较大的数可以直接覆盖“0”放到nums1数组的后面。
        注意,这里的两个数组都是已经按非递减顺序排列好了的。

class Solution(object):
    def merge(self, nums1, m, nums2, n):
        """
        :type nums1: List[int]
        :type m: int
        :type nums2: List[int]
        :type n: int
        :rtype: None Do not return anything, modify nums1 in-place instead.
        """
        p1, p2 = m-1, n-1
        tail = m+n-1 #tail = len(nums1)-1
        while p2>=0:
            if p1 < 0 or nums1[p1] < nums2[p2]:
                nums1[tail] = nums2[p2]
                tail -= 1
                p2 -= 1
            else:
                nums1[tail] = nums1[p1]
                tail -= 1
                p1 -= 1

169.多数元素

题目描述:给定一个大小为n的数组,找到其中的多数元素(数组中出现次数大于n/2的元素)。假设数组非空,且给定的数组总存在多数元素。
进阶:尝试设计时间复杂度为n,空间复杂度为1的算法解决此问题。

1. 简单思路(不满足时间复杂度和空间复杂度)
首先对数组进行排序,目的是为了让相同元素排在一起。主要思想是记录下原数组中各个不同元素第一次出现的索引位置index,然后计算相邻不同元素之间的距离,是否超过n/2,来判断该元素是否为多数元素。不过执行结果超出了时间限制,说明这种方法不太高效。

class Solution(object):
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        l = len(nums)
        nums.sort()  #首先对数组进行排序,重复的元素放在一起
        count = [0]
        p = 1   #p是指针,从nums第二个元素开始
        while p < l:    #存储不同元素出现的第一个索引值
              if nums[p] != nums[p-1]:
                  count.append(p)
        count.append(l-1)   #将nums最后一个元素的索引值也存储进来
        for i in range(l-1):
            if count[i+1]-count[i] >= len(nums)/2:
                break
        return nums[count[i]]

2. 秒杀方法
既然多数元素出现的次数大于n/2,说明数组中间的元素一定是多数元素。(突然感觉自己像个傻x)

class Solution(object):
    def majorityElement(self, nums):
        nums.sort()
        return nums[len(nums)//2]

 3. Moore摩尔投票算法
这里存在两个重要因素,一个是candidate,一个是count。首先选取一个candidate,然后用count记录candidate出现的次数,如果当前元素是candidate,count加一,反之count则减一。当count为0时,就把candidate设为当前数并继续操作。
该算法满足时间复杂度n,空间复杂度1

nums775751575577777
candidate7557
count121210101210123
class Solution(object):
    def majorityElement(self, nums):
        count = 0
        candidate = None

        n = len(nums)
        for i in range(n):
            if count == 0:
                candidate = nums[i]
            count += (1 if candidate == nums[i] else -1)

        return candidate

4. 字典方法(不满足空间复杂度1)
利用字典存储每个num,统计每个num出现的次数,返回出现次数最多的num

class Solution(object):
    def majorityElement(self, nums):
        dic = defaultdict(int)
        #统计每个数字出现的次数
        for num in nums:
            dic[num] += 1
        #返回出现次数最多的num, 即返回字典中最大value对应的key
        return max(dic, key=dic.get)

217. 存在重复元素

题目描述:给定一个整数数组,判断是否存在重复元素。如果存在一值在数组中出现至少两次,函数返回true。如果数组中每个元素都不相同,则返回false。

1. 秒杀法——(48ms, 20.7MB)
把列表转换成集合,用来去重,比较两者的长度,如果有重复元素,则新的长度会比旧的短。缺点就是占用内存空间比较大。

class Solution(object):
    def containsDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        l1 = len(nums)
        nums2 = set(nums)
        l2 = len(nums2)
        if l1 == l2:
            return False
        else:
            return True

2. 哈希表
暂时先不展开写,可以参考这里

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值