排序与检索--Leetcode(python)

基于比较的内部排序算法复杂度

https://blog.csdn.net/weixin_41571493/article/details/81875088
在这里插入图片描述
时间复杂度的下界是o(nlogn)证明:
对于n个待排序元素,在未比较时,可能的正确结果有n!种。在经过一次比较后,其中两个元素的顺序被确定,所以可能的正确结果剩余n!/2种。依次类推,直到经过m次比较,剩余可能性 n ! / ( 2 m ) n!/(2^m) n!/(2m)种。直到 n ! / ( 2 m ) < = 1 n!/(2^m)<=1 n!/(2m)<=1时,结果只剩余一种。此时的比较次数m为o(nlogn)次。所以基于排序的比较算法,最优情况下,复杂度是o(nlogn)的。

搜索二维矩阵 II

编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target。该矩阵具有以下特性:

每行的元素从左到右升序排列。
每列的元素从上到下升序排列。
示例:

现有矩阵 matrix 如下:

[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
给定 target = 5,返回 true。

给定 target = 20,返回 false。

解法:为了节省比较的次数,可以和左下角位置的数字进行比较。如果tmp>target,说明最后一行可以不用比较了;如果tmp<target,则第一列不需要再比较了

class Solution(object):
    def searchMatrix(self, matrix, target):
        """
        :type matrix: List[List[int]]
        :type target: int
        :rtype: bool
        """
        if matrix == []:
            return False
        
        a = len(matrix) - 1
        b = len(matrix[0])
        
        i = 0
        while a >= 0 and i < b:
            tmp = matrix[a][i]
            if tmp == target:
                return True
            elif tmp > target:
                a -= 1
            else:
                i += 1
                
        return False
            

最大数

给定一组非负整数,重新排列它们的顺序使之组成一个最大的整数。

示例 1:

输入: [10,2]
输出: 210
示例 2:

输入: [3,30,34,5,9]
输出: 9534330
说明: 输出结果可能非常大,所以你需要返回一个字符串而不是整数。

解法
其实就是写一个排序方法,判断两个字符串的大小。两个字符串数字a,b,
若a+b<b+a,则a<b,即b排在a的前面更大。
记一下map,sorted,lambda的用法。

class Solution(object):
    def largestNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: str
        """
        
        if not nums:
            return ""
        
        # nums = [str(x) for x in nums]
        nums = sorted(list(map(str, nums)), cmp = lambda x, y: cmp(x+y, y+x), reverse = True)
        if nums[0] == '0':
            return '0'
        else:
            return ''.join(nums)

摆动排序 II

给定一个无序的数组 nums,将它重新排列成 nums[0] < nums[1] > nums[2] < nums[3]… 的顺序。

示例 1:

输入: nums = [1, 5, 1, 1, 6, 4]
输出: 一个可能的答案是 [1, 4, 1, 5, 1, 6]
示例 2:

输入: nums = [1, 3, 2, 2, 3, 1]
输出: 一个可能的答案是 [2, 3, 1, 3, 1, 2]
说明:
你可以假设所有输入都会得到有效的结果。

进阶:
你能用 O(n) 时间复杂度和 / 或原地 O(1) 额外空间来实现吗?

解法
想到对数组从小到大排序,然后从左到右间隔排序,就像示例1一样,奇数位置是前半排序,偶数位置是后半排序。但是由于排序会出现中间好几个数相同的情况,比如[4, 5, 5, 6],按照这个方法得到的结果还是[4, 5, 5, 6],所以可以在赋值的时候,倒着赋值,即按照从大到小的顺序。
看了网上的答案,发现思想相同,但是代码简洁的多,特别是求中间位置的时候直接用len(nums[::2]),以及赋值的时候不需要循环。

class Solution(object):
    def wiggleSort(self, nums):
        """
        :type nums: List[int]
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        tmp = sorted(nums, reverse=False)
        mid = len(tmp) / 2 if len(tmp) % 2 == 0 else len(tmp) / 2 + 1
        #print(mid, tmp)
        i = 0
        j = mid - 1
        k = len(nums) - 1
        while i < len(nums):
            nums[i] = tmp[j]
            i += 1
            if i < len(nums):
                nums[i] = tmp[k]
                i += 1
                j -= 1
                k -= 1
        
class Solution(object):
    def wiggleSort(self, nums):

        nums.sort()
        half = len(nums[::2])
        nums[::2], nums[1::2] = nums[:half][::-1], nums[half:][::-1]

寻找峰值

峰值元素是指其值大于左右相邻值的元素。

给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引。

数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位置即可。

你可以假设 nums[-1] = nums[n] = -∞。

示例 1:

输入: nums = [1,2,3,1]
输出: 2
解释: 3 是峰值元素,你的函数应该返回其索引 2。
示例 2:

输入: nums = [1,2,1,3,5,6,4]
输出: 1 或 5
解释: 你的函数可以返回索引 1,其峰值元素为 2;
或者返回索引 5, 其峰值元素为 6。
说明:

你的解法应该是 O(logN) 时间复杂度的。

解法
因为时间复杂度是O(logN)的,所以不能直接遍历,logN可以想到二分法。注意数组的0和len-1位置也是有可能的峰值。
此时我们应该考虑nums[k]和nums[k+1]的关系。如果我们nums[k]>nums[k+1],我们应该让j=k,因为k很可能就是峰值(因为右边小,而左边存在-inf)。而如果nums[k]<nums[k+1],我们应该让i=k+1,因为k+1可能是峰值(同理)。对于nums[k]==nums[k+1]的情况,我们放到第二种情况了考虑就可以了。

class Solution(object):
    def findPeakElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        
        l = 0
        r = len(nums) -1
        while l < r:
            mid = (l + r) // 2
            
            if nums[mid] <= nums[mid + 1]:
                l = mid + 1
            else:
                r = mid
                
        return l
        

寻找重复数

给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。

示例 1:

输入: [1,3,4,2,2]
输出: 2
示例 2:

输入: [3,1,3,4,2]
输出: 3

说明:

  1. 不能更改原数组(假设数组是只读的)。
  2. 只能使用额外的 O(1) 的空间。
  3. 时间复杂度小于 O(n2) 。
  4. 数组中只有一个重复的数字,但它可能不止重复出现一次。

解法
参考二分法解法
快慢指针的方法

二分法代码:

class Solution(object):
    def findDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        l, r = 0, len(nums) - 1
        
        while l < r:
            mid = (l + r) // 2
            
            cnt = 0
            for x in nums:
                if x <= mid:
                    cnt += 1
                    
            if
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值